目录
3.7 角点检测 goodFeaturesToTrack()
1 介绍
光流估计是判断移动物体的移动距离与方向
- 亮度恒定,小运动,空间一致 是光流估计的三个前提
下面是我们对之前行人的视频进行光流估计,下面绘制出的白色轨迹就是光流估计的结果
2 Lucas-Kanade算法
光流估计是用这个算法做的
上面这个方程使用的约束条件是亮度一致与小运动
I是某一帧的像素点,x是横坐标,y是纵坐标,t是当前的对应帧数,这个约束方程的意思是,只有当我的点满足这个条件才能用,第二行是泰勒级数展开,我们最终通过约束方程得到了最后这个式子,我们求u和v
当前我们Ix,Iy,It都是已知的,但是现在有两个未知量,现在还求不出来,这个时候我们用到第三个约束条件空间一致,我们下面这个图里有两个红框,这两个红框的u和v一致,所以我们通过(矩阵大小)的平方个方程求解2个未知数(u,v),这样我们就得到了多组解
之后我们使用最小二乘法对多组解进行线性回归,A是(Ix,Iy)这个矩阵,u是u,v这个矩阵,b是It这个矩阵
通常来说角点可逆,非角点不可逆,所以我们每次进行光流估计前需要先进行角点检测
3 代码实现
3.1 导入库
3.2 读视频
3.3 定义角点检测参数
这个不同于 12.harris角点检测,我们在下面调用时会提到
3.4 定义lucas-kanade参数
3.5 定义颜色
这个颜色是在(0,255,3)-(0,255,100)中随机抽取的
3.6 获取第一张图像并做灰度处理
3.7 角点检测 goodFeaturesToTrack()
goodFeaturesToTrack()是harris的增强版,运算速度更快,我们看一下参数
- old_gray 要检测的图片
- mask 掩膜,我们这里不使用掩膜
- maxCorners 返回的最大角点数量,这里我们设置为100,如果该参数值小于等于0则表示不设置最大数量
- qualityLevel 质量等级,这个值越大获得的角点就越少
- misDistance 返回角点之间最小的欧式距离,我们在这里设置为7,也就是在欧式距离为7的范围内,我们选择角点
我们在这里检测出了第一帧的角点,我们下面进入循环后只使用一次第一帧角点
3.8 创建掩膜
掩膜的尺寸和视频中的每一帧尺寸相同,内容全为0(黑)
.9 进入循环
3.9.1 读取每一帧图像并转换其为灰度图
3.9.2 光流估计
我们看一下传入的参数
- old_gray 第一帧图像
- frame_gray 当前图像
- p0 待跟踪的特征点向量,这个就是我们刚刚检测出来的角点
- None 这个是输出跟踪特征点向量,我们使用返回值p1获取它,所以此处我们设置为None
- winSize 搜索窗口大小,上面定义为(15,15)的矩阵
- maxLevel 最大的金字塔层数,在算法中我们使用到了图像金字塔,图像金字塔的层数不超过maxLevel,我们此处设置为2
返回值我们这里写了三个
- p1 输出跟踪特征点向量
- st 特征点状态
- err 报的错
3.9.3 匹配后上升维度
之后我们获取找到的新角点和老角点
st ==1 代表匹配上了,如果匹配上了就讲p1与p0上升一个维度,我们打印出来看一下
- p1
- 带中括号前
- 带中括号后
- p0
- 带中括号前
- 带中括号后
如果st不等于1表示没有追踪成功,这个时候good_new与good_old的值均为[]
3.9.4 绘制轨迹
新点老点压在一起,然后给一个序号,之后开始遍历
遍历第一步,讲多维数组转换为1维数组
ravel()之前我们没接触过,举个例子
import numpy as np
a = np.array([[[[693,83]],[[396,34]]]])
print(a)
print(type(a))
print(a.shape)
print()
b = a.ravel()
print(b)
print(type(b))
print(b.shape)
变为1维数组之后我们将坐标提出来,此时a,b是新点的横纵坐标,c,d是老点的横纵坐标
之后我们在掩膜中用直线连接两个点,颜色是每一组点一个颜色区间在(0,255,3)-(0,255,100),线宽为2
之后我们在图像中画圆,圆心是新点,半径为5,颜色和上面直线一样,-1是线宽的位置,在这里置为-1的意思是将这个圆进行填充
然后将两张图像加和,黑(0)就变成了图像实际的样子,不是黑的就与图像像素值加和
3.9.5 显示
展示图像,如果按ESC则关闭窗口
3.9.6 更新
新图赋值给老图,然后将新点降维后赋值给老点
3.10 关闭
我们看一下效果