OpenCV 滑动条
📅 2026/7/13 16:18:13
👁️ 阅读次数
📝 编程学习
案例一、通过滑动条修改高、低阈值控制边缘检测
在QuickDemo.h中添加
#pragma once #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; class QuickDemo { void track_bar(); }在主程序main.cpp中调用
#include "QuickDemo.h" #include <iostream> using namespace cv; using namespace std; int main() { QuickDemo qd; qd.track_bar(); }在QuickDemo.cpp中编辑函数主体
Mat src, dst; int minValue = 100;//Canny算法的第三个参数:低阈值 int maxValue = 200;//Canny算法的第四个参数:高阈值 void onChange(int,void*)//2. { Canny(src,dst,minValue,maxValue); imshow("滑动条操作窗口",dst); } /// <summary> /// 滑动条控制 /// </summary> void QuickDemo::track_bar() { //1.加载图片图像数据 src = imread("D:\\img\\image\\004.png"); if (src.empty()) { cout << "图片加载失败";return; } imshow("src",src); /*Mat dst; Canny(src,dst,100,200); imshow("dst",dst);*/ namedWindow("滑动条操作窗口",1); //第一步:创建滑动条,指定依附的窗口,并设置指定的滑动条回调函数 createTrackbar("低阈值","滑动条操作窗口",&minValue,255, onChange,0); createTrackbar("高阈值", "滑动条操作窗口", &maxValue, 255, onChange, 0); while (true) { //imshow("滑动条操作窗口", src); int key = waitKey(20); if (key == 27) break; } src.release(); destroyAllWindows(); }案例二、OpenCV视频+滑动条控制思路
难点1:如何获取总时长、当前时长
解决: 获取视频的帧率,总帧数 视频总时长=总帧数/帧率
int fps = vcp.get(CAP_PROP_FPS);//获取帧率 int frame_count = vcp.get(CAP_PROP_FRAME_COUNT);//总帧数 int second_total = frame_count / fps;//总时长当前时长=当前帧数/帧率
double frame_current = vcp.get(CAP_PROP_POS_FRAMES);//当前帧数 int second_current = frame_current / fps;//当前时长难点2:多次回调,程序崩溃
解决:设置手动拖动锁,自动刷新锁
bool isDragging = false;//用户手动拖动滑块锁
bool autoSyncLock = false; // 代码自动刷新滑块锁
在视频播放while循环中编辑
if (!isDragging) { autoSyncLock = true; //上锁:告知回调这是代码自动刷新 setTrackbarPos("播放进度", "显示视频", (int)frame_current); autoSyncLock = false; //解锁 }在滑动条回调函数中编辑
void on_trackbar_video(int, void*) { if (autoSyncLock) return; //代码自动更新滑块时,直接跳过回调,阻断递归 isDragging = true;//标记正在拖拽,暂停自动刷新 play_video(vcp,frame_current); }难点3:播放、暂停
int isPlay = 1; // 1播放 0暂停,存储滑动条的值 bool isPlayFlag = true; //是否播放在滑动条回调函数中编辑
void on_stop_video(int, void*) { isPlayFlag = (isPlay == 1) ? true : false; }在视频播放while循环中添加
while(true) { if(isPlayFlag) { } }上面是核心代码,下面是全部代码
在QuickDemo.h中添加
void trackbar_video();在主程序main.cpp中调用
QuickDemo qd; qd.trackbar_video();在QuickDemo.cpp中编辑函数主体
/// <summary> /// 返回总时长 /// </summary> /// <param name="seconds"></param> /// <returns></returns> string getDuration(int second_total) { //不超过1小时 int minute = second_total / 60; int second = second_total % 60; string min_str = (minute >= 10) ? to_string(minute) : "0" + to_string(minute); string sec_str = (second >= 10) ? to_string(second) : "0" + to_string(second); return min_str + ':' + sec_str; } /// <summary> /// 根据当前帧数,返回当前播放进度 /// </summary> /// <param name="frame_current"></param> /// <returns></returns> string getCurrentProgress(int frame_current,int fps) { int second_current = frame_current / fps; int minute = second_current / 60; int second = second_current % 60; string min_str = (minute>=10) ? to_string(minute) : "0" + to_string(minute); string sec_str = (second>=10)? to_string(second) : "0" + to_string(second); return min_str + ':' + sec_str; } int frame_current; VideoCapture vcp; bool isDragging = false;//用户手动拖动滑块锁 bool autoSyncLock = false; // 代码自动刷新滑块锁 int isPlay = 1; // 1播放 0暂停,存储滑动条的值 bool isPlayFlag = true; //是否播放 /// <summary> /// 正常从0帧播放视频 /// </summary> /// <param name="vcp"></param> void play_video(VideoCapture vcp) { int fps = vcp.get(CAP_PROP_FPS);//获取帧率 int frame_count = vcp.get(CAP_PROP_FRAME_COUNT);//总帧数 int second_total = frame_count / fps;//总时长 //cout << "帧率:" << fps << "总帧数:" << frame_count << "总时长:" << second_total << endl; while (true) { if(isPlayFlag) { Mat frame;//创建图片数据对象 vcp.read(frame); if (frame.empty()) { break; }//读取为空则结束 //获取当前帧数 double frame_current = vcp.get(CAP_PROP_POS_FRAMES); cout << "当前帧数:"<<frame_current << endl; if (!isDragging) { autoSyncLock = true; //上锁:告知回调这是代码自动刷新 setTrackbarPos("播放进度", "显示视频", (int)frame_current); autoSyncLock = false; //解锁 } string result = getCurrentProgress((int)frame_current, fps) + "/" + getDuration(second_total); result += " fps:" + to_string(fps)+"fps_current:"+ to_string(frame_current); putText(frame, result,Point(30,30),1,2,Scalar(0,0,255),2,8); imshow("显示视频", frame); } int key = waitKey(20); if (key == 27) break; isDragging = false; } vcp.release(); destroyAllWindows(); } /// <summary> /// 从当前帧播放视频 /// </summary> /// <param name="vcp">视频数据</param> /// <param name="frame_current">当前帧</param> void play_video(VideoCapture vcp, double frame_current) { int fps = vcp.get(CAP_PROP_FPS);//获取帧率 int frame_count = vcp.get(CAP_PROP_FRAME_COUNT);//总帧数 int second_total = frame_count / fps;//总时长 cout << "帧率:" << fps << "总帧数:" << frame_count << "总时长:" << second_total << endl; vcp.set(CAP_PROP_POS_FRAMES, frame_current); //校验是否跳转成功(很多时候不会精准跳转到100,会跳到 最近1帧) frame_current = vcp.get(CAP_PROP_POS_FRAMES); cout << "跳转后实际所在帧:" << frame_current << endl; while (true) { if(isPlayFlag) { Mat frame;//创建图片数据对象 vcp.read(frame); if (frame.empty()) { break; }//读取为空则结束 namedWindow("显示视频", WINDOW_FREERATIO);//方便调节大小 //获取当前帧数 frame_current = vcp.get(CAP_PROP_POS_FRAMES); cout << "当前帧数:" << frame_current << endl; if (!isDragging) { autoSyncLock = true; //上锁:告知回调这是代码自动刷新 setTrackbarPos("播放进度", "显示视频", (int)frame_current); autoSyncLock = false; //解锁 } string result = getCurrentProgress((int)frame_current, fps) + "/" + getDuration(second_total); result += " fps:" + to_string(fps) + "fps_current:" + to_string(frame_current); putText(frame, result, Point(30, 30), 1, 2, Scalar(0, 0, 255), 2, 8); imshow("显示视频", frame); } int key = waitKey(20); if (key == 27) break; isDragging = false; } vcp.release(); destroyAllWindows(); } void on_trackbar_video(int, void*) { if (autoSyncLock) return; //代码自动更新滑块时,直接跳过回调,阻断递归 isDragging = true;//标记正在拖拽,暂停自动刷新 play_video(vcp,frame_current); } void on_stop_video(int, void*) { isPlayFlag = (isPlay == 1) ? true : false; } /// <summary> /// 滑动条控制视频播放 /// </summary> void QuickDemo::trackbar_video() { vcp.open("D:\\img\\video\\test.avi"); if (!vcp.isOpened()) { cout << "视频打开失败!"; return; } frame_current = 0; int frame_count = vcp.get(CAP_PROP_FRAME_COUNT);//总帧数 //cout << "总帧数:" << frame_count; namedWindow("显示视频", WINDOW_FREERATIO); createTrackbar("播放进度", "显示视频", &frame_current, frame_count, on_trackbar_video, 0); createTrackbar("播放/暂停","显示视频",&isPlay,1,on_stop_video,0); play_video(vcp); }案例三 滑动条调节图片亮度
在QuickDemo.h中添加
void trackbar_bright();在主程序main.cpp中调用
QuickDemo qd; qd.trackbar_bright();//调节亮度在QuickDemo.cpp中编辑函数主体
int brightness = 0; Mat src = imread("D:\\img\\image\\baboon.jpg"); Mat temp = src.clone();//副本 /// <summary> /// 调节像素 /// </summary> /// <param name="a">原像素</param> /// <param name="b">增、减像素</param> /// <returns></returns> int adjustBright(int a,int b) { if (a + b >= 255) return 255; else if (a + b <= 0) return 0; else return a + b; } void onTrackbar(int, void*) { int width = src.rows; int height = src.cols; for (int i = 0;i < width;i++) { for (int j = 0;j < height;j++) { temp.at<Vec3b>(i, j)[0] = adjustBright(src.at<Vec3b>(i, j)[0], brightness); temp.at<Vec3b>(i, j)[1] = adjustBright(src.at<Vec3b>(i, j)[1], brightness); temp.at<Vec3b>(i, j)[2] = adjustBright(src.at<Vec3b>(i, j)[2], brightness); } } imshow("src", temp); } /// <summary> /// 滑动条调节亮度 /// </summary> void QuickDemo::trackbar_bright() { if (src.empty()) { cout << "图片加载失败!";return; } namedWindow("src", 1); createTrackbar("调节亮度", "src", &brightness, 255, onTrackbar,0); setTrackbarMin("调节亮度", "src",-255); showPic("src", src); waitKey(0); destroyAllWindows(); }文件下载
通过网盘分享的文件:070303img.zip 链接: 百度网盘 请输入提取码 提取码: 772p
文件下载后,修改文件夹名为"img",存放D盘。
以上不足,请同行、业界大佬批评指正。
编程学习
技术分享
实战经验