C++ OpenCV 视频处理入门与实战
C++ OpenCV 视频处理 是许多开发者在图像识别、视频分析和计算机视觉项目中常用的技能。OpenCV 提供了丰富的 API 来读取、处理和写入视频流,本文将围绕这些核心功能,提供实用的代码示例和技巧,帮助你在工作中快速实现视频处理需求。
快速解决
要使用 OpenCV 在 C++ 中处理视频,首先需要包含相关头文件并初始化 VideoCapture 和 VideoWriter 对象。以下是一个最简单的视频读取和保存示例:
#include <opencv2/opencv.hpp> // 包含 OpenCV 头文件
#include <iostream>
using namespace cv;
using namespace std;
int main() {
VideoCapture cap("input.mp4"); // 打开视频文件
if (!cap.isOpened()) {
cout << "无法打开视频文件" << endl; // 如果失败,输出错误信息
return -1;
}
int frameWidth = static_cast<int>(cap.get(CAP_PROP_FRAME_WIDTH)); // 获取视频宽度
int frameHeight = static_cast<int>(cap.get(CAP_PROP_FRAME_HEIGHT)); // 获取视频高度
VideoWriter writer("output.mp4", VideoWriter::fourcc('M','P','4','V'), 30, Size(frameWidth, frameHeight), true); // 创建 VideoWriter 保存处理后的视频
Mat frame;
while (true) {
cap >> frame; // 读取视频帧
if (frame.empty()) break; // 如果帧为空,说明视频结束
// 在这里添加视频处理逻辑,例如灰度化
cvtColor(frame, frame, COLOR_BGR2GRAY); // 将彩色帧转为灰度
writer << frame; // 写入处理后的帧
imshow("视频处理", frame); // 显示处理中的帧
if (waitKey(30) == 27) break; // 按 ESC 键退出
}
cap.release(); // 释放视频捕获对象
writer.release(); // 释放视频写入对象
destroyAllWindows(); // 关闭所有窗口
return 0;
}
常用方法
以下是 C++ OpenCV 视频处理中常见的方法,按使用频率排序:
| 方法名 | 作用描述 | 是否常用 |
|---|---|---|
VideoCapture::open() |
打开视频文件或摄像头 | ✅ |
VideoCapture::read() / >> |
读取视频帧 | ✅ |
VideoWriter::write() / << |
写入视频帧 | ✅ |
CAP_PROP_FRAME_WIDTH / CAP_PROP_FRAME_HEIGHT |
获取视频宽高 | ✅ |
CAP_PROP_FPS |
获取帧率 | ✅ |
cvtColor() |
颜色空间转换 | ✅ |
GaussianBlur() |
高斯模糊处理 | ✅ |
flip() |
帧翻转(例如左右镜像) | ✅ |
详细说明
视频读取与显示
OpenCV 通过 VideoCapture 类读取视频文件,支持从文件或摄像头获取视频流:
VideoCapture cap("input.mp4"); // 从文件读取视频
if (!cap.isOpened()) {
cout << "无法打开视频文件" << endl;
return -1;
}
Mat frame;
while (true) {
cap >> frame; // 读取下一帧
if (frame.empty()) break;
imshow("原始视频", frame); // 显示帧
if (waitKey(30) == 27) break; // 按 ESC 退出
}
视频保存与写入
处理完视频帧后,使用 VideoWriter 将帧写入新文件:
int frameWidth = static_cast<int>(cap.get(CAP_PROP_FRAME_WIDTH));
int frameHeight = static_cast<int>(cap.get(CAP_PROP_FRAME_HEIGHT));
double fps = cap.get(CAP_PROP_FPS);
VideoWriter writer("output.mp4",
VideoWriter::fourcc('M','P','4','V'), // 视频编码格式
fps, // 帧率
Size(frameWidth, frameHeight), // 分辨率
true); // 是否是彩色视频
Mat frame;
while (true) {
cap >> frame;
if (frame.empty()) break;
// 示例:添加处理逻辑
GaussianBlur(frame, frame, Size(15,15), 0); // 对帧进行高斯模糊
writer << frame; // 写入帧到输出视频
}
视频属性获取
你可以通过 cap.get() 方法获取视频的详细属性,例如宽高、帧率、总帧数等:
int width = static_cast<int>(cap.get(CAP_PROP_FRAME_WIDTH)); // 获取视频宽度
int height = static_cast<int>(cap.get(CAP_PROP_FRAME_HEIGHT)); // 获取视频高度
double fps = cap.get(CAP_PROP_FPS); // 获取帧率
int totalFrames = static_cast<int>(cap.get(CAP_PROP_FRAME_COUNT)); // 获取总帧数
int codec = static_cast<int>(cap.get(CAP_PROP_FOURCC)); // 获取编码格式
cout << "视频宽度: " << width << endl;
cout << "视频高度: " << height << endl;
cout << "帧率: " << fps << endl;
cout << "总帧数: " << totalFrames << endl;
cout << "编码格式: " << codec << endl;
高级技巧
实时摄像头处理与保存
如果你需要从摄像头读取视频并实时处理:
VideoCapture cap(0); // 打开默认摄像头
if (!cap.isOpened()) {
cout << "无法打开摄像头" << endl;
return -1;
}
int width = static_cast<int>(cap.get(CAP_PROP_FRAME_WIDTH));
int height = static_cast<int>(cap.get(CAP_PROP_FRAME_HEIGHT));
double fps = cap.get(CAP_PROP_FPS);
VideoWriter writer("output_webcam.mp4",
VideoWriter::fourcc('M','P','4','V'),
fps,
Size(width, height),
true);
Mat frame;
while (true) {
cap >> frame;
if (frame.empty()) break;
// 示例:灰度化 + 反色处理
cvtColor(frame, frame, COLOR_BGR2GRAY);
bitwise_not(frame, frame); // 反色
writer << frame;
imshow("处理中的摄像头", frame);
if (waitKey(30) == 27) break;
}
cap.release();
writer.release();
destroyAllWindows();
视频帧率控制与跳帧处理
在某些场景下(如视频分析),你可能希望跳过某些帧以提高效率:
int skipFrame = 2; // 跳过每两帧
int count = 0;
Mat frame;
while (true) {
cap >> frame;
if (frame.empty()) break;
if (count % skipFrame == 0) { // 只处理每隔 skipFrame 帧
writer << frame;
imshow("处理中的视频", frame);
}
count++;
}
常见问题
Q:为什么保存的视频没有声音?
A:OpenCV 的 VideoWriter 不支持音频通道,只能保存视频帧。如果需要带音频的输出,需使用其他工具(如 FFmpeg)进行后期合成。
Q:如何判断视频是否打开成功?
A:调用 cap.isOpened() 方法,返回 true 表示成功打开,否则为 false。
Q:为什么输出视频播放不了?
A:可能使用了不兼容的编码格式(FourCC),例如在某些系统上 'M','P','4','V' 不可用,可以尝试 'X','V','I','D' 或其他格式。
Q:如何获取视频的当前帧号?
A:使用 cap.get(CAP_PROP_POS_FRAMES),该方法返回当前已读取的帧数。
总结
C++ OpenCV 视频处理 提供了强大的工具来读取、处理和保存视频,掌握基本的 VideoCapture 和 VideoWriter 用法即可完成大部分任务,结合颜色转换、模糊处理等图像操作,可以实现更多实际功能。