ffmpeg学习4:opencv在音视频领域常用指令

目录

[1 视频/图像读写](#1 视频/图像读写)

[1.1 视频](#1.1 视频)

[1.1.1 视频读 VideoCapture](#1.1.1 视频读 VideoCapture)

[1.1.2 视频写 VideoWriter](#1.1.2 视频写 VideoWriter)

[1.2 图像](#1.2 图像)

[1.2.1 图像读 imread](#1.2.1 图像读 imread)

[1.2.2 图像写 imwriter](#1.2.2 图像写 imwriter)

[2 图像预处理 resize等](#2 图像预处理 resize等)


核心流程:

视频/图像读写 → 帧预处理 → 特征提取或模型推理 → 视频分析 → 结果输出

阶段 主要工作 常用模块
视频/图像读写 摄像头、文件、RTSP 拉流 videoio
帧预处理 缩放、裁剪、色彩转换、去噪 imgproc、core
特征提取/推理 边缘、光流、背景减除、DNN 推理 video、dnn、features2d
视频分析 检测、跟踪、运动分析、场景识别 video、dnn
结果输出 画框、显示、保存、推流 imgcodecs、videoio

1 视频/图像读写

1.1 视频

1.1.1 视频读 VideoCapture

camera: 从相机读取

file:从视频文件读取

rtsp:从视频流文件读取,需要使用多线程+队列保证视频流畅

cpp 复制代码
void testCmaera() {

    cv::VideoCapture capture;

    bool result = capture.open(0);
    if (!result) {
        std::cout << ("capture open fail") << std::endl;
        return; 
    }


    cv::namedWindow("camera");
    cv::Mat frame;
    while (capture.read(frame)) {

        if (frame.empty()) {
            break;
        }

        cv::imshow("camera", frame);
        cv::waitKey(30);
    }
    // 閲婃斁绐楀彛璧勬簮
    cv::destroyAllWindows();

}



void testMP4() {

    cv::VideoCapture capture;

    bool result = capture.open("images/trailer.mp4");

    if (!result) {
        std::cout << "打开视频文件失败" << std::endl;
        return;
    }

    double fps = capture.get(cv::CAP_PROP_FPS);
    if (fps <= 0) {
        fps = 30.0;
    }

    int pauseTime = 1000 / fps;

    cv::Mat frame;
    cv::namedWindow("mp4");
    while (capture.read(frame)) {
        if (frame.empty()) {
            break;
        }
        cv::imshow("mp4", frame);
        if (cv::waitKey(pauseTime) == 27) break;
    }
    capture.release();
    cv::destroyAllWindows();

}


void testRtsp() {

        string rtsp_url = "rtsp://rtsp.rtsplink.com/live/test?token=cfe62a0ba7e1e5f7d3cf21dc94b1b21d1a34d8f6e9f09d1263b90607aa0e6d2a";

        queue<Mat> frame_q;
        mutex mtx;
        bool running = true;
        const int MAX_QUEUE = 6;

        // ========== 子线程:拉流 grab + retrieve ==========
        thread producer([&]() {
            VideoCapture cap(rtsp_url);

            if (!cap.isOpened())
            {
                cout << "子线程打开RTSP失败!检查地址、网络、opencv是否带ffmpeg" << endl;
                running = false;
                return;
            }

            cout << "W:" << cap.get(CAP_PROP_FRAME_WIDTH)
                << " H:" << cap.get(CAP_PROP_FRAME_HEIGHT) << endl;

            Mat frame;
            while (running)
            {
                if (!cap.grab())
                {
                    cout << "丢帧/断流" << endl;
                    this_thread::sleep_for(chrono::milliseconds(200));
                    continue;
                }
                if (!cap.retrieve(frame))
                {
                    continue;
                }
                if (frame.empty())
                    continue;

                lock_guard<mutex> lk(mtx);
                if (frame_q.size() >= MAX_QUEUE)
                {
                    frame_q.pop();
                }
                frame_q.push(frame.clone());
            }
            cap.release(); // cap在这里释放,子线程内部自己释放
            });

        // ========== 主线程:显示 + 写文件 ==========
        VideoWriter writer("demo.mp4", cv::VideoWriter::fourcc('m', 'p', '4', 'v'), 30, Size(1280, 720));
        if (!writer.isOpened())
        {
            running = false;
            producer.join();
            cout << "writer 创建失败" << endl;
            return;
        }

        Mat curr;
        while (true)
        {
            {
                lock_guard<mutex> lk(mtx);
                if (!frame_q.empty())
                {
                    curr = frame_q.front();
                    frame_q.pop();
                }
            }

            if (!curr.empty())
            {
                writer.write(curr);
                imshow("rtsp", curr);
            }

            int key = waitKey(1);
            if (key == 'q')
            {
                break;
            }
        }

        // 优雅退出
        running = false;
        producer.join();// 阻塞,等待线程退出

        writer.release();
        destroyAllWindows();
}

1.1.2 视频写 VideoWriter

fourcc:编码格式,参考Video Codecs by FOURCC - fourcc.org

fourcc 写法 编码 推荐后缀 说明
fourcc('M','J','P','G') MJPEG .avi 最稳,几乎所有 OpenCV 都支持,画质好、体积大
fourcc('m','p','4','v') MPEG-4 .mp4 Windows MSMF 后端友好,兼容性首选 mp4
fourcc('a','v','c','1') H.264 .mp4 压缩率高,必须开启 FFmpeg 才支持
fourcc('X','V','I','D') XVID .avi 压缩好,预编译包大多不带,容易打开失败
fourcc('I','Y','U','V') IYUV 无压缩 .avi 无压缩,文件巨大
cpp 复制代码
void testWriter() {

    cv::VideoCapture capture("oceans.mp4");

    if (!capture.isOpened()) {
        cout << "打开失败" << endl;
        return;
    }

    int w = capture.get(cv::CAP_PROP_FRAME_WIDTH);
    int h = capture.get(cv::CAP_PROP_FRAME_HEIGHT);
    //int fourcc = VideoWriter::fourcc('M', 'J', 'P', 'G');
    int fourcc = VideoWriter::fourcc('m', 'p', '4', 'v');
    VideoWriter writer("output.avi", fourcc, 30, Size(w, h));

    if (!writer.isOpened()) {
        cout << "writer 打开失败,编码器不可用" << endl;
        capture.release();
        return;
    }


    cv::Mat frameIn;

    while (capture.read(frameIn)) {
        if (frameIn.empty()) {
            return;
        }
        imshow("oceans",frameIn );
        writer.write(frameIn);

        if (cv::waitKey(30) == 27) {
            break;
        }

    }

    capture.release();
    writer.release();
    cv::destroyAllWindows();
}

1.2 图像

1.2.1 图像读 imread

cpp 复制代码
void testImg() {

    cv::Mat image = cv::imread("images/1.jpg");
    if (image.empty()) {

        return;
    }

    cv::namedWindow("image");

    cv::imshow("image", image);

    cv::waitKey();

    cv::destroyAllWindows();

}

1.2.2 图像写 imwriter

在退出时保存一帧图像

cpp 复制代码
void testImgWrite() {

    cv::VideoCapture capture("oceans.mp4");

    if (!capture.isOpened()) {
        cout << "打开失败" << endl;
        return;
    }

    cv::Mat frameIn;

    while (capture.read(frameIn)) {
        if (frameIn.empty()) {
            return;
        }
        imshow("oceans", frameIn);
        //writer.write(frameIn);

        if (cv::waitKey(30) == 27) {
            cv::imwrite("snapshot.jpg", frameIn);
            break;
        }
    }

    capture.release();

    cv::destroyAllWindows();
}

2 图像预处理 resize等

用于后续的分析等

cpp 复制代码
void preProcess() {

    cv::Mat image = cv::imread("images/1.jpg");

    if (image.empty()) {
        return;
    }
    cv::imshow("source", image);
    //cv::namedWindow("aim"); // 可要可不要


    // 1 缩放
    cv::Mat aim;
    cv::resize(image, aim, cv::Size(640, 480));

    // 2 色彩转换
    //cv::cvtColor(aim, aim,cv::COLOR_BGR2GRAY);

    // 3 翻转
    // 0 沿着X轴镜像
    // 1 沿着Y轴镜像
    // -1 沿着中心点镜像 (x+y)
    cv::flip(aim, aim, 0);

    // 4 旋转180
    cv::rotate(aim, aim, cv::ROTATE_90_CLOCKWISE);

    // 5 高斯模糊
    cv::GaussianBlur(aim, aim, cv::Size(11, 11)/*卷积核大小*/, 0/*X轴方向上的sigma�*/);

    // 6 边缘检测
    //cv::Canny(aim, aim, 10/*下边界值*/, 30/*上边界值*/);

    // 7 二值化
    cv::threshold(aim, aim, 160/*边界*/, 255/*最大值*/, cv::THRESH_BINARY);


    // 8 左右眼图像拼接,VR中常用
    cv::Mat sidBySide;
    cv::hconcat(aim, aim, sidBySide);
    //cv::vconcat(aim, aim, sidBySide);

    // 9 绘制文字
    cv::putText(
        aim,                    // 目标
        "hello",                // 文字
        cv::Point(50, 50),      // 起始点位置
        cv::FONT_HERSHEY_SIMPLEX, // 字体
        1.0,                    // 大小
        cv::Scalar(0, 255, 0),  // 色彩
        2,                      // 线宽
        cv::LINE_AA             // 线的类型
    );

    // 10 roi
    cv::Mat roi = aim(cv::Rect(10, 10, 200, 200));



    cv::imshow("aim", aim);
    //cv::imshow("sidBySide", sidBySide);
    //cv::imshow("roi", roi);

    cv::waitKey(0);


}
相关推荐
wangqiaowq13 小时前
Ontology 学习
学习
choumou_M14 小时前
算法_1:由浅入深学习快速排序QuickSort
学习·算法·排序算法
Android系统攻城狮19 小时前
Linux FFmpeg深度解析之avio_open调用流程与实战(三十八)
linux·运维·服务器·ffmpeg·音视频进阶·ffmpeg音视频
蒸蒸yyyyzwd19 小时前
后端学习笔记 day111
笔记·学习
叼烟扛炮20 小时前
[LangChain] 学习笔记(08):工具调用底层闭环与第三方搜索(Tavily)实战
人工智能·笔记·学习·langchain
Century_Dragon20 小时前
让新能源故障诊断实训“触手可及“——仿真教学软件(VR)介绍
学习
楚山之石21 小时前
【Radiology】影像组学的标准化与可重复性:IBSI 卷积滤波器共识及其未能覆盖的环节
人工智能·学习·机器学习·mri
小李不想当小白1 天前
HAL库之UART(STM32 HAL库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式
旖旎夜光1 天前
【C++ 基础入门】C++ 多态(中):虚函数表、多态原理与动静绑定
开发语言·c++·笔记·学习