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

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.xdnf.cn/news/722917.html

相关文章:

  • DAY 40 训练和测试的规范写法
  • <PLC><socket><西门子>基于西门子S7-1200PLC,实现手机与PLC通讯(通过websocket转接)
  • 每日温度(力扣-739)
  • 零知开源——STM32F407VET6驱动Flappy Bird游戏教程
  • 深兰科技董事长陈海波受邀出席2025苏商高质量发展(常州)峰会,共话AI驱动产业升级
  • LVS-DR 负载均衡集群
  • Spring Boot 整合 Spring Security
  • 后端项目中静态文案国际化语言包构建选型
  • 华为云Flexus+DeepSeek征文 | 基于Dify和DeepSeek-R1开发企业级AI Agent全流程指南
  • 什么是Docker容器?
  • 【Linux 基础知识系列】第三篇-Linux 基本命令
  • 探索C++模板STL
  • Vert.x学习笔记-EventLoop工作原理
  • AI赋能开源:如何借助MCP快速解锁开源项目并提交你的首个PR
  • 机房网络设备操作安全管理制度
  • 历年中国农业大学计算机保研上机真题
  • 深入详解DICOMweb:WADO与STOW-RS的技术解析与实现
  • 如何安全地清洁 Windows10/11PC上的SSD驱动器
  • 系统思考:经营决策沙盘
  • 知识图谱增强的大型语言模型编辑
  • 【Linux】vim编辑器
  • 服务器如何配置防火墙管理端口访问?
  • Ubuntu20.04服务器开启路由转发让局域网内其他电脑通过该服务器连接外网
  • 【仿muduo库实现并发服务器】实现时间轮定时器
  • 戴尔AI服务器订单激增至121亿美元,但传统业务承压
  • 24核32G,千兆共享:裸金属服务器的技术原理与优势
  • VRRP 原理与配置:让你的网络永不掉线!
  • Dify运行本地和在线模型
  • Oracle数据库性能优化的最佳实践
  • 【appium】环境安装部署问题记录