计算机视觉-光流估计(附python代码)
光流估计
光流是空间运动物体在观测成像平⾯上的像素运动的“瞬时速度”,根据各个像素点的速度⽮量特征,可以对图像进⾏动态分析,例如⽬标跟踪。
- 亮度恒定:同⼀点随着时间的变化,其亮度不会发⽣改变。
- ⼩运动:随着时间的变化不会引起位置的剧烈变化,只有⼩运动情况下才能⽤前后帧之间单位位置变化引起的灰度变化去近似灰度对位置的偏导数。
- 空间⼀致:⼀个场景上邻近的点投影到图像上也是邻近点,且邻近点速度⼀致。因为光流法基本⽅程约束只有⼀个,⽽要求x,y⽅向的速度,有两个未知变量。所以需要连⽴n多个⽅程求解。光流估计
Lucas-Kanade 算法
如何求解⽅程组呢?看起来⼀个像素点根本不够,在物体移动过程中还有哪些特性呢?
cv2.calcOpticalFlowPyrLK():
参数:
-prevImage 前⼀帧图像
-nextImage 当前帧图像
-prevPts 待跟踪的特征点向量
-winSize 搜索窗⼝的⼤⼩(注意窗⼝的⼤⼩选择,窗⼝太⼤会违背空间⼀致性假设,太⼩⼜会追踪不到窗⼝外的点。)-maxLevel 最⼤的⾦字塔层数
返回:
-nextPts 输出跟踪特征点向量
-status 特征点是否找到,找到的状态为1,未找到的状态为0
import numpy as np
import cv2
cap = cv2.VideoCapture('test.avi')
# ⾓点检测所需参数
feature_params =dict( maxCorners =100,
qualityLevel =0.3,
minDistance =7)
# lucas kanade参数
lk_params =dict( winSize =(15,15),
maxLevel =2)
# 随机颜⾊条
color = np.random.randint(0,255,(100,3))
# 拿到第⼀帧图像
ret, old_frame = ad()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
# 返回所有检测特征点,需要输⼊图像,⾓点最⼤数量(效率),品质因⼦(特征值越⼤的越好,来筛选)
财务能力# 距离相当于这区间有⽐这个⾓点强的,就不要这个弱的了
p0 = dFeaturesToTrack(old_gray, mask =None,**feature_params)
# 创建⼀个mask
mask = np.zeros_like(old_frame)
while(True):
ret,frame = ad()
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 需要传⼊前⼀帧和当前图像以及前⼀帧检测到的⾓点
p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0,None,**lk_params)
# st=1表⽰
good_new = p1[st==1]
good_old = p0[st==1]
# 绘制轨迹
for i,(new,old)in enumerate(zip(good_new,good_old)):
a,b = new.ravel()
桌面壁纸日历
c,d = old.ravel()走一步算一步
mask = cv2.line(mask,(a,b),(c,d), color[i].tolist(),2)
frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)
img = cv2.add(frame,mask)
楚辞中最唯美的名字女
cv2.imshow('frame',img)
k = cv2.waitKey(150)&0xff
if k ==27:
break
# 更新
old_gray = py()
p0 = shape(-1,1,2)广东省旅游攻略
cv2.destroyAllWindows()
其实光流估计是对检测到的⾓点进⾏跟踪,所以,⾓点检测所需参数feature_params = dict( maxCorners = 100,qualityLevel = 0.3, minDistance = 7)中maxCorners不能太⼤,⾓点数量太⼤,可能达不到实时的效果。
函数讲解:
a是⼀个ndarray(n维数组),翻译过来应该数组更容易理解⼀点吧。
就是将这个ndarray⾥⾯的元素全变为0,看代码就能懂
In [1]: a = np.arange(24).reshape(4,6)
车之巨人... a_0 = np.zeros_like(a)
... a.shape
... a_0.shape
... a_0
Out [1]:(4,6)
Out [1]:(4,6)
Out [1]: array([[0,0,0,0,0,0],
缩阴法[0,0,0,0,0,0],
[0,0,0,0,0,0],
[0,0,0,0,0,0]])
顾名思义这个函数的意思就是⽣成⼀个和你所给数组a相同shape的全0数组。
enumerate() 函数:
描述:enumerate() 函数⽤于将⼀个可遍历的数据对象(如列表、元组或字符串)组合为⼀个索引序列,同时列出数据和数据下标,⼀般⽤在for 循环当中。
语法:enumerate(quence, [start=0])
参数:quence – ⼀个序列、迭代器或其他⽀持迭代对象。start – 下标起始位置。
返回值: enumerate(枚举) 对象。
实例:
>>>asons =['Spring','Summer','Fall','Winter']
>>>list(enumerate(asons))
[(0,'Spring'),(1,'Summer'),(2,'Fall'),(3,'Winter')]
>>>list(enumerate(asons, start=1))# 下标从 1 开始
[(1,'Spring'),(2,'Summer'),(3,'Fall'),(4,'Winter')]
普通的for循环:
>>>i =0
>>> q =['one','two','three']
>>>for element in q:
...print i, q[i]
... i +=1
.白雪公主的故事文字版
..
0 one
1 two
2 three
for 循环使⽤ enumerate:
>>>q =['one','two','three']
>>>for i, element in enumerate(q):
...print i, element
...
0 one
1 two
2 three
cv2.line()函数:
img = cv2.line(img, pt1, pt2, color[, thickness[, lineType[, shift]]])
img:背景图
pt1:直线起点坐标
pt2:直线终点坐标
color:当前绘画的颜⾊。如在BGR模式下,传递(255,0,0)表⽰蓝⾊画笔。灰度图下,只需要传递亮度值即可。
thickness:画笔的粗细,线宽。若是-1表⽰画封闭图像,如填充的圆。默认值是1。
lineType:线条的类型
cv.circle()函数:
img = cv2.circle(img, center, radius, color[, thickness[, lineType[, shift]]])
img,背景图
center,圆⼼
radius,半径
color,颜⾊
thickness,线粗细
numpy tolist()函数:
可以将数组或者矩阵转换成列表。
>>> a1 =[[1,2,3],[4,5,6]]# a1是列表
>>> a2 = array(a1)# 列表——>数组
>>> a2array([[1,2,3],
[4,5,6]])
>>> a3 = mat(a1)# 列表——>矩阵
>>> a3matrix([[1,2,3],
[4,5,6]])
>>> a4 = a2.tolist()# 数组——>列表
>>> a4
[[1,2,3],[4,5,6]]
>>> a5 = a3.tolist()# 矩阵——>列表
>>> a5
[[1,2,3],[4,5,6]]