计算机视觉–光流估计

今天看了BURST IMAGE RESTORATION AND ENHANCEMENT(多帧图片修复和增强),提到了光流估计,所以想介绍这个运动评估技术。

光流的概念是Gibson在1950年首先提出来的。它是空间运动物体在观察成像平面上的像素运动的瞬时速度,是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的一种方法。一般而言,光流是由于场景中前景目标本身的移动、相机的运动,或者两者的共同运动所产生的。

计算机视觉光流估计 光流估计的应用_灰度

光流估计的种类

1、Lucas-Kanade算法,1981年提出,opencv中已实现。
2、Farneback算法,2003年提出,opencv中已实现。
3、brox算法,2004年提出,opencv中已实现。
4、SF算法,2012年提出,opencv中已实现。
5、Flownet2,2016年提出,利用深度卷积神经网络生成光流图像
SF算法较慢,brox算法需要使用GPU,Flownet2需要GPU和docker环境

光流估计代码实现

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)
## 第四步:返回所有检测特征点,需要输入图片,角点的最大数量,品质因子,minDistance=7如果这个角点里有比这个强的就不要这个弱的
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)
    # 第七步:进行光流检测需要输入前一帧和当前图像及前一帧检测到的角点
	#参数说明:pl表示光流检测后的角点位置,st表示是否是运动的角点,err表示是否出错,old_gray表示输入前一帧图片,frame_gray表示后一帧图片,p0表示需要检测的角点,lk_params:winSize表示选择多少个点进行u和v的求解,maxLevel表示空间金字塔的层数
    pl, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
    # 第八步:读取运动了的角点st == 1表示检测到的运动物体,即v和u表示为0
    good_new = pl[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)
    # p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)
cv2.destroyAllWindows()
cap.release()

光流法的优点在于它无须了解场景的信息,就可以准确地检测识别运动日标位置,且在摄像机处于运动的情况下仍然适用。缺点计算量大,耗时长,在对实时性要求苛刻的情况下并不适用。使用光流法无法将输入帧完全继承到端对端的学习管道中,也就是无法对齐输入帧。在后续的处理阶段可能出现错误。
参考