知识—-OpenCV库中的视频处理功能–用户捕获、编辑和分析视频流

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 1. 视频捕获(Video Capture):
    • 创建 VideoCapture 对象:
    • 或者直接打开摄像头或视频文件:
    • 检查是否成功打开:
    • 读取视频帧:
    • 获取视频参数:
    • 释放资源:
    • 案例
  • 2. 视频文件I/O:
    • 读取视频文件:
    • 读取视频帧:
    • 获取视频参数:
    • 写入视频文件:
    • 写入视频帧:
    • 释放资源:
    • 案例
  • 3. 视频分析:
    • 光流计算 - cv::calcOpticalFlowFarneback:
      • 案例
    • 帧差计算 - cv::absdiff:
      • 案例
    • 视频分析的应用:
  • 4. 视频显示:
    • cv::imshow 函数用于在窗口中显示图像,包括视频帧
      • 案例
    • 完整实例
  • 5. 视频处理回调函数:
    • 定义回调函数:
    • 设置回调函数:
  • 总结

前言

OpenCV(Open Source Computer Vision Library)是一款开源的计算机视觉和机器学习软件库。它提供了一套全面的工具,用于图像和视频处理、计算机视觉以及机器学习

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中的有关于视频工程处理的一些基本操作,如有不足之处,还请大家斧正!!