光流原理
图像目标位置识别到以后,由于每次识别需要花费的时间较长,用每帧识别方式对于视频中目标的实时检测是不合理的,为了提高速度与实时位置输出效率,需要引入实时跟踪算法,Tracking。跟踪Tracking中最常见的使用方法是光流法。
光流的概念是Gibson在1950年首先提出来的。它是空间运动物体在观察成像平面上的像素运动的瞬时速度,是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的一种方法。一般而言,光流是由于场景中前景目标本身的移动、相机的运动,或者两者的共同运动所产生的。其计算方法可以分为三类:(1)基于区域或者基于特征的匹配方法;(2)基于频域的方法;(3)基于梯度的方法。简单来说,光流是空间运动物体在观测成像平面上的像素运动的“瞬时速度”。光流的研究是利用图像序列中的像素强度数据的时域变化和相关性来确定各自像素位置的“运动”。研究光流场的目的就是为了从图片序列中近似得到不能直接得到的运动场。
光流估计就是指利用时间上相邻的两帧图像,得到点的运动。满足以下几点假设:
- 前后两帧点的位移不大(泰勒展开)
- 外界光强保持恒定。
- 空间相关性,每个点的运动和他们的邻居相似(连续函数,泰勒展开)
光流原理与L-K光流估计可参照:https://xmfbit.github.io/2017/05/03/cs131-opticalflow/
OpenCV实现
opencv中光流法的函数calcOpticalFlowPyrLK函数使用。
calcOpticalFlowPyrLK(prevImg,nextImg,prevPts,nextPts,status,err)
prevImg(输入):深度为8位的前一帧图像
nextImg(输入):和prevImg有相同的大小和类型的后一帧图像(可以看到一次光流就是在两针图像之间找不同)。
prevPts(输入):是前一帧图像中的2D特征点,这个特征点必须自己去找,所以在使用calcOpticalFlowPyrLK函数的时候,前面需要有一个找特征点的操作。那么一般就是找图像的角点,就是一个像素点与周围像素点都不同的那个点,这个角点特征点的寻找,opencv也提供函数:goodFeatureToTrack()。
nextPts(输出):参数就是计算前一帧特征点在后一帧中的新的位置。
status(输出):输出状态矢量(元素是无符号char类型,uchar),如果相应特征点的流发现则矢量元素置为1,否则为0。
error(输出):误差。
关于特征角点检测函数goodFeatureToTrack()
goodFeaturesToTrack(image,corners,maxCorners,qualityLevel,minDistance):顾名思义找到好的特征点
image(输入):8位或32位单通道灰度图像;
corners(输出):输出的位置点向量,保存的是检测到角点的坐标,每一个元素就是一个特征点的位置。
maxCorners(输入,设定最具特征的corners数量):规定的特征点最大数目,例如一副图像你可以找到很多特征点,但是只是取前maxCorners个具有最大特征的那些点作为最后的特征点,至于怎么判断哪些点的特征更好了,opencv自有一个机制。
qualityLevel(输入):检测到的角点的质量等级,角点特征值小于qualityLevel*最大特征值的点将被舍弃。
minDistance:特征点与点之间的最小距离,一般我们如果想特征点尽量分散一些,太密集了肯定不好,可以通过这个参数。