如何用OpenCV跟踪鼠标操作

在视频第一帧手动标记出目标的位置是在线视觉跟踪中最基本的一个操作,实现这个操作需要检测鼠标的移动和点击事件。OpenCV提供了setMouseCallback这个函数来响应鼠标的动作,并返回鼠标在绑定窗口上的坐标位置。下面就这个函数的使用做一个简单的介绍。

首先,setMouseCallback的C++函数声明如下:

1
C++: void setMouseCallback(const string& winname, MouseCallback onMouse, void* userdata=0 )

  • winname是窗口的名称
  • onMouse是响应事件的函数
  • userdata可选项,是用户提供给onMouse响应函数的指针。

Read More

Lucas-Kanade(LK)算法原理介绍及OpenCV代码实现分析

Lucas-Kanade跟踪算法是视觉跟踪中一个很经典的基于点的逐帧跟踪算法。起初这个算法是用来求解stero matching1的,后来经过Carlo Tomasi2和Jianbo Shi3等人的发展渐趋成熟。Jianbo Shi提出了一种筛选跟踪点特征的方法,使得特征的跟踪更可靠。Jean-Yves Bouguet4详细阐述了如何采用金字塔方式实现LK算法以处理两帧之间特征点位移较大的情况。

问题阐述

首先我们来看一下我们要解决的问题是什么?LK算法是基于特征点的跟踪,而这里的特征点就是每个点对应的一个小窗口图像块,LK所要解决的是求解连续两帧图像相同特征点的位移问题。这里我们假设\(I\)\(J\)为连续两帧图像,其\((x,y)\)点的灰度值分别对应\(I(x,y), J(x,y)\)。设\(\mathbf{u}=[u_x,u_y]^T\)是图像\(I\)上一点,LK算法的目标是在图像\(J\)找到一点\(\mathbf{v}= \mathbf{u} + \mathbf{d} = [u_x+d_x,u_y+d_y]^T\)使得点\(I(\mathbf{u})\)和点\(J(\mathbf{v})\)是同一个位置。为了求解这样的点,LK求解这两个点对应的小窗口内像素的相似度。设\(\omega_x\)\(\omega_y\)分别是点左右扩展的窗口范围,这样我们可以定义如下residual function为

\[\epsilon(\mathbf{d})=\epsilon(d_x,d_y)=\sum_{x=u_x-\omega_x}^{u_x+\omega_x}\sum_{y=u_y-\omega_y}^{u_y+\omega_y}(I(x,y)-J(x+d_x,y+d_y))^2\]

窗口大小为\((2\omega_x+1)\times (2\omega_y+1)\),通常情况下\(\omega_x\)\(\omega_y\)的值为2,3,4,5,6,7。

Read More

OpenCV系列(三):Mat详解

Mat类是OpenCV最基本的一个数据类型,它可以表示一个多维的多通道的数组。Mat常用来存储图像,包括单通道二维数组——灰度图,多通道二维数组——彩色图。当然也可以用来存储点云,直方图等等,对于高维的数组可以考虑存储在SparseMat中。对于一个Mat对象M,其数据布局是由M.step[]决定的,数据存放在M.data里面,假设M有d维,则数据的寻址方式为:

\[addr(M_{i_0,...,i_{d-1}}) = M.data + i_0*M.step[0] + ... + i_{d-1}*M.step[d-1] \]

例如\(Img\)是一个二维三通道矩阵,则,

\[addr(Img_{i_0,i_1}) = M.data + i_0*M.step[0] + i_1*M.step[1] \]

这里需要说明的是各个维度的步长满足如下关系:M.step[i] >= M.step[i+1]*M.size[i+1],也就是二维数组的数据的存放是一行一行的,三维数组数据存放是一面一面的。

Read More

如何在CodeBlocks和Qt Creator开发环境下使用OpenCV(Ubuntu12.04)

自从切换到ubuntu系统后,就一直在寻找合适的C++开发环境。看了网上的一些介绍,大体就这么几个选择:Eclipse, CodeBolocksQt Creator。后来自己试用了一下CodeBlocks和Qt Creator,感觉这两个开发环境还是不错,打开速度都很快。但是由于CodeBlocks的Find declaration功能针对OpenCV老是不灵,这让我很不爽,所以果断换掉去尝试Qt Creator。Qt Creator给人焕然一新的感觉,界面简洁,布局合理,常用的功能在左侧排列,不会给人杂乱的感觉。

因为要开发OpenCV项目,所以首先需要知道开发环境配置第三方库的方法。虽然最后没有选择CodeBlocks,但是毕竟也摸索过一段时间,这里以OpenCV为实例一并介绍其如何配置第三方库。

CodeBlocks下配置OpenCV

CodeBlocks的安装主要可以参考官网的教程。主要两种方式,一是下载源代码,自己编译安装;再就是安装别人编译好的,对于ubuntu系统参考这里。把这个源加入自己的系统,即执行

sudo add-apt-repository ppa:pasgui/ppa

然后执行

sudo apt-get install codeblocks 

这样 就可以CodeBlocks就安装好了。

Read More

OpenCV系列(二):基本数据结构

常用的OpenCV数据结构像Mat,Point等我们并不陌生,但最近仔细阅读OpenCV手册后发现有些数据结构的一些便捷操作以及一些新加入的功能自己并没有掌握,这里做个记录算是学习笔记。

众多的类模板

我们平时常用的数据结构像Point,Rect其实是类模板某一数据类型的实例。比如Point对应Point_<int>Rect对应Rect_<int>。 这里就简单罗列一下Point对应的定义:

1
2
3
4
typedef Point_<int> Point2i;
typedef Point2i Point;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;

而且,Point也重载了加减乘除等操作运算符,比如:

1
2
3
4
5
6
7
Point pt1,pt2,pt3;
int a;
pt1 = pt2 + pt3, pt1 = pt2 - pt3;
pt1 = pt2 * a, pt1 = a * pt2;
pt1 += pt2, pt1 -= pt2, pt1 *= a;
double value = norm(pt); // L2 norm
pt1 == pt2, pt1 != pt2;

Read More