摘要:

我学习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()详解的更多相关文章

  1. Hadoop Mapreduce分区、分组、二次排序过程详解[转]

    原文地址:Hadoop Mapreduce分区.分组.二次排序过程详解[转]作者: 徐海蛟 教学用途 1.MapReduce中数据流动   (1)最简单的过程:  map - reduce   (2) ...

  2. (原创)LAMP搭建之二:apache配置文件详解(中英文对照版)

    LAMP搭建之二:apache配置文件详解(中英文对照版) # This is the main Apache server configuration file. It contains the # ...

  3. Velocity魔法堂系列二:VTL语法详解

    一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力.而且Velocity被移植到不 ...

  4. Python学习二:词典基础详解

    作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/7862377.html 邮箱:moyi@moyib ...

  5. Zookeeper系列二:分布式架构详解、分布式技术详解、分布式事务

    一.分布式架构详解 1.分布式发展历程 1.1 单点集中式 特点:App.DB.FileServer都部署在一台机器上.并且访问请求量较少 1.2  应用服务和数据服务拆分  特点:App.DB.Fi ...

  6. Java8初体验(二)Stream语法详解(转)

    本文转自http://ifeve.com/stream/ Java8初体验(二)Stream语法详解 感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com上篇文章Java8初体验(一 ...

  7. Java8初体验(二)Stream语法详解---符合人的思维模式,数据源--》stream-->干什么事(具体怎么做,就交给Stream)--》聚合

    Function.identity()是什么? // 将Stream转换成容器或Map Stream<String> stream = Stream.of("I", & ...

  8. RocketMQ详解(二)安装使用详解

    专题目录 RocketMQ详解(一)原理概览 RocketMQ详解(二)安装使用详解 RocketMQ详解(三)启动运行原理 RocketMQ详解(四)核心设计原理 RocketMQ详解(五)总结提高 ...

  9. Hadoop集群搭建安装过程(二)(图文详解---尽情点击!!!)

    Hadoop集群搭建安装过程(二)(配置SSH免密登录)(图文详解---尽情点击!!!) 一.配置ssh无密码访问 ®生成公钥密钥对 1.在每个节点上分别执行: ssh-keygen -t rsa(一 ...

随机推荐

  1. lightoj 1125 - Divisible Group Sums (dp)

    Given a list of N numbers you will be allowed to choose any M of them. So you can choose in NCM ways ...

  2. 在Linux查看版本命令

    1.在终端中执行下列指令: cat /etc/issue 可以查看当前正在运行的 Ubuntu 的版本号. 2. 使用 lsb_release 命令也可以查看 Ubuntu 的版本号,与方法一相比,内 ...

  3. Python作业本——第4章 列表

    课后习题: 1.[]是一个空列表 2. spam.insert(3, 'hello') 错,应为:spam[2] = 'hello' 3.['d']    'd' 4.['d']    'd' 5.[ ...

  4. mysql之innodb存储引擎---数据存储结构

    一.背景 1.1文件组织架构 首先看一下mysql数据系统涉及到的文件组织架构,如下图所示: msyql文件组织架构图 从图看出: 1.日志文件:slow.log(慢日志),error.log(错误日 ...

  5. Go语言标准库之strconv

    Go语言中strconv包实现了基本数据类型和其字符串表示的相互转换. strconv包 strconv包实现了基本数据类型与其字符串表示的转换,主要有以下常用函数: Atoi().Itia().pa ...

  6. Python数据库小程序

    源代码: # dict1 是 字典 , 用来对应相应元素的下标,我们将文件转成列表,对应的也就是文件的下标,通过下标来找文件元素 dict1 = {'sort':0 , 'name':1 ,'age' ...

  7. SRAM和DRAM的区别

    一.浅谈关于SRAM和DRAM的区别:https://www.cnblogs.com/nano94/p/4014082.html. 二.ROM.RAM.DRAM.SRAM和FLASH的区别,转自:ht ...

  8. Linux 笔记 - 第十四章 LAMP 之(一) 环境搭建

    博客地址:http://www.moonxy.com 一.前言 LAMP 是 Linux Apache MySQL PHP 的简写,即把 Apache.MySQL 以及 PHP 安装在 Linux 系 ...

  9. Redis 的底层数据结构(字典)

    字典相对于数组,链表来说,是一种较高层次的数据结构,像我们的汉语字典一样,可以通过拼音或偏旁唯一确定一个汉字,在程序里我们管每一个映射关系叫做一个键值对,很多个键值对放在一起就构成了我们的字典结构. ...

  10. Google、百度搜索引擎高级应用6/15

    不得不知道的搜索技巧.