openCV:光流

2019-10-01  本文已影响0人  SwiftBirds

概念

定义

光流是空间运动物体在观测成像平面上的像素运动的“瞬时速度”,是由对象或相机的移动引起的两个连续帧之间的图像对象的明显运动的模式,它是2D矢量场,其中每个矢量是位移矢量,表示从第一帧到第二帧的点的移动。根据各个像素点的速度矢量特征,可以对图像进行动态分析,例如目标跟踪。

使用光流的前提

Lucas-Kanade 算法

由光流估计的前提—亮度恒定,得到约束方程;然后根据泰勒级数展开化简,得到关于像素点梯度与速度矢量的方程。

如何求解方程组呢?看起来一个像素点根本不够。

API

cv2.calcOpticalFlowPyrLK():

参数:

返回:

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 = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
# 返回所有检测特征点,需要输入图像,
# 
p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params)

# 创建一个mask
mask = np.zeros_like(old_frame)

while(True):
    ret,frame = cap.read()
    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 = frame_gray.copy()
    p0 = good_new.reshape(-1,1,2)

cv2.destroyAllWindows()
cap.release()
上一篇 下一篇

猜你喜欢

热点阅读