提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 1. 视频捕获(Video Capture):
-
- 创建 VideoCapture 对象:
- 或者直接打开摄像头或视频文件:
- 检查是否成功打开:
- 读取视频帧:
- 获取视频参数:
- 释放资源:
- 案例
- 2. 视频文件I/O:
-
- 读取视频文件:
- 读取视频帧:
- 获取视频参数:
- 写入视频文件:
- 写入视频帧:
- 释放资源:
- 案例
- 3. 视频分析:
-
- 光流计算 - cv::calcOpticalFlowFarneback:
-
- 案例
- 帧差计算 - cv::absdiff:
-
- 案例
- 视频分析的应用:
- 4. 视频显示:
-
- cv::imshow 函数用于在窗口中显示图像,包括视频帧
-
- 案例
- 完整实例
- 5. 视频处理回调函数:
-
- 定义回调函数:
- 设置回调函数:
- 总结
前言
OpenCV提供了丰富的功能用于视频处理,允许用户捕获、编辑和分析视频流。
以下是一些主要的视频处理功能和相关函数的详细介绍:
1. 视频捕获(Video Capture):
视频捕获是指从摄像头、视频文件或图像序列中获取视频帧的过程。在OpenCV中,主要通过 cv::VideoCapture 类来实现视频捕获。
以下是详细介绍:
创建 VideoCapture 对象:
cv::VideoCapture cap;
或者直接打开摄像头或视频文件:
cv::VideoCapture cap(0); // 打开默认摄像头 // 或 cv::VideoCapture cap("video_file.mp4"); // 打开视频文件
检查是否成功打开:
if (!cap.isOpened()) { std::cerr << "Error: Unable to open the video capture device." << std::endl; return -1; }
读取视频帧:
使用 >> 运算符可以从 VideoCapture 对象中读取一帧:
cv::Mat frame; cap >> frame;
获取视频参数:
double fps = cap.get(cv::CAP_PROP_FPS); // 帧率 int width = cap.get(cv::CAP_PROP_FRAME_WIDTH); // 帧宽 int height = cap.get(cv::CAP_PROP_FRAME_HEIGHT); // 帧高
释放资源:
cap.release(); // 关闭视频捕获对象
案例
#include <opencv2/opencv.hpp> int main() { cv::VideoCapture cap(0); // 打开默认摄像头 if (!cap.isOpened()) { std::cerr << "Error: Unable to open the video capture device." << std::endl; return -1; } cv::Mat frame; while (true) { cap >> frame; // 从摄像头中读取一帧 if (frame.empty()) break; // 在这里添加对帧的处理逻辑 cv::imshow("Video Frame", frame); if (cv::waitKey(30) == 27) // 按下ESC键退出 break; } cap.release(); // 释放资源 return 0; }
这个示例打开默认摄像头,不断读取视频帧并在窗口中显示,直到按下ESC键退出。
在实际应用中,可以根据需要添加对帧的处理逻辑,如图像处理、目标检测等。
2. 视频文件I/O:
视频文件 I/O 主要涉及从视频文件中读取和写入视频。在 OpenCV 中,这主要通过 cv::VideoCapture 类用于读取视频,以及 cv::VideoWriter 类用于写入视频。
以下是详细介绍:
读取视频文件:
使用 cv::VideoCapture 打开视频文件:
cv::VideoCapture cap("input_video.mp4"); if (!cap.isOpened()) { std::cerr << "Error: Unable to open the input video file." << std::endl; return -1; }
读取视频帧:
cv::Mat frame; cap >> frame; // 从视频文件中读取一帧
获取视频参数:
double fps = cap.get(cv::CAP_PROP_FPS); // 帧率 int width = cap.get(cv::CAP_PROP_FRAME_WIDTH); // 帧宽 int height = cap.get(cv::CAP_PROP_FRAME_HEIGHT); // 帧高
写入视频文件:
使用 cv::VideoWriter 创建视频写入对象:
cv::VideoWriter writer("output_video.avi", cv::VideoWriter::fourcc('X','V','I','D'), 30, cv::Size(width, height), true); if (!writer.isOpened()) { std::cerr << "Error: Unable to open the output video file." << std::endl; return -1; }
参数解释:
‘XVID’ 是视频编解码器的四字符码,表示使用 Xvid 编码器,具体的编码器可以根据需要选择。
30 是输出视频的帧率。
cv::Size(width, height) 是输出视频的帧大小。
true 表示输出视频帧使用彩色格式。
写入视频帧:
cv::Mat frame; cap >> frame; // 从视频文件中读取一帧 writer << frame; // 将帧写入输出视频文件
释放资源:
cap.release(); // 关闭视频捕获对象 writer.release(); // 关闭视频写入对象
案例
#include <opencv2/opencv.hpp> int main() { cv::VideoCapture cap("input_video.mp4"); if (!cap.isOpened()) { std::cerr << "Error: Unable to open the input video file." << std::endl; return -1; } int width = cap.get(cv::CAP_PROP_FRAME_WIDTH); int height = cap.get(cv::CAP_PROP_FRAME_HEIGHT); double fps = cap.get(cv::CAP_PROP_FPS); cv::VideoWriter writer("output_video.avi", cv::VideoWriter::fourcc('X','V','I','D'), fps, cv::Size(width, height), true); if (!writer.isOpened()) { std::cerr << "Error: Unable to open the output video file." << std::endl; return -1; } cv::Mat frame; while (true) { cap >> frame; // 从视频文件中读取一帧 if (frame.empty()) break; // 在这里添加对帧的处理逻辑 writer << frame; // 将帧写入输出视频文件 cv::imshow("Video Frame", frame); if (cv::waitKey(30) == 27) // 按下ESC键退出 break; } cap.release(); // 释放资源 writer.release(); // 关闭视频写入对象 return 0; }
这个示例打开一个输入视频文件,读取每一帧并在窗口中显示,同时将每一帧写入输出视频文件。
在实际应用中,可以根据需要添加对帧的处理逻辑。
3. 视频分析:
视频分析涉及到从视频中提取有关运动、变化等方面的信息。
以下是一些视频分析的常用功能以及相关函数的详细解释:
光流计算 - cv::calcOpticalFlowFarneback:
函数原型:
void cv::calcOpticalFlowFarneback( cv::InputArray prev, cv::InputArray next, cv::InputOutputArray flow, double pyr_scale, int levels, int winsize, int iterations, int poly_n, double poly_sigma, int flags);
参数解释:
prev: 先前帧图像。
next: 后续帧图像。
flow: 计算得到的光流。在函数调用之前,可以使用 cv::Mat::zeros 初始化为零。
pyr_scale: 图像金字塔的尺度因子。
levels: 图像金字塔的层数。
winsize: 每个金字塔层的窗口大小。
iterations: 每个金字塔层的迭代次数。
poly_n: 多项式扩展的像素领域大小。
poly_sigma: 多项式扩展中高斯标准差。
flags: 光流计算的标志。
案例
cv::Mat prev_frame, next_frame, flow; cap >> prev_frame; cap >> next_frame; cv::calcOpticalFlowFarneback(prev_frame, next_frame, flow, 0.5, 3, 15, 3, 5, 1.2, 0);
帧差计算 - cv::absdiff:
函数原型:
void cv::absdiff(cv::InputArray src1, cv::InputArray src2, cv::OutputArray dst);
参数解释:
src1: 输入图像1。
src2: 输入图像2。
dst: 输出差值图像。
案例
cv::Mat frame1, frame2, diff; cap >> frame1; cap >> frame2; cv::absdiff(frame1, frame2, diff);
以上示例计算两个连续帧之间的差异。
视频分析的应用:
这些函数的应用包括运动检测、目标跟踪、人流量统计等。
通过计算光流,可以了解图像中的运动情况;通过帧差计算,可以检测到图像中的像素变化,从而实现运动检测等应用。
#include <opencv2/opencv.hpp> int main() { cv::VideoCapture cap("input_video.mp4"); if (!cap.isOpened()) { std::cerr << "Error: Unable to open the input video file." << std::endl; return -1; } cv::Mat prev_frame, next_frame, flow, diff; cap >> prev_frame; while (true) { cap >> next_frame; if (next_frame.empty()) break; // 计算光流 cv::calcOpticalFlowFarneback(prev_frame, next_frame, flow, 0.5, 3, 15, 3, 5, 1.2, 0); // 计算帧差 cv::absdiff(prev_frame, next_frame, diff); // 在这里添加对光流和帧差的处理逻辑 cv::imshow("Optical Flow", flow); cv::imshow("Frame Difference", diff); prev_frame = next_frame; if (cv::waitKey(30) == 27) // 按下ESC键退出 break; } cap.release(); // 释放资源 return 0; }
这个示例在视频中计算了光流和帧差,并在窗口中显示结果。
在实际应用中,可以根据需要添加对光流和帧差的处理逻辑,实现各种视频分析的应用场景。
4. 视频显示:
OpenCV允许将视频帧显示在窗口中。主要使用 cv::imshow 函数。
以下是详细介绍:
cv::imshow 函数用于在窗口中显示图像,包括视频帧
函数原型:
void cv::imshow(const cv::String &winname, cv::InputArray mat);
winname: 窗口的名称。
mat: 要显示的图像。
案例
cv::Mat frame; cv::VideoCapture cap("input_video.mp4"); while (true) { cap >> frame; if (frame.empty()) break; cv::imshow("Video Frame", frame); if (cv::waitKey(30) == 27) // 按下ESC键退出 break; }
注意事项:
窗口关闭: 在窗口中显示图像后,按下任意键,窗口会等待用户按键,如果按下的是 ESC 键(ASCII码为 27),则退出循环关闭窗口。
实时显示: 在循环中调用 cv::imshow 可以实现图像的实时显示。
完整实例
#include <opencv2/opencv.hpp> int main() { cv::VideoCapture cap("input_video.mp4"); if (!cap.isOpened()) { std::cerr << "Error: Unable to open the input video file." << std::endl; return -1; } cv::Mat frame; while (true) { cap >> frame; if (frame.empty()) break; cv::imshow("Video Frame", frame); if (cv::waitKey(30) == 27) // 按下ESC键退出 break; } cap.release(); // 释放资源 return 0; }
这个示例打开一个输入视频文件,不断读取每一帧并在窗口中显示,通过按下 ESC 键退出。在实际应用中,可以根据需要添加对帧的处理逻辑。
5. 视频处理回调函数:
OpenCV允许通过回调函数处理视频帧,以在帧被显示前进行自定义处理。这通常使用 cv::VideoCapture 结合回调函数实现。
以下是详细介绍:
使用回调函数处理视频帧:
定义回调函数:
void processFrame(const cv::Mat& frame, void* userData) { // 在这里添加对帧的自定义处理逻辑 // frame 是传递给回调函数的视频帧 }
设置回调函数:
cv::VideoCapture cap("input_video.mp4"); if (!cap.isOpened()) { std::cerr << "Error: Unable to open the input video file." << std::endl; return -1; } cv::namedWindow("Video Frame", cv::WINDOW_NORMAL); cv::resizeWindow("Video Frame", 800, 600); // 设置回调函数 cap.set(cv::CAP_PROP_FRAME_WIDTH, 800); cap.set(cv::CAP_PROP_FRAME_HEIGHT, 600); cap.set(cv::CAP_PROP_FPS, 30); cap.set(cv::CAP_PROP_POS_FRAMES, 0); cv::VideoWriter writer("output_video_with_callback.avi", cv::VideoWriter::fourcc('X','V','I','D'), 30, cv::Size(800, 600), true); cap.set(cv::CAP_PROP_POS_FRAMES, 0); while (true) { cv::Mat frame; cap >> frame; if (frame.empty()) break; // 调用回调函数 processFrame(frame, nullptr); // 显示帧 cv::imshow("Video Frame", frame); // 将帧写入输出视频文件 writer << frame; if (cv::waitKey(30) == 27) // 按下ESC键退出 break; } cap.release(); // 释放资源 writer.release(); // 关闭视频写入对象 cv::destroyAllWindows(); // 关闭所有窗口 return 0;
在上述示例中,通过 cap.set 函数设置了视频的宽、高、帧率等属性,并通过 cap.set(cv::CAP_PROP_POS_FRAMES, 0) 将视频的帧位置设置为初始位置。在循环中,通过 cap >> frame 获取视频的每一帧,然后调用 processFrame 回调函数进行自定义处理。最后,通过 cv::imshow 显示帧,通过 cv::VideoWriter 将帧写入输出视频文件。
总结
以上就是OpenCV中的有关于视频工程处理的一些基本操作,如有不足之处,还请大家斧正!!