在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++項目中成功添加錄像功能,將攝像頭捕獲的圖像保存為視頻文件。希望這篇博客能對你有所幫助!