如何使用光流法进行目标追踪
如今,“图像分类”、“目标检测”、“语义分割”、“实例分割”和“目标追踪”等5大领域是计算机视觉的热门应用。其中“图像分类”与“目标检测”是最基础的应用,在此基础上,派生出了“语义分割”、“实例分割”和“目标跟踪”等相对高级的应用。
“语义分割”与“实例分割”是将图像中的像素点分到对应的类别,实现图像前景和背景分离。“目标追踪”是跟踪图像序列或视频中的目标,定位出目标在图像帧中的运行轨迹。
如图1所示,目标追踪(Object Tracking)是获取图像序列(一般为视频)中感兴趣的区域,并在接下来的视频帧中对其进行跟踪,目标跟踪是计算机视觉里一个重要的领域,在赛事转播、人机交互、监控安防、无人驾驶、无人机等应用中有着关键的作用。
一、目标追踪概述
目标追踪的输入通常是视频,视频是一种非结构化数据,可以看成是图像序列的组合(即一组有序的图像)。虽然在形式上,视频没有固定的结构,但在内容上,视频本身有着较强的逻辑关系,如图2所示,按照颗粒度大小将视频分成帧(Frame)、镜头(Shot)、场景(Scene)、视频(Video)四个层次。
(1)帧是视频最基本单元,视频帧其实是一幅图像,关键帧,又叫代表帧,是指具有代表性的帧。
(2)镜头是由一系列帧组成的,这些帧表达同一个事件或者是摄像机的一组连续的运动。
(3)场景有一定的语义,由一系列相似的镜头组成,这些镜头从不同角度表达同一批对象或环境。
1.视频与图像序列的相互转换
视频可以看成是一组有序的图像组成,对视频的目标检测和对图像的目标检测没有本质不同。通过OpenCV提供的VideoCapture和VideoWriter模块,可以实现视频和图像序列的相互转换,转换的示例代码如下:
(1)导入用到的库。
1 import cv2,os
2 from os.path import isfile, join
(2)使用VideoCapture将视频转换为图像序列。
1 videoFile = './video/ball.mp4' #输入的视频文件
2 imgPath = "./video/frame/" #输出的图像文件路径
3 #打开视频文件、读取视频帧、并以jpg的图像格式,写到指定目录下
4 cap = cv2.VideoCapture(videoFile)
5 frame_id = 0
6 while True:
7 ret,frame = cap.read() #读取视频的帧
8 if not ret: #视频结束
9 break
10 rgb_img= cv2.cvtColor(frame.copy(),cv2.COLOR_BGR2RGB) #将视频的帧转换为RGB格式
11 cv2.imwrite("%s/%04d.jpg"%(imgPath,frame_id),rgb_img)
12 frame_id = frame_id + 1
13 print("转换结束:(视频文件:%s,图像序列路径:%s)"%(videoFile,imgPath))
(3)使用VideoWriter将图像序列转换为视频。
1 imgPath = "./video/frame/" #输入的图像文件路径
2 videoFile = './video/video.mp4' #输出的视频文件
3 fps = 25.0 #速率,每秒25帧
4 #找到目录下所有的图像文件,并按照文件名排序
5 files=[f for f in os.listdir(imgPath) if isfile(join(imgPath,f)) and f.endswith('.jpg')]
6 files.sort()
7 #得到图像文件的尺寸
8 img = cv2.imread(imgPath+files[0])
9 height, width, channel = img.shape
10 #创建视频对象,使用mpg4格式压缩
11 video = cv2.VideoWriter(videoFile,cv2.VideoWriter_fourcc(*'DIVX'),fps,(width,height))
12 #将图像序列写入视频文件
13 for file_name in files:
14 img = cv2.imread(imgPath+file_name)
15 rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #转换为RGB格式
16 video.write(rgb)
17 video.release()
18 print("转换结束:(图像序列路径:%s,视频文件:%s)"%(imgPath,videoFile))
2.目标追踪的分类
根据任务的实时性要求,目标追踪分为“在线追踪”和“离线跟踪”两种:“在线追踪”通过过去和现在的视频帧确定目标的位置,对实时性要求较高;“离线追踪”通过过去、现在和未来的视频帧确定目标的位置,对实时性要求不高,“离线追踪”的准确率通常会高于“在线追踪”的准确率。根据应用场景,目标追踪又可以分为以下几种类型:
(1)单目标追踪,追踪一个固定目标在视频帧中出现的位置。
(2)多目标追踪,同时追踪多个目标在视频帧中出现的位置。
(3)多目标多摄像头追踪,追踪多个摄像头,拍摄到的多个目标,在不同的视频帧中出现的位置。
(4)姿态追踪,追踪目标在视频帧中姿态的变化,如视频中人的不同姿态。
3.生成式模型
生成式模型首先定义出目标的特征,然后在后续视频帧中寻找相似特征的位置,从而实现目标的定位。早期的目标追踪模型中常使用这类方法,如光流法等,但是,生成式模型使用简单的特征定义,对追踪目标的描述方法有很大的局限性,在光照变化,目标被遮挡,分辨率低,拍摄角度变化等情况下,模型的识别效果不是很理想。
4.鉴别式模型
鉴别式模型通过比较视频帧中目标和背景的差异,将目标从视频帧中提取出来,从而实现目标的定位。鉴别式模型同时考虑了目标和背景的信息,在模型的准确度和实时性上,比生成式模型有更好的效果,也逐渐成为目标追踪的主流方法。在本世纪初,传统的机器学习模型(如SVM,随机森林,GBDT等)逐渐被引入到目标追踪中,大约在2015年前后,基于深度学习模型的目标追踪方法开始成为研究热点。
5.目标追踪的方法
有多种框架和算法可以实现目标追踪,其原理也不尽相同,按照时间顺序,可将目标追踪分成“经典方法”、“基于滤波方法”和“基于深度学习方法”三大类,如图3所示。
(1)经典方法。
经典的目标追踪方法是先对目标的外观进行建模(如特征点,轮廓,SIFT等特征),然后在视频帧中查找该目标出现的位置,为了提高查找效率,通常使用预测算法,对目标可能出现的区域进行预测,只在预测的区域内查找目标。
(2)基于滤波方法。
这种方法是通过度量视频帧中目标的相似程度,将不同视频帧中的目标进行关联,实现目标追踪。如MOSSE算法使用相关滤波器(Correlation Filter),计算目标之间的相关值,根据相关值找到不同视频帧中相同的目标并建立关联,从而实现目标追踪。
(3)基于深度学习方法。
这种方法是将深度学习引入到目标追踪中,如基于目标检测的追踪方法(Tracking By Detecting,简称TBD)等。这类方法通过深度学习模型,在每个视频帧上执行目标检测,并在检测到的目标之间建立关联,从而实现目标追踪。
二、使用光流法进行目标追踪
光流法是一种经典的目标追踪方法,通过将不同的视频帧中的像素点形成对应关系,描述出运动信息,从而完成目标的追踪。如图4所示,点、点和点是在不同时刻的视频帧中的同一个目标,光流法通过找到这些点的映射关系,描述出这些点的运动过程,实现目标的追踪。
1.光流
光流(Optical Flow)是指运动物体在成像平面上的像素运动的瞬时速度。如图5所示,三维空间的物体运动,可以用一个三维矢量来描述,将其投影到二维成像平面上,得到一个二维矢量。在时间间隔极小的情况下(如相邻的两个视频帧中),称这个二维矢量为光流矢量用来描述该点的瞬时速度。
2.光流法的原理
光流法通过计算视频帧中像素点的光流,得到光流场(光流的集合),光流场中包含了目标的运动信息,通过分析光流场实现对目标的追踪。
光流法是根据像素值在时间序列上的变化和相邻帧之间的关联程度,找到当前帧和前一帧的对应关系,并根据这种对应关系计算出目标的运行轨迹,使用光流法进行目标追踪时,需要满足以下两个假设条件:
(1)亮度不变性假设,同一目标在不同视频帧间运动时,其亮度不会发生变化。
(2)时间连续性假设,时间的变化不会引起目标位置的剧烈变化,相邻帧之间位移要小。
如图6所示,假设某一个像素点在时刻的坐标是,像素值是,在时刻的坐标是,像素值是,其中为动作向量,表示该像素点向右移动了个像素点,向上移动了个像素点。
光流法假设了同一个点的亮度不变,根据这一假设,可以得到公式10.4。
使用泰勒级数将展开,如公式10.5所示。
略掉公式10.5中的二阶无穷小,再根据“亮度不变”假设(即公式10.4),可以得到动作向量是图像强度和时间内的变化方程,如公式10.6所示。
分别为像素值关于,和的偏导数,分别用、和表示,可得公式10.7,其中、和为已知变量,和为待求参数。有多种算法可以对和进行求解,经典的求解算法是Lucas-Kanade(LK)算法。
3.Lucas-Kanade(LK)算法
公式10.7中,有两个待求参数和,而只有一个方程,为了能求解出和,LK算法在“亮度不变”和“时间连续”假设的基础上,又增加了一个“空间一致”的假设,即在目标像素周围MxM的窗口内的所有像素均有相同的光流矢量。
根据“空间一致”假设,LK算法使用大小3x3窗口内的9个像素点建立9个方程,如公式10.8所示,最后通过最小二乘法,求解出和的最优解。
4.稠密光流于稀疏光流
光流法有“稠密光流”和“稀疏光流”两种类型,稠密光流计算视频帧中所有像素点的光流,形成密集光流场,然后再对目标进行像素级别的配准,而稀疏光流则计算指定特征点的光流(如Harris角点等),形成稀疏光流场,然后再对目标的特征点进行配准。
5.使用OpenCV计算光流
OpenCV内置了LK算法的实现函数calcOpticalFlowPyrLK(),可以直接调用该函数计算光流,并实现目标的追踪,以下代码演示了稀疏光流的计算方法,代码的输出如图7所示。
(1)导入库。
1 import cv2
2 import numpy as np
3 from matplotlib import pyplot as plt
(2)读取文件,读取两幅图像,代表连续的两个视频帧,并将图像转换为灰度图。
1 img_0=cv2.imread("./images/da_feng_che_0.jpg") #读取第一帧的图像
2 img_1=cv2.imread("./images/da_feng_che_1.jpg") #读取第二帧的图像
3 img_0 = cv2.cvtColor(img_0, cv2.COLOR_BGR2RGB) #转换为RGB格式
4 img_1 = cv2.cvtColor(img_1, cv2.COLOR_BGR2RGB) #转换为RGB格式
5 gray_0 = cv2.cvtColor(img_0.copy(), cv2.COLOR_RGB2GRAY) #转换为灰度图
6 gray_1 = cv2.cvtColor(img_1.copy(), cv2.COLOR_RGB2GRAY) #转换为灰度图
7 mask = img_0+img_1 #mask用来显示最后的结果
(3)生成特征点,使用cv2.goodFeaturesToTrack函数,生成第一帧图像的特征点。
1 params = {"maxCorners":10,"qualityLevel":0.01,"minDistance":50,"blockSize":1}
2 key_points_0 = cv2.goodFeaturesToTrack(gray_0, mask = None, **params)
(4)计算光流(稀疏光流),生成第二帧图像的特征点,并将第一帧和第二帧图像的特征点进行关联。
1 #key_points_1是光流计算出的特征点位置,match表示匹配上的特征点
2 key_points_1, match, _ = cv2.calcOpticalFlowPyrLK(gray_0,gray_1,key_points_0, None)
3 matched_0 = key_points_0[match==1] #第一帧图像上的特征点
4 matched_1 = key_points_1[match==1] #第二帧图像上的特征点
(5)显示运动信息,如图10.20所示,红色和蓝色点表示两帧图像上的特征点,白色连线表示对应关系。
1 for i,(frame_0,frame_1) in enumerate(zip(matched_0,matched_1)):
2 a,b = frame_0.ravel()
3 c,d = frame_1.ravel()
4 mask = cv2.circle(mask,(a,b),3,(255,0,0),-1) #用红色标记,第一帧图上的特征点
5 mask = cv2.circle(mask,(c,d),3,(0,0,255),-1) #用蓝色标记,第二帧图上的特征点
6 mask = cv2.line(mask, (a,b),(c,d),(255,255,255),2) #用白色标记,两帧图像上特征点的对应关系
7 f,ax = plt.subplots(1,3, figsize=(12,12))
8 ax[0].imshow(img_0)
9 ax[1].imshow(img_1)
10 ax[2].imshow(mask)
文章来源公众号:OpenCV与AI深度学习
- 分享
- 举报
-
浏览量:804次2023-10-09 19:30:04
-
浏览量:608次2023-09-11 18:04:33
-
浏览量:1070次2020-10-15 14:47:39
-
浏览量:1092次2023-06-02 17:42:09
-
浏览量:1183次2023-03-29 10:55:15
-
浏览量:156次2023-08-30 15:38:33
-
浏览量:1558次2023-12-16 11:15:45
-
浏览量:2305次2022-05-13 10:46:47
-
浏览量:1437次2019-11-11 09:18:07
-
浏览量:8377次2021-01-20 09:27:42
-
浏览量:5282次2021-01-20 09:58:57
-
浏览量:10863次2021-03-20 13:22:58
-
浏览量:8163次2020-12-14 16:23:48
-
浏览量:1485次2024-03-31 22:08:36
-
浏览量:1923次2020-03-12 11:25:13
-
浏览量:470次2024-01-30 09:57:47
-
浏览量:6738次2020-12-22 09:37:22
-
浏览量:2364次2021-10-19 22:29:41
-
浏览量:846次2023-07-05 10:18:03
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
outman
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明