在C++项目中添加录像功能:从摄像头捕获到视频文件的保存
在这篇博客中,我们将介绍如何在一个现有的C++项目中添加录像功能,具体包括如何从摄像头捕获图像并将其保存为视频文件。我们将使用OpenCV库来处理图像捕获和视频写入。
目录
- 引言
- 准备工作
- 包含必要的头文件
- 添加录像功能的变量
- 初始化录像功能
- 在主循环中添加录像逻辑
- 控制录像的开始和停止
- 释放资源
- 完整示例代码
1. 引言
在计算机视觉应用中,常常需要从摄像头捕获图像并进行处理。为了记录这些图像,我们可以将其保存为视频文件。使用OpenCV库,我们可以轻松实现这一功能。本文将逐步讲解如何在你的C++项目中集成录像功能。
2. 准备工作
在开始之前,请确保你已经安装了OpenCV库,并且你的开发环境已经配置好以使用OpenCV。如果还没有安装,可以参考OpenCV官方网站获取安装和配置指南。
3. 包含必要的头文件
首先,确保你的代码中包含了OpenCV和其他必要的头文件。以下是示例代码的头文件部分:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <QString>
#include <chrono>
#include <thread>
#include "UdpUtil.h"
#include "lcmUtil.h"
#include "mythread.h"
#include "colorgroup.h"using namespace std;
using namespace std::chrono;
using namespace cv;
4. 添加录像功能的变量
我们需要一些变量来控制录像功能,例如一个VideoWriter
对象来保存视频文件,以及一个布尔标志来控制录像的开始和停止:
bool isRecording = false;
VideoWriter videoWriter;
std::string outputVideoFile = "output.avi";
5. 初始化录像功能
在摄像头成功打开后,我们需要初始化VideoWriter
对象。以下是初始化的代码片段:
for (int i = 0; i <= 3; i++) {cap.open(i);if (!cap.isOpened()) {printf("打开摄像头失败:number=%d\n", i);if (i == 3) return 0;} else {printf("打开摄像头成功:number=%d\n", i);// 获取摄像头帧率double fps = cap.get(CAP_PROP_FPS);if (fps == 0) fps = 30; // 如果无法获取帧率,设置一个默认值// 获取帧的宽度和高度int frameWidth = cap.get(CAP_PROP_FRAME_WIDTH);int frameHeight = cap.get(CAP_PROP_FRAME_HEIGHT);// 初始化VideoWritervideoWriter.open(outputVideoFile, VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, Size(frameWidth, frameHeight), true);if (!videoWriter.isOpened()) {cerr << "无法打开视频文件进行写入\n";return -1;}break;}
}
6. 在主循环中添加录像逻辑
在主循环中,我们将每一帧写入视频文件。以下是代码示例:
while (1) {cap >> srcImage;if (!srcImage.empty()) {imageProcess(srcImage); // 图像处理和指令发送lcmutil->send(v_des, gait_type, step_height, stand_height, rpy_des); // 发送步态指令logMode(); // 打印状态// 写入当前帧到视频文件if (isRecording) {videoWriter.write(srcImage);}if (flag) {colorgroup.showPicture(srcImage, 1);colorgroup.start();if (udpsocket.ifReceiveInfoFlag != 0) {switch (udpsocket.ifReceiveInfoFlag) {case 1: // 选择颜色并返回阈值colorgroup.chooseColor(udpsocket.color);colorgroup.sendColorThreadhold();colorgroup.ifRunContinueFlag = true;break;case 2: // 设置颜色阈值colorgroup.setColorThreadhold(udpsocket.colorThreadhold);break;case 3: // 保存颜色阈值colorgroup.save();break;}udpsocket.ifReceiveInfoFlag = 0;}}}QThread::msleep(20);
}
7. 控制录像的开始和停止
我们可以通过检查某些条件或命令行参数来控制录像的开始和停止。以下是一个示例,其中通过输入参数控制录像:
else if (argc >= 2) {inputParameters1 = argv[1];if (inputParameters1 == "record") {printf("录像模式\n");isRecording = true;}// 其他模式...
}
8. 释放资源
在程序结束时,确保释放VideoWriter
对象和其他资源:
printf("程序运行结束\n");
cap.release();
if (videoWriter.isOpened()) {videoWriter.release();
}
return 0;
9. 完整示例代码
以下是集成了录像功能的完整示例代码:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <QString>
#include <chrono>
#include <thread>
#include "UdpUtil.h"
#include "lcmUtil.h"
#include "mythread.h"
#include "colorgroup.h"using namespace std;
using namespace std::chrono;
using namespace cv;int main(int argc, char* argv[]) {UdpUtil udpsocket;QString inputParameters1;QString inputParameters2;bool flag = false; // 该标志位用于是否显示图像bool isRecording = false; // 录像标志位VideoWriter videoWriter;std::string outputVideoFile = "output.avi";static steady_clock::time_point start;if (argc == 1) {printf("using default parameter mode is track\n");printf("mode is track\n");printf("default residenceColor is red\n");mythread.mode = track;residenceColor = "brown";} else if (argc >= 2) {inputParameters1 = argv[1];if (inputParameters1 == "track") {printf("mode is track\n");printf("default residenceColor is null\n");mythread.mode = track;} else if (inputParameters1 == "brown") {printf("mode is track\n");printf("input residenceColor is brown\n");mythread.mode = track;residenceColor = "brown";} else if (inputParameters1 == "violet") {printf("mode is track\n");printf("input residenceColor is violet\n");mythread.mode = track;residenceColor = "violet";} else if (inputParameters1 == "stop") {printf("mode is stop\n");mythread.mode = stop;} else {mythread.mode = track;printf("parameters error\n");printf("mode is track\n");}if (argc == 3) {inputParameters2 = argv[2];if (inputParameters2 == "red") {printf("mode is track\n");printf("input divergerColor is red\n");mythread.mode = track;divergerColor = "red"; printf("start to show image\n");flag = true;udpsocket.start();} else if (inputParameters2 == "green") {printf("mode is track\n");printf("input divergerColor is green\n");mythread.mode = track;divergerColor = "green"; printf("start to show image\n");flag = true;udpsocket.start();} else if (inputParameters2 == "showImage") {printf("start to show image\n");flag = true;udpsocket.start();} else if (inputParameters1 == "record") {printf("录像模式\n");isRecording = true;}}}for (int i = 0; i <= 3; i++) {cap.open(i);if (!cap.isOpened()) {printf("打开摄像头失败:number=%d\n", i);if (i == 3) return 0;} else {printf("打开摄像头成功:number=%d\n", i);double fps = cap.get(CAP_PROP_FPS);if (fps == 0) fps = 30;int frameWidth = cap.get(CAP_PROP_FRAME_WIDTH);int frameHeight = cap.get(CAP_PROP_FRAME_HEIGHT);videoWriter.open(outputVideoFile, VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, Size(frameWidth, frameHeight), true);if (!videoWriter.isOpened()) {cerr << "无法打开视频文件进行写入\n";return -1;}break;}}lcmUtil *lcmutil = new lcmUtil;mythread.start();while (1) {cap >> srcImage;if (!srcImage.empty()) {imageProcess(srcImage);lcmutil->send(v_des, gait_type, step_height, stand_height, rpy_des);logMode();if (isRecording) {videoWriter.write(srcImage);}if (flag) {colorgroup.showPicture(srcImage, 1);colorgroup.start();if (udpsocket.ifReceiveInfoFlag != 0) {switch (udpsocket.ifReceiveInfoFlag) {case 1:colorgroup.chooseColor(udpsocket.color);colorgroup.sendColorThreadhold();colorgroup.ifRunContinueFlag = true;break;case 2:colorgroup.setColorThreadhold(udpsocket.colorThreadhold);break;case 3:colorgroup.save();break;}udpsocket.ifReceiveInfoFlag = 0;}}}QThread::msleep(20);}printf("程序运行结束\n");cap.release();if (videoWriter.isOpened()) {videoWriter.release();}return 0;
}
通过以上步骤,你可以在你的C++项目中成功添加录像功能,将摄像头捕获的图像保存为视频文件。希望这篇博客能对你有所帮助!