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;
}
相关推荐
?!7141 小时前
Socket编程之TCP套件字
linux·网络·c++·网络协议·tcp/ip
小指纹2 小时前
2025山东CCPC题解
c++·算法
流年viv3 小时前
数据分析学习笔记——A/B测试
笔记·学习·数据分析·统计原理
技术程序猿华锋3 小时前
Void:免费且隐私友好的 AI 编码利器,挑战 Cursor 地位?
c++·人工智能·mfc
倔强的石头1064 小时前
【C++指南】C++ list容器完全解读(二):list模拟实现,底层架构揭秘
c++·架构·list
木子.李3476 小时前
数据结构-算法学习C++(入门)
数据库·c++·学习·算法
Y学院7 小时前
Vue 技术文档
vue.js·笔记·学习
DIY机器人工房7 小时前
[9-2] USART串口外设 江协科技学习笔记(9个知识点)
笔记·科技·stm32·单片机·学习·江协科技
半青年7 小时前
IEC61850规约客户端软件开发实战(第二章)
java·c++·qt·网络协议·c#·信息与通信·iec61850
moz与京8 小时前
【数据结构】字符串操作整理(C++)
开发语言·数据结构·c++