摘要:

我学习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. HDU 1173 采矿

    采矿 题解:如果给你一条线段(左右端点设为A,B), 那么在这条线上的任意一点到A B距离之和是一个定值, 然后如果再这条线段内在任意确定一个定点C, 那么这条线段上再任意取一个点,这个点到 A B ...

  2. 【3】Decision tree(决策树)

    前言 Decision tree is one of the most popular classification tools 它用一个训练数据集学到一个映射,该映射以未知类别的新实例作为输入,输出 ...

  3. .NetCore技术研究-ConfigurationManager在单元测试下的坑

    最近在将原有代码迁移.NET Core, 代码的迁移基本很快,当然也遇到了不少坑,重构了不少,后续逐步总结分享给大家.今天总结分享一下ConfigurationManager遇到的一个问题. 先说一下 ...

  4. 【原创】(四)Linux内存模型之Sparse Memory Model

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  5. 一篇RPO漏洞挖掘文章翻译加深理解。

    这是我第一次尝试翻译一篇漏洞挖掘文章,翻译它也是为了加深理解它.这是一篇很有意思的漏洞挖掘文章. 前几天在看fd的博客,偶然看到了这篇文章,虽然有点老了.但是思路真的牛皮.我决定花费时间和精力研究它们 ...

  6. 在asp.net core中使用托管服务实现后台任务

    在业务场景中经常需要后台服务不停的或定时处理一些任务,这些任务是不需要及时响应请求的. 在 asp.net中会使用windows服务来处理. 在 asp.net core中,可以使用托管服务来实现,托 ...

  7. zookeeper学习(一)_简介

    上篇文章 我们已经安装上了zookeeper,也简单的体验了一把,但是如果让你给别人介绍下zookeeper,可能也是说不出来.本篇文章就参考了网上各位优秀博主的文章,整理出自己更能理解的内容 优秀博 ...

  8. 开源导入导出通用库Magicodes.ExporterAndImporter发布

    导入导出通用库 Magicodes.ExporterAndImporter为心莱团队封装的导入导出通用库,并且仍在跟随项目不断地打磨. GitHub地址: https://github.com/xin ...

  9. Thinkphp5.0 仿百度糯米 开发多商家 电商平台(完整版)

    目录第1章 课程简介第2章 需求分析第3章 快速掌握thinkphp5第4章 任性的TP5模块第5章 生活服务分类管理模块第6章 百度地图应用封装第7章 打造属于TP5自己的发送邮件服务第8章 商户模 ...

  10. 002:CSS基础

    注意:蓝色 重要:红色 目录: 1. 学会使用CSS选择器: 9大选择器.交集选择器.并集选择器.后代选择器.子代选择器.伪类选择器. 2.font.color.横向竖向居中.文本修饰.首行缩进. f ...