文章目录
-
- [一、OpenCV 视频录制概述](#一、OpenCV 视频录制概述)
- 二、示例代码
一、OpenCV 视频录制概述
在 OpenCV 中,视频录制主要靠 cv::VideoWriter 类。它可以把连续的 cv::Mat 帧写入一个视频文件(如 .avi、.mp4 等)。
VideoWriter类
构造函数:
cpp
VideoWriter::VideoWriter(const String &filename,
int fourcc,
double fps,
Size frameSize,
bool isColor = true);
参数说明:
- filename:保存的视频文件名,例如 "output.avi"
- fourcc:视频编码方式,如 CV_FOURCC('M','J','P','G') 或 VideoWriter::fourcc('M','J','P','G')
- fps:帧率(帧每秒)
- frameSize:视频每帧的尺寸,Size(width, height)
- isColor:是否为彩色视频,true 彩色,false 灰度
常用编码(fourcc):
cpp
int fourcc = VideoWriter::fourcc('M','J','P','G'); // AVI 常用
int fourcc_mp4 = VideoWriter::fourcc('a','v','c','1'); // MP4 H264
二、示例代码
示例 1:从摄像头录制视频
cpp
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main() {
VideoCapture cap(0); // 打开摄像头
if (!cap.isOpened()) {
cout << "Cannot open camera" << endl;
return -1;
}
// 视频参数
int frame_width = static_cast<int>(cap.get(CAP_PROP_FRAME_WIDTH));
int frame_height = static_cast<int>(cap.get(CAP_PROP_FRAME_HEIGHT));
VideoWriter writer("output.avi",
VideoWriter::fourcc('M','J','P','G'),
30, Size(frame_width, frame_height));
Mat frame;
while (true) {
cap >> frame;
if (frame.empty()) break;
writer.write(frame); // 写入视频
imshow("Camera", frame);
if (waitKey(1) == 27) break; // 按 ESC 停止
}
cap.release();
writer.release();
destroyAllWindows();
return 0;
}
示例 2:将视频文件处理后保存
cpp
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main() {
VideoCapture cap("opencv_demo.mp4");
if (!cap.isOpened()) return -1;
int width = cap.get(CAP_PROP_FRAME_WIDTH);
int height = cap.get(CAP_PROP_FRAME_HEIGHT);
VideoWriter writer("output_processed.avi",
VideoWriter::fourcc('M', 'J', 'P', 'G'),
30, Size(width, height));
Mat frame;
while (true) {
cap >> frame;
if (frame.empty()) break;
// 处理帧,例如灰度
cvtColor(frame, frame, COLOR_BGR2GRAY);
cvtColor(frame, frame, COLOR_GRAY2BGR); // 保持三通道以写入
writer.write(frame);
}
cap.release();
writer.release();
return 0;
}
示例3:自动读取指定文件夹下所有图片生成视频
cpp
#include <opencv2/opencv.hpp>
#include <iostream>
#include <filesystem>
#include <vector>
#include <algorithm>
using namespace cv;
using namespace std;
namespace fs = std::filesystem;
int main() {
string folderPath = "images"; // 图片文件夹路径
string outputVideo = "output_video.avi";
double fps = 30.0; // 帧率
vector<string> imgFiles;
// 遍历文件夹,收集图片路径
for (const auto& entry : fs::directory_iterator(folderPath)) {
if (entry.is_regular_file()) {
string ext = entry.path().extension().string();
// 支持 jpg/png/bmp
if (ext == ".jpg" || ext == ".png" || ext == ".bmp")
imgFiles.push_back(entry.path().string());
}
}
if (imgFiles.empty()) {
cout << "No images found in folder!" << endl;
return -1;
}
// 按文件名排序
sort(imgFiles.begin(), imgFiles.end());
// 读取第一张图片获取尺寸
Mat firstImg = imread(imgFiles[0]);
if (firstImg.empty()) {
cout << "Failed to read " << imgFiles[0] << endl;
return -1;
}
Size frameSize(firstImg.cols, firstImg.rows);
// 创建 VideoWriter
VideoWriter writer(outputVideo,
VideoWriter::fourcc('M','J','P','G'),
fps,
frameSize,
true);
if (!writer.isOpened()) {
cout << "Cannot open VideoWriter!" << endl;
return -1;
}
// 写入每张图片
for (const auto& file : imgFiles) {
Mat img = imread(file);
if (img.empty()) {
cout << "Failed to read " << file << endl;
continue;
}
// 尺寸不一致就 resize
if (img.size() != frameSize) {
resize(img, img, frameSize);
}
writer.write(img);
}
writer.release();
cout << "Video saved as " << outputVideo << endl;
return 0;
}