前言
上一篇《C++ OpenCV视频操作之KLT稀疏光流对象跟踪(一)》中我们先试过了在每帧图像中先获取特征点,到了了Shi-Tomas特征提取,这章我们就看看KLT稀疏光流跟踪的方法。
视频效果展示
实现原理
首先要在初始帧中检测特征点,之后在下一帧中尝试跟踪这些点。你必须找到新的图像帧中这些点的位置,因此,你必须在特征点的先前位置附近进行搜索,以找到下一帧中它的新位置。输入两个连续的图像帧以及第一幅图像中检测到的特征点数组,该函数将返回一组新的特征点为位置。为了跟踪完整的序列,你需要在帧与帧之间重复这个过程,不可避免地你也会丢失其中一些点,于是被跟踪的特征点数目会减少。为了解决这个问题,我们可以不时地检测新的特征值。
函数API
calcOpticalFlowPyrLK( InputArray prevImg, InputArray nextImg,
InputArray prevPts, InputOutputArray nextPts,
OutputArray status, OutputArray err,
Size winSize = Size(21,21), int maxLevel = 3,
TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01),
int flags = 0, double minEigThreshold = 1e-4 );
参数说明:
prevImg: 第一帧(跟踪图像的前一帧,一般是定位特征点)
nextImg: 第二帧/当前帧
prev_Pts: 第一帧特征点集
next_Pts: 计算输出的第二帧光流特征点集
status : 状态标志位,如果对应特征的光流被发现,数组中的每一个元素都被设置为 1, 否则设置为 0。
err:双精度数组,包含原始图像碎片与移动点之间的误差。
代码演示
我们还是用接着上一章的DEMO,继续往下做
定义基本数据
上面的API也提到我们会检测当前帧和前一帖进行处理,所以我们要先定义关于前一帧及当前帧的一些相关数据,下图红框内就是我们定义的用于处理的基本数据。
然后在检测到特征点后判断前一帧灰度图是否存在,如果不存在先复制过来
检测新的特征点
上面红线标的就是我闪可能在检测过程中出现的问题,所以我们这里也要改造一下检测,用我们定义的ftps的参数里面设置一个数值,用于检测如果数值小于我们设置的数后就重新检测特征点。我们改造一下寻找特征点这块。
先放一下原先的检测代码,红框部分是我们要改造地部分
下面这张是我们改造后的源代码
上面可以看出,我们把检测出的特征点数组存放到了fpts[0]中,当前一帧的特征点小于30后我们将重新检测,然后把检测出的结果存放到前一帧fpts[0]和初始化的特征点IniPoints里,最后再打印一个字符,可以从命令行里看到当前状态是在检测特征点,当特征点大于30时我们就打印一个检测的字符。
实现稀疏光流跟踪
首先我们先在最上方定义一个HLK跟踪的方法及跟踪成功的状态和误差参数
然后我们在写这个方法,这里就用到了我们的calcOpticalFlowPyrLK函数API
然后在上面的跟踪那里加入这个方法
绘制源图
最后在源图上画出特征点并把当前帧数据放到前一帧里,由于我们把前一帧数据已经转移到了fpts[0]里,所以这里也改为过来,然后我们又加入了画出直线的一个操作,用于观察移动的原点与现在的一个距离。
下面是视频中的截图
**-END-
**
Vaccae的往期经典
OpenCV
Android
《Android利用SurfaceView结合科大讯飞修改语音实别UI》
《Android关于语音识别的功能实现分析(一)---结构化思维》
《Android关于语音识别的功能实现分析(二)---语义解析》
.Net C#
数据库及其它
长按下方二维码关注微卡智享
本文分享自微信公众号 - 微卡智享(VaccaeShare)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。