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


猜你喜欢
- 一、题目描述给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种
- 静态数组Java中最基本的数组大家肯定不会陌生:int[] array = new int[6];for (int i = 0; i <
- 前言最近遇到很有意思转换二进制的问题,有部分童鞋俨然已了解,可能也有一部分童鞋没碰到过也就不知情,这里我们来深入学习下转换二进制所带来的问题
- 基本结构我们先来看一段最基本的代码,分析这段代码在RxJava中是如何实现的。Observable.OnSubscribe<Strin
- Monitor对象1.Monitor.Enter(object)方法是获取锁,Monitor.Exit(object)方法是释放锁,这就是M
- 本节讲运行在后台服务里的工作请求,如何向发送请求者报告状态。推荐用LocalBroadcastManager发送和接收状态,它限制了只有本a
- 本文主要是分析Spring bean的循环依赖,以及Spring的解决方式。 通过这种解决方式,我们可以应用在我们实际开发项目中。1. 什么
- 最近项目用到了Spring Boot ,但是在控制器返回html视图并渲染参数的时候,存在了疑问。后面考虑用Thymeleaf ,感觉真的不
- foreach嵌套使用if标签对象取值问题最近做项目过程中,涉及到需要在 Mybatis 中 使用 foreach 进行循环读取传入的查询条
- SqlssionFactory1.SqlSessionFactory是MyBatis的关键对象,它是个单个数据库映射关系经过编译后的内存镜像
- ps: 不想看代码的滑到最下面有apk包百度网盘下载地址1. 先看效果图 不然都是耍流氓2.项目目录3.一些配置build.gradlepl
- 本文实例分析了C#中登录窗体和欢迎窗体关闭方法。分享给大家供大家参考。具体分析如下:在c#的winform编程中,我们经常会做登录窗体或欢迎
- Zipkin是一种分布式跟踪系统。它有助于收集解决微服务架构中延迟问题所需的时序数据。它管理这些数据的收集和查找。Zipkin的设计基于&n
- 1.背景在java语言中还没有引入枚举类型之前,表示枚举类型的常用模式是声明一组具有int常量。之前我们通常利用public final s
- 对于一个简单的tcp通讯这里我就不再讲述了,今天主要为大家讲解下,如何从::recv中筛选出一个完整包逻辑。就简单的以客户端为例(服务器接收
- 本文实例讲述了Android编程实现对电池状态的监视功能。分享给大家供大家参考,具体如下:最近在开发一个与GPS相关的项目,因为其中涉及到了
- 拒绝策略介绍线程池的拒绝策略,是指当任务添加到线程池中被拒绝,而采取的处理措施。当任务添加到线程池中之所以被拒绝,可能是由于:第一,线程池异
- 一、MyBatisPlusConfig中配置分页插件/** * 配置分页插件 * @
- 背景看完本章,你将会学习到用ASM的tree api进行对匿名线程的hook操作,同时也能够了解到asm相关的操作和背景知识介绍!对于ASM
- QTableView是Qt中用来把数据集以表格形式提供给用户的一个控件QTableView类实现表格视图,QTableView的数据由继承Q