当前位置: 首页 > article >正文

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

1. 相机与视频操作

1.1 打开视频/相机

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

// 构造函数
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 读取并播放视频

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;                // 读取下一帧到 frameif (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)

示例:

double width  = video.get(cv::CAP_PROP_FRAME_WIDTH);
double height = video.get(cv::CAP_PROP_FRAME_HEIGHT);

3. 视频写入与保存

3.1 VideoWriter

// 构造函数
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 保存摄像头视频

#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);// 配置 VideoWriterint 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 创建滑动条

createTrackbar(trackbarName, windowName, &value, maxCount, callback, userdata=0);

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

4.2 示例:图像阈值调整

#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函数对图像的更新。

#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;
}
http://www.lryc.cn/news/2395661.html

相关文章:

  • LINUX528 重定向
  • 研华工控机安装Windows10系统,适用UEFI(GPT)格式安装
  • 1、树莓派更换软件下载源
  • 历年中山大学计算机保研上机真题
  • Python----目标检测(《SSD: Single Shot MultiBox Detector》论文和SSD的原理与网络结构)
  • springboot集成websocket给前端推送消息
  • DrissionPage SessionPage模式:轻量级HTTP请求的利器
  • 0527漏洞原理:XSS笔记
  • 智能制造之精读——RPA制造行业常见场景【附全文阅读】
  • spark shuffle的分区支持动态调整,而hive不支持
  • 网络安全十大漏洞
  • 关于uv 工具的使用总结(uv,conda,pip什么关系)
  • 深入剖析 Docker 容器化原理与实战应用,开启技术新征程!
  • Xamarin劝退之踩坑笔记
  • 计算机网络(4)——网络层
  • java 多线程中的volatile关键字作用
  • ESP32基础知识1:项目工程建立和烧录
  • allWebPlugin中间件VLC专用版之录像功能介绍
  • Vim 支持多种编程语言编辑器
  • 解决 IDEA 在运行时中文乱码问题
  • Diffusion Planner:扩散模型重塑自动驾驶路径规划(ICLR‘25)
  • 华为OD机试真题——阿里巴巴找黄金宝箱 IV(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
  • 数据结构:时间复杂度(Time Complexity)和空间复杂度(Space Complexity)
  • CentOS7.9环境离线部署docker和docker-compose的两种方式
  • 北京大学肖臻老师《区块链技术与应用》公开课:06-BTC-网络
  • SSL/TLS 协议详解:安全通信的基石
  • 设计模式——外观设计模式(结构型)
  • Linux `vi/vim` 编辑器深度解析与高阶应用指南
  • ES中must与filter的区别
  • qt之开发大恒usb3.0相机三