在C++项目中添加录像功能:从摄像头捕获到视频文件的保存
在这篇博客中,我们将介绍如何在一个现有的C++项目中添加录像功能,具体包括如何从摄像头捕获图像并将其保存为视频文件。我们将使用OpenCV库来处理图像捕获和视频写入。
目录
- 引言
- 准备工作
- 包含必要的头文件
- 添加录像功能的变量
- 初始化录像功能
- 在主循环中添加录像逻辑
- 控制录像的开始和停止
- 释放资源
- 完整示例代码
1. 引言
在计算机视觉应用中,常常需要从摄像头捕获图像并进行处理。为了记录这些图像,我们可以将其保存为视频文件。使用OpenCV库,我们可以轻松实现这一功能。本文将逐步讲解如何在你的C++项目中集成录像功能。
2. 准备工作
在开始之前,请确保你已经安装了OpenCV库,并且你的开发环境已经配置好以使用OpenCV。如果还没有安装,可以参考OpenCV官方网站获取安装和配置指南。
3. 包含必要的头文件
首先,确保你的代码中包含了OpenCV和其他必要的头文件。以下是示例代码的头文件部分:
cpp
#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
对象来保存视频文件,以及一个布尔标志来控制录像的开始和停止:
cpp
bool isRecording = false;
VideoWriter videoWriter;
std::string outputVideoFile = "output.avi";
5. 初始化录像功能
在摄像头成功打开后,我们需要初始化VideoWriter
对象。以下是初始化的代码片段:
cpp
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
videoWriter.open(outputVideoFile, VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, Size(frameWidth, frameHeight), true);
if (!videoWriter.isOpened()) {
cerr << "无法打开视频文件进行写入\n";
return -1;
}
break;
}
}
6. 在主循环中添加录像逻辑
在主循环中,我们将每一帧写入视频文件。以下是代码示例:
cpp
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. 控制录像的开始和停止
我们可以通过检查某些条件或命令行参数来控制录像的开始和停止。以下是一个示例,其中通过输入参数控制录像:
cpp
else if (argc >= 2) {
inputParameters1 = argv[1];
if (inputParameters1 == "record") {
printf("录像模式\n");
isRecording = true;
}
// 其他模式...
}
8. 释放资源
在程序结束时,确保释放VideoWriter
对象和其他资源:
cpp
printf("程序运行结束\n");
cap.release();
if (videoWriter.isOpened()) {
videoWriter.release();
}
return 0;
9. 完整示例代码
以下是集成了录像功能的完整示例代码:
cpp
#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++项目中成功添加录像功能,将摄像头捕获的图像保存为视频文件。希望这篇博客能对你有所帮助!