Opencv4 c++ 自用笔记 03 滑动条、相机与视频操作

1. 相机与视频操作

1.1 打开视频/相机

OpenCV 中 imread() 只能读取静态图像,若要读取视频文件或摄像头流,需要使用 VideoCapture 类:

cpp 复制代码
// 构造函数
cv::VideoCapture::VideoCapture();                      
cv::VideoCapture::VideoCapture(const std::string& filename, int apiPreference = cv::CAP_ANY);  // 打开视频文件,apiPreference为设置属性
cv::VideoCapture::VideoCapture(int index, int apiPreference = cv::CAP_ANY);                     // 打开摄像头,index 为设备 ID

// 或者先默认构造,再调用 open()
VideoCapture cap;
cap.open("example.avi");
cap.open(0);

1.2 读取并播放视频

cpp 复制代码
VideoCapture video("example.avi");
if (!video.isOpened()) {
    std::cerr << "Error: 无法打开视频文件!" << std::endl;
    return -1;
}

double fps = video.get(cv::CAP_PROP_FPS);  // 读取帧率
int delay = static_cast<int>(1000.0 / fps); // 每帧显示时长(毫秒)

while (true) {
    cv::Mat frame;
    video >> frame;                // 读取下一帧到 frame
    if (frame.empty()) break;      // 视频结束或读取失败则退出
    cv::imshow("Video Playback", frame);
    if (cv::waitKey(delay) == 'q') break;
}
video.release();
cv::destroyAllWindows();

2. 视频属性查询

使用 VideoCapture::get(propId) 可以获取视频或摄像头流的各种参数:

Property 参数 ID
当前播放位置(毫秒) CAP_PROP_POS_MSEC (0)
视频宽度 CAP_PROP_FRAME_WIDTH (3)
视频高度 CAP_PROP_FRAME_HEIGHT (4)
帧率 CAP_PROP_FPS (5)
编解码器 CAP_PROP_FOURCC (6)
总帧数 CAP_PROP_FRAME_COUNT (7)
返回图像格式 CAP_PROP_FORMAT (8)
摄像头专属属性
亮度 CAP_PROP_BRIGHTNESS (10)
对比度 CAP_PROP_CONTRAST (11)
饱和度 CAP_PROP_SATURATION (12)
色调 CAP_PROP_HUE (13)
增益 CAP_PROP_GAIN (14)

示例:

cpp 复制代码
double width  = video.get(cv::CAP_PROP_FRAME_WIDTH);
double height = video.get(cv::CAP_PROP_FRAME_HEIGHT);

3. 视频写入与保存

3.1 VideoWriter

cpp 复制代码
// 构造函数
cv::VideoWriter::VideoWriter();
cv::VideoWriter::VideoWriter(const std::string& filename,
                             int fourcc, 
                             double fps, 
                             cv::Size frameSize, 
                             bool isColor = true);

filename :输出文件路径及名称(带后缀)
fourcc :编码格式,使用 VideoWriter::fourcc('M','J','P','G') 等,-1为自动采用合适的编解码器
fps :输出帧率
frameSize :视频分辨率(宽, 高)
isColor :是否彩色(true/false

3.2 保存摄像头视频

cpp 复制代码
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main() {
    VideoCapture cap(0);
    if (!cap.isOpened()) {
        cerr << "Error: 无法打开摄像头!" << endl;
        return -1;
    }

    // 读取第一帧以获取格式
    Mat frame;
    cap.read(frame);
    bool isColor = (frame.type() == CV_8UC3);

    // 配置 VideoWriter
    int codec = VideoWriter::fourcc('M','J','P','G');
    double fps = 30.0;
    Size size(640, 480);
    VideoWriter writer("output.avi", codec, fps, size, isColor);

    if (!writer.isOpened()) {
        cerr << "Error: 无法创建视频写入器!" << endl;
        return -1;
    }

    // 循环读取并写入
    while (1) {
        if (!cap.read(frame) || frame.empty()) {
            cerr << "Error: 无法读取帧或帧为空!" << endl;
            break;
        }
        writer.write(frame);
        imshow("Capture & Save", frame);
        if (waitKey(30) == 'q') {
            cout << "退出程序" << endl;
            break;
        }
    }

    cap.release();
    writer.release();
    destroyAllWindows();
    return 0;
}

4. 窗口交互与滑动条

4.1 创建滑动条

cpp 复制代码
createTrackbar(trackbarName, windowName, &value, maxCount, callback, userdata=0);

trackbarName :滑动条名称
windowName :所属窗口名称
value :滑动条的当前值(整型指针)
maxCount :滑动条最大值
callback :回调函数,每次滑动时调用
userdata:用户自定义数据指针(可选)

4.2 示例:图像阈值调整

cpp 复制代码
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int maxValue = 127;
Mat gray, binary;

void callback(int, void*) {
    adaptiveThreshold(gray, binary, maxValue,
                      ADAPTIVE_THRESH_MEAN_C,
                      THRESH_BINARY, 11, 2);
    imshow("Thresh", binary);
}

int main() {
    string inputPath  = "/home/user/test.jpg";
    string outputPath = "/home/user/outputs.jpg";
    gray = imread(inputPath, IMREAD_GRAYSCALE);
    if (gray.empty()) {
        cerr << "Error: 无法读取输入图像!" << endl;
        return -1;
    }

    namedWindow("Thresh");
    createTrackbar("MaxValue", "Thresh", &maxValue, 255, onTrackbar);

    // 初始显示
    onTrackbar(0, nullptr);

    while (true) {
        char key = (char)waitKey(10);
        if (key == 'q') {
            imwrite(outputPath, binary);
            cout << "结果已保存到: " << outputPath << endl;
            break;
        }
    }

    destroyAllWindows();
    return 0;
}

回调函数签名void callback(int pos, void* userdata);

每次滑动时,pos 为当前滑动位置,可用全局变量或 getTrackbarPos() 获取最新值。

5. 相机图像处理示例

上述代码中实现了利用滑动条调整二值化图像中的阈值,核心在于callback函数对图像的更新。

cpp 复制代码
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int maxValue = 127;
Mat gray, binary;

void callback(int, void*) {
    adaptiveThreshold(gray, binary, maxValue,
                      ADAPTIVE_THRESH_MEAN_C,
                      THRESH_BINARY, 11, 2);
    imshow("Binary", binary);
}

int main() {
    VideoCapture cap(0);
    if (!cap.isOpened()) {
        cerr << "Error: 无法打开摄像头!" << endl;
        return -1;
    }

    namedWindow("Binary");
    createTrackbar("Threshold", "Binary", &maxValue, 255, onTrackbar);

    while (1) {
        Mat frame;
        cap >> frame;
        if (frame.empty()) {
            cerr << "Error: 捕获帧为空!" << endl;
            break;
        }
        // 转灰度并二值化
        cvtColor(frame, gray, COLOR_BGR2GRAY);
        onTrackbar(0, nullptr);  // 初始更新一次
        imshow("Binary", binary);

        if (waitKey(30) == 'q') {
            destroyWindow("Binary");
            break;
        }
    }

    cap.release();
    return 0;
}
相关推荐
AI进化营-智能译站21 小时前
ROS2 C++开发系列11-VS Code一键生成Doxygen注释|让ROS2节点文档自动跟上代码迭代
java·数据库·c++·ai
HERR_QQ21 小时前
端到端课程自用 5 规划 基于Difussion 的端到端planner AI 笔记
人工智能·笔记·学习·自动驾驶
zhouwy1131 天前
Linux文件系统与IO编程
linux·c++
William Dawson1 天前
2026软考中级系统集成项目管理工程师备考笔记
笔记·系统集成项目管理工程师
王老师青少年编程1 天前
csp信奥赛C++高频考点专项训练之贪心算法 --【哈夫曼贪心】:合并果子
c++·算法·贪心·csp·信奥赛·哈夫曼贪心·合并果子
叼烟扛炮1 天前
C++第二讲:类和对象(上)
数据结构·c++·算法·类和对象·struct·实例化
样例过了就是过了1 天前
LeetCode热题100 最长公共子序列
c++·算法·leetcode·动态规划
谭欣辰1 天前
C++ 排列组合完整指南
开发语言·c++·算法
love530love1 天前
精简版|Claude-HUD 插件介绍 + 一键安装教程
人工智能·windows·笔记
想成为优秀工程师的爸爸1 天前
第三十篇技术笔记:郭大侠学UDS - 人有生老三千疾,望闻问切良方医
网络·笔记·网络协议·tcp/ip·信息与通信