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;
}
相关推荐
西岭千秋雪_2 小时前
计算机网络学习笔记:应用层概述、动态主机配置协议DHCP
笔记·学习·计算机网络
A.A呐2 小时前
【Linux第四章】gcc、makefile、git、GDB
linux·c语言·开发语言·c++·git
懒惰的bit3 小时前
STM32F103C8T6 学习笔记摘要(二)
笔记·stm32·学习
weixin_448119943 小时前
Datawhale 网络爬虫技术入门第2次笔记
笔记·爬虫
struggle20253 小时前
torchmd-net开源程序是训练神经网络潜力
c++·人工智能·python·深度学习·神经网络
xuanzdhc3 小时前
C++重点知识详解(命名空间,缺省参数,函数重载)
开发语言·c++
虾球xz4 小时前
CppCon 2017 学习:Howling at the Moon: Lua for C++ Programmers
开发语言·c++·学习·lua
岑梓铭4 小时前
计算机网络第九章——数据链路层《流量控制和可靠传输》
笔记·计算机网络·考研·408·计网
monicaaaaan5 小时前
旋转图像C++
开发语言·c++
无影无踪的青蛙5 小时前
[C++] STL数据结构小结
开发语言·数据结构·c++