计算机视觉(二)-opencv之createTrackbar()详解
摘要:
我学习openCV3看的是《学习openCV3》这本书,很厚的一本,不知道是不是因为自己看的还不是很多,个人觉得里面的有些重要函数讲的不是很详细,比如createTrackbar()这个函数,这个函数出现在这本书的第三个实例程序,书中只是说明了这是一个创建滚动条的程序,然而对里面的参数讲解以及与他相对应的回调函数讲解都不是很完美,因此我就打开了它的定义以及到网上找了一些博主的文章来学习,但是感觉讲的都不是很全,下面我结合自己的实验加上自己的理解,讲解一下我对这个函数的看法。
函数说明:
createTrackbar()函数的函数原型为:
CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname,int* value, int count,TrackbarCallback onChange = 0, void* userdata = 0);
trackbarname:这个参数用来给这个滚动条取一个名字;
winname:这个参数用来指定你要吧这个滚动条用到那个窗口上;
value:这个参数用来设置滑块初始值位置,同时记录滑块以后的位置;
count:这个参数用来指定滚动条可以滚动的最大值;
onChange:这个参数可以理解为一个函数类型的变量(当然这样说感觉有点怪),用来接收回调函数函数名的,默认值为0;
userdata:这个变量这个参数是用户传给回调函数的数据,用来处理轨迹条事件,默认值为0。
这里面一共有6个参数,其中value这个参数容易理解有偏差,onchange,userdata这俩参数可能难以理解;
下面先说我对value这个参数的看法:
value这个参数首先要知道它是用来给滑块位置一个初始值的,也就是告诉我们滑块最初位置在哪,而不是滑块可以滑动范围的最小值,滑块可以滑动的范围永远都是[0, count],count即为第四个参数,然后还要理解一个概念,代码运行过程中,不是value的值影响滑块的位置,而是由于用户对滑块的移动改变了value的值,也就是说value是被动的。
然后在说对onChange该参数的理解:
首先我们看一下回调函数的函数原型:
void (*TrackbarCallback)(int pos, void* userdata);
当我们没看回调函数原型时可能很难理解有些代码中定义回调函数时为什么必须要有那俩参数,当看了回调函数原型后我相信有C++基础的人也都能明白了,那么我来说说回调函数和createTrackbar()函数的关系;首先,我们看到回调函数和createTrackbar函数都有一个形参名为userdata,那这是不是巧合呢?答案当然不是,你可以这样理解,回调函数是一个必须依托于createTrackbar()函数而使用的函数,他不能单独拿来使用,那他的两个形参是怎么用的呢?首先第一个形参pos,它表示的是当前滑块所在的位置,它的值是createTrackbar()传给他的,也就是createTrackbar()形参value的值,这个传输过程是在createTrackbar()内部实现的,无需深究,然后回调函数形参userdata的值就是通过createTrackbar()的形参userdata直接得到的,所以createTrackbar()的形参userdata其实就是专门给回调函数准备的。
函数的使用上的问题:
createTrackbar()在使用上可能也会比较神奇,比如说你可能看到如下程序:
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <imgproc.hpp> using namespace std;
using namespace cv; //TrackBar发生改变的回调函数
void onChangeTrackBar(int pos, void* userdata); //主函数
int main()
{
//trackbar的值
int posTrackBar = ;
//trackbar的最大值
int maxValue = ; //读入图像,以灰度图形式读入
Mat img = imread("F:\\图片\\timg.jpg", ); //新建窗口
namedWindow("二值化");
imshow("二值化", img); //创建trackbar,我们把img作为数据传进回调函数中
createTrackbar("pos", "二值化", &posTrackBar, maxValue, onChangeTrackBar, &img); waitKey(); return ;
} // 回调函数
void onChangeTrackBar(int pos, void* usrdata)
{
// 强制类型转换
Mat src = *(Mat*)(usrdata);
Mat dst; // 二值化
threshold(src, dst, pos, , );
imshow("二值化", dst);
}
上面这个是一个很简单的用于图像二值化处理的代码,当你运行它时你会神奇的发现,这里面没有一个循环,但是你却可以一直滑动滚动条的滑块,而且图像会出现相应的变化,如图滑块到不同位置的效果:
这里其实是靠createTrackbar事件处理得到的,学过一点计算机的人就可以理解为该函数其实一直运行在后台检测是否有滑块移动这种中断产生,然后当你移动滑块时就会触发中断,这时回调函数就相当于中断服务函数来处理中断(不完全准确但是可以这么理解,就像牛顿的经典定律,不是完全准确的描述这个世界,但是在宏观层面来说,用来理解世界是很好的定律)。
结语:
以上全是我个人通过实验验证过的,如果有什么不对的地方,欢迎大家评论区指出。最后附上一些测试用代码:
视频的连续播放,进度可调:
#include <opencv.hpp>
#include<iostream> using namespace std; int g_slider_position = ;
int g_run = , g_dontset = ;
cv::VideoCapture g_cap; void onTrackbarSlide(int pos, void *) {
g_cap.set(cv::CAP_PROP_POS_FRAMES, pos);
if (!g_dontset) {
g_run = ;
} g_dontset = ;
} int main() {
cv::namedWindow("show_video", );
g_cap.open("F:\\图片\\123.mp4");
int frames = (int)g_cap.get(cv::CAP_PROP_FRAME_COUNT);
int tmpw = (int)g_cap.get(cv::CAP_PROP_FRAME_WIDTH);
int tmph = (int)g_cap.get(cv::CAP_PROP_FRAME_HEIGHT);
cout << "Video has" << frames << "frames of dimensions(" << tmpw << "," << tmph << ")." << endl;
cv::createTrackbar("Position", "show_video", &g_slider_position, frames, onTrackbarSlide);
cv::Mat frame;
while () {
if (g_run != ) {
g_cap >> frame;
if (frame.empty()) {
break;
}
int current_pos = (int)g_cap.get(cv::CAP_PROP_POS_FRAMES);
g_dontset = ; cv::setTrackbarPos("Position", "show_video", current_pos);
cv::imshow("show_video", frame); g_run = -;
}
char c = (char)cv::waitKey();
if (c == 's') {
g_run = ;
cout << "Single step,run = " << g_run << endl;
}
if (c == 'r') {
g_run = -;
cout << "Run mode,run" << g_run << endl;
}
if (c == ) {
cv::destroyWindow("show_video");
break;
}
}
cv::destroyWindow("show_video");
return ;
}
计算机视觉(二)-opencv之createTrackbar()详解的更多相关文章
- Hadoop Mapreduce分区、分组、二次排序过程详解[转]
原文地址:Hadoop Mapreduce分区.分组.二次排序过程详解[转]作者: 徐海蛟 教学用途 1.MapReduce中数据流动 (1)最简单的过程: map - reduce (2) ...
- (原创)LAMP搭建之二:apache配置文件详解(中英文对照版)
LAMP搭建之二:apache配置文件详解(中英文对照版) # This is the main Apache server configuration file. It contains the # ...
- Velocity魔法堂系列二:VTL语法详解
一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力.而且Velocity被移植到不 ...
- Python学习二:词典基础详解
作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/7862377.html 邮箱:moyi@moyib ...
- Zookeeper系列二:分布式架构详解、分布式技术详解、分布式事务
一.分布式架构详解 1.分布式发展历程 1.1 单点集中式 特点:App.DB.FileServer都部署在一台机器上.并且访问请求量较少 1.2 应用服务和数据服务拆分 特点:App.DB.Fi ...
- Java8初体验(二)Stream语法详解(转)
本文转自http://ifeve.com/stream/ Java8初体验(二)Stream语法详解 感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com上篇文章Java8初体验(一 ...
- Java8初体验(二)Stream语法详解---符合人的思维模式,数据源--》stream-->干什么事(具体怎么做,就交给Stream)--》聚合
Function.identity()是什么? // 将Stream转换成容器或Map Stream<String> stream = Stream.of("I", & ...
- RocketMQ详解(二)安装使用详解
专题目录 RocketMQ详解(一)原理概览 RocketMQ详解(二)安装使用详解 RocketMQ详解(三)启动运行原理 RocketMQ详解(四)核心设计原理 RocketMQ详解(五)总结提高 ...
- Hadoop集群搭建安装过程(二)(图文详解---尽情点击!!!)
Hadoop集群搭建安装过程(二)(配置SSH免密登录)(图文详解---尽情点击!!!) 一.配置ssh无密码访问 ®生成公钥密钥对 1.在每个节点上分别执行: ssh-keygen -t rsa(一 ...
随机推荐
- 详解RMQ-ST算法 ST模板
RMQ问题是求解区间最值的问题. 这里分析的是ST算法,它可以对所有要处理的数据做到O(nlogn)的预处理,对每个区间查询做到O(1)查询 ST算法本质是一个DP的过程 这里通过举一个求最大值实例来 ...
- codeforces 768 C. Jon Snow and his Favourite Number(思维+暴力)
题目链接:http://codeforces.com/contest/768/problem/C 题意:给出n个数,k个操作,和一个x,每次操作先排序然后对奇数位数进行xor x操作,最后问k次操作后 ...
- (六十)c#Winform自定义控件-鼓风机(工业)
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...
- C#开发BIMFACE系列24 服务端API之获取模型数据9:获取单个房间信息
系列目录 [已更新最新开发文章,点击查看详细] 大厦建筑模型中,基本上包含多个楼层,每个楼层包含多个房间等信息.在<C#开发BIMFACE系列21 服务端API之获取模型数据6:获取单模 ...
- GA,RC,Alpha,Beta,Final等软件版本名词释义
对应上图的表格如下: 名词 说明 Alpha α是希腊字母的第一个,表示最早的版本,内部测试版,一般不向外部发布,bug会比较多,功能也不全,一般只有测试人员使用. Beta β是希腊字母的第二个,公 ...
- SpringBoot 2.0 + Apache Dubbo 2.7.3 最新版整合方案
前言 2018年2月16日,Apache Dubbo 加入 Apache 基金会孵化器.2019年5月16日,Apache 软件基金会董事会决议通过了 Apache Dubbo 的毕业申请,这意味着 ...
- (一)ArrayList集合源码解析
一.ArrayList的集合特点 问题 结 论 ArrayList是否允许空 允许 ArrayList是否允许重复数据 允许 ArrayList是否有序 有序 ArrayList是否线程安全 ...
- [翻译] .NET Core 3.0 RC 1 发布
原文: Announcing .NET Core 3.0 Release Candidate 1 今天,我们宣布推出 .NET Core 3.0 Release Candidate 1.就像 Prev ...
- Python3 爬虫之 Scrapy 核心功能实现(二)
博客地址:http://www.moonxy.com 基于 Python 3.6.2 的 Scrapy 爬虫框架使用,Scrapy 的搭建过程请参照本人的另一篇博客:Python3 爬虫之 Scrap ...
- HashMap浅析
一.概述 HashMap,基于哈希结构的Map接口的一个实现,无序,允许null键值对,线程不安全的.可以使用集合工具类Collections中的synchronizedMap方法,去创建一个线程安全 ...