C++ Opencv实现录制九宫格视频
作者:白木木木木 发布时间:2023-08-16 04:11:28
标签:C++,Opencv,九宫格,视频
在项目开始之前,我的环境已配置完成,具体环境如何配置可参考网络教程。下面我们开始项目的实现
库的导入
#include<iostream>
#include<opencv2/opencv.hpp>
#include<string.h>
using namespace std;
using namespace cv;
这就不多说了
开启摄像头
Mat frame;
Mat newframe;
string outputVideoPath = "F:\\C++language\\robocon.avi";
VideoCapture capture(0);
int frame_width = capture.get(CAP_PROP_FRAME_WIDTH);
int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT);
VideoWriter writer;
开始摄像头,并获取摄像头的像素高度与宽度
定义所需变量
int num = 3;//原图片长宽皆被划分为三份,共划分成九份
int stepwidth;//划分后单个图片的宽度
int stepheight;//划分后的那个图片的高度
int space = 5;//九宫格中每张图片的间隔
捕获图片并生成视频
capture >> frame;
stepwidth = frame.cols / num;
stepheight = frame.rows / num;
resize(frame, frame, Size(stepwidth * num, stepheight * num), 1, 1, INTER_LINEAR);
newframe = Mat(Size(frame.cols + (num - 1) * space, frame.rows + (num - 1) * space), CV_8UC3, Scalar(255, 255, 255));//新画布的生成
writer.open(outputVideoPath, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), 10, Size(frame.cols + (num - 1) * space, frame.rows + (num - 1) * space));
if (!capture.isOpened())
{
cout << "The camera cannot be opened" << endl;
}
if (!writer.isOpened())
{
cout << "The video cannot be saved" << endl;
}
根据九宫格各张图片以及间隔的大小生成新的画布,用于存放新的九宫格图片
实现图片的抓取、转换与保存
int count = 1;
while (count <= 60)
{
capture >> frame;
stepwidth = frame.cols / num;
stepheight = frame.rows / num;
resize(frame, frame, Size(stepwidth * num, stepheight * num), 1, 1, INTER_LINEAR);
Mat newframe = Mat(Size(frame.cols + (num - 1) * space, frame.rows + (num - 1) * space), CV_8UC3, Scalar(255, 255, 255));
int i = 0;
int j = 0;
for (i = 0; i < num; i++)
{
for (j=0; j < num; j++)
{
int x = stepwidth * j;
int y = stepheight * i;
frame(Rect(x, y, stepwidth, stepheight)).copyTo(newframe(Rect(x + space * j, y + space * i, stepwidth, stepheight)));
}
}
imshow("output", newframe);
waitKey(100);
writer << newframe;
count += 1;
}
}
视频以10帧的形式呈现,共60帧图片。
补充
当然OpenCV不仅可以实现录制九宫格视频,还能制作出九宫格拼图功能,下面是实现的示例代码,感兴趣的可以学习一下
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <stdlib.h>
#include <time.h>
using namespace cv;
using namespace std;
Mat img = imread("C:\\picture\\aa.jpg");
int m = img.cols;//宽
int n = img.rows;//高
cv::Mat combine = cv::Mat::zeros(m, n, img.type());
Mat imgROI1 = combine(Rect(0, 0, m / 3, n / 3));
Mat imgROI2 = combine(Rect(m / 3, 0, m / 3, n / 3));
Mat imgROI3 = combine(Rect(m / 3 * 2, 0, m / 3, n / 3));
Mat imgROI4 = combine(Rect(0, n / 3, m / 3, n / 3));
Mat imgROI5 = combine(Rect(m / 3, n / 3, m / 3, n / 3));
Mat imgROI6 = combine(Rect(m / 3 * 2, n / 3, m / 3, n / 3));
Mat imgROI7 = combine(Rect(0, n / 3 * 2, m / 3, n / 3));
Mat imgROI8 = combine(Rect(m / 3, n / 3 * 2, m / 3, n / 3));
Mat imgROI9 = combine(Rect(m / 3 * 2, n / 3 * 2, m / 3, n / 3));
Mat a[10];
Mat imge[10];
int t = 0;
int first;
int second;
Mat temp;
int f(int xx, int yy);
void onMouseHandle(int event, int x, int y, int flags, void *param);
int main()
{
//分割图像rect()
imge[1] = img(Rect(0, 0, m / 3, n / 3));
imge[2] = img(Rect(m / 3, 0, m / 3, n / 3));
imge[3] = img(Rect(m / 3 * 2, 0, m / 3, n / 3));
imge[4] = img(Rect(0, n / 3, m / 3, n / 3));
imge[5] = img(Rect(m / 3, n / 3, m / 3, n / 3));
imge[6] = img(Rect(m / 3 * 2, n / 3, m / 3, n / 3));
imge[7] = img(Rect(0, n / 3 * 2, m / 3, n / 3));
imge[8] = img(Rect(m / 3, n / 3 * 2, m / 3, n / 3));
imge[9] = img(Rect(m / 3 * 2, n / 3 * 2, m / 3, n / 3));
//生成随机数
int i, j;
int b[10];//存储获取到的随机数。
int f[10] = { 0 };//存储是否获取到过。
int nx = 1; //计数器。
srand((unsigned)time(NULL));//设置随机数种子。
while (nx < 10)
{
int my = rand() % 10; //获取一个0~9的随机数。
if (f[my]||my==0) continue;//该数之前已经获取到过。
b[nx++] = my;//将该数存入数组。
f[my] = 1;//标记该数已经获取过。
}
for (i = 1; i <= 9; i++)
{
a[i] = imge[b[i]];
}
namedWindow("九宫格");
resize(a[1], imgROI1, imgROI1.size());
resize(a[2], imgROI2, imgROI2.size());
resize(a[3], imgROI3, imgROI3.size());
resize(a[4], imgROI4, imgROI4.size());
resize(a[5], imgROI5, imgROI5.size());
resize(a[6], imgROI6, imgROI6.size());
resize(a[7], imgROI7, imgROI7.size());
resize(a[8], imgROI8, imgROI8.size());
resize(a[9], imgROI9, imgROI9.size());
imshow("九宫格", combine);
setMouseCallback("九宫格", onMouseHandle, (void*)&combine);
// 等待6000 ms后窗口自动关闭
waitKey(0);
return 0;
}
int f(int xx, int yy)
{
int s;
if (xx + yy == 2)
{
s = 1;
}
if (xx + yy == 3 && xx > yy)
{
s = 2;
}
if (xx + yy == 4 && xx > yy)
{
s = 3;
}
if (xx + yy == 3 && xx < yy)
{
s = 4;
}
if (xx + yy == 4 && xx == yy)
{
s = 5;
}
if (xx + yy == 5 && xx > yy)
{
s = 6;
}
if (xx + yy == 4 && xx < yy)
{
s = 7;
}
if (xx + yy == 5 && xx < yy)
{
s = 8;
}
if (xx + yy == 6)
{
s = 9;
}
return s;
}
void onMouseHandle(int event, int x, int y, int flags, void *param)
{
int xx ;
int yy ;
switch (event)
{
case CV_EVENT_LBUTTONDOWN ://左键单击
{
xx = x / (m / 3) + 1;
yy = y / (n / 3) + 1;
++t;
if (t % 2 == 1)
{
first = f(xx, yy);
}
if (t % 2 == 0)
{
second = f(xx, yy);
if (second == first + 3 || second == first - 3 || second == first + 1 || second == first - 1)
{
temp = a[first];
a[first] = a[second];
a[second] = temp;
resize(a[1], imgROI1, imgROI1.size());
resize(a[2], imgROI2, imgROI2.size());
resize(a[3], imgROI3, imgROI3.size());
resize(a[4], imgROI4, imgROI4.size());
resize(a[5], imgROI5, imgROI5.size());
resize(a[6], imgROI6, imgROI6.size());
resize(a[7], imgROI7, imgROI7.size());
resize(a[8], imgROI8, imgROI8.size());
resize(a[9], imgROI9, imgROI9.size());
}
}
imshow("九宫格", combine);
}
break;
default:
break;
}
}
来源:https://blog.csdn.net/qq_51444641/article/details/124730825
0
投稿
猜你喜欢
- String 字符串常量StringBuffer 字符串变量(线程安全)StringBuilder 字符串变量(非线程安全) 简要
- System.getProperty(user.dir)定位问题前言随着学习java web 的深入学习,为了巩固自己的学习成果,练习了一个
- 生命太短暂,不要去做一些根本没有人想要的东西。本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术
- 在日常开发中,可能会遇到同一份代码,需要根据运营需求打出不同包名、不同图标、不同名称的Apk,发布到不同的渠道中。Android Studi
- 刚开始学习C#的时候,就听说CLR对于String类有一种特别的内存管理机制:有时候,明明声明了两个String类的对象,但是他们偏偏却指向
- 自然排序TreeSet集合在存储数据时有一定的顺序,它会将一些数据进行比较,比较调用的是comparaTo()方法,该方法是在Compara
- Maven打包时指定启动类使用Maven打包的时候, 有时候需要指定启动类, 可如下操作!测试项目(结构如下):代码: com.xxx.Ma
- 现象正常情况下修改完代码,运行项目就会立即生效的。但是突然有一天发现运行的还是老的代码,新代码根本没有生效。通过 mvn clean、 in
- java 中newInstance()方法和new关键字的区别* 它们的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一个新
- 目录前言应用定义基本Enum特性Enum的静态导入Enum中添加新方法Switch语句中的EnumEnum的继承EnumSet的使用Enum
- 本文实例总结了Android实现屏幕旋转方法。分享给大家供大家参考。具体如下:在介绍之前,我们需要先了解默认情况下android屏幕旋转的机
- 首先,来看一下,快速排序的实现的动态图:快速排序介绍:快速排序,根据教科书说法来看,是冒泡排序的一种改进。快速排序,由一个待排序的数组(ar
- 这是我们用得比较多的一种设计模式,也是23种标准设计模式之一,使用前面讲的简单工厂设计模式,遇到具体产品经常变换时就不太适合了,违反了开闭设
- 上一篇:瑞吉外卖项目:新增员工一. 员工信息分页查询1. 需求分析当系统中的用户越来越多页面展示不完整,我们需要通过实现分页的方式去展示员工
- 1. 异常1.1 try…catch异常处理try catch的异常处理的格式写法 :try{ &nbs
- 本文实例讲述了Java面向对象程序设计多态性。分享给大家供大家参考,具体如下:多态:具有表现多种形态的能力的特征(同一个实现接口,使用不同的
- 本文实例讲述了C#文件断点续传实现方法。分享给大家供大家参考。具体实现方法如下:/// <summary>/// 下载局域网文件
- 目录1.项目gitthub地址链接: https://github.com/baisul/generateCode.git切换到master
- Java内存分配与管理是Java的核心技术之一,之前我们曾介绍过Java的内存管理与内存泄露以及Java垃圾回收方面的知识,今天我们再次深入
- Java程序设计 图形用户界面 【十】复选框复选框JCheckBoxJCheckBox类方法作用public JCheckBox(Icon