用代码实例学习OpenCV Python中的物体追踪
简介
在这篇文章中,我们将实现和比较OpenCV Python库中的物体跟踪算法。 我们将首先了解什么是物体追踪,然后看到OpenCV python的几个物体追踪模块的代码例子,如KCF, CSRT, Mean Shift, 和Cam Shift算法。
什么是物体追踪?
物体跟踪是一项计算机视觉任务,指的是寻找和跟踪视频帧中正在移动的预定义物体的位置的过程。
物体跟踪与物体检测
有时,初学者会将物体追踪与物体检测混淆,并将这两个词交替使用。但这两者之间有细微的差别------。
在物体检测任务中,我们在特定的帧或场景中识别物体,该场景可能只是一个静态图像。而在物体追踪中,我们追踪的是视频中连续运动的物体。事实上,如果我们对视频的每一帧都进行物体检测,其结果就只是物体跟踪的效果。
物体追踪的应用
物体追踪有许多有趣而有用的应用,其中一些应用如下所示
- 人机互动
- 安全和监控
- 扩增现实
- 交通控制
- 医学成像
- 视频编辑
物体跟踪算法的类型
i) 单一物体跟踪
单一物体追踪是指选择一个感兴趣的区域(在视频的初始帧中)并追踪该物体在接下来的视频帧中的位置(即坐标)的过程。我们将在本文中介绍一些用于单一物体追踪的算法。
单一物体检测器实例
二)多物体追踪(MOT)
多物体追踪是追踪视频中不止一个物体的任务。在这种情况下,该算法为视频帧中检测到的每个物体分配一个唯一的变量。随后,它在视频的连续/未来帧中识别并跟踪所有这些多个物体。
由于视频中可能有大量的物体,或者视频本身不清晰,而且物体的运动方向可能不明确,所以多物体追踪是一项困难的任务,因此它依赖于单帧物体检测。
多重物体检测实例
安装库
i) 安装OpenCV
我们为我们的目的安装opencv-contrib-python库。它是一个不同的社区维护的OpenCV Python包,包含了一些比常规OpenCV Python包更多的功能和实现。
pip install opencv-contrib-python
ii) 安装Numpy
Numpy是任何计算机视觉任务的重要先决条件,它可以像下面这样安装。
pip install numpy
iii) 导入库
让我们导入这些库,如下所示。
import cv2
import numpy as np
i) KCF物体跟踪
KCF是Kernelized Correlation Filter的缩写,它是两种跟踪算法(BOOSTING和MIL跟踪器)技术的结合。它应该利用圆周移动来平移边界框(物体的位置)。简单地说,KCF追踪器关注图像中的变化方向(可能是运动、延伸或方向),并试图生成要追踪的物体的概率位置。
OpenCV Python中的KCF物体追踪
KCF物体追踪是在OpenCV python的TrackerKCF_create()模块中实现的。下面是代码和解释。
tracker = cv2.TrackerKCF_create()
video = cv2.VideoCapture('video.mp4')
ok,frame=video.read()
bbox = cv2.selectROI(frame)
ok = tracker.init(frame,bbox)
while True:
ok,frame=video.read()
if not ok:
break
ok,bbox=tracker.update(frame)
if ok:
(x,y,w,h)=[int(v) for v in bbox]
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2,1)
else:
cv2.putText(frame,'Error',(100,0),cv2.FONT_HERSHEY_SIMPLEX,1,(0,0,255),2)
cv2.imshow('Tracking',frame)
if cv2.waitKey(1) & 0XFF==27:
break
cv2.destroyAllWindows()
第1-3行:我们首先初始化 "KCF "跟踪器对象。接下来,我们初始化视频,然后使用'read()'函数来获取视频的第一帧。
第5行。我们用第二行获取的视频的第一帧初始化'selectROI'函数,并将其值存储在'bbox'变量中。
第7行。我们用要追踪的物体的帧(我们在其中选择了感兴趣的区域)和位置(bbox)来初始化追踪器(使用'init')。
第9行。初始化一个while循环,循环播放我们视频的各个帧。
第10行:在视频对象上使用 "read() "函数来获取视频帧,同时使用一个标志参数('ok')来告知获取帧的过程是否成功。
第11-12行。如果标志参数是假的,执行就会停止,即如果视频没有被正确获取,执行就会停止。
第13行:我们使用追踪器的 "更新 "函数,在循环的每一次迭代中传递一个新的连续帧。它返回两个变量,第一个是通知跟踪过程是否成功的标志参数,第二个是返回被跟踪物体在帧中的位置,如果且仅当第一个参数为真。
第14-16行。如果 "ok "标志为真,则执行该块。我们在'bbox'变量中获取了物体的位置,在这里我们初始化了x、y坐标以及宽度和高度的值。接下来,我们使用OpenCV的'rectangle'函数在视频的连续帧中为检测到的物体设置一个边界框。
第17-18行。如果追踪器无法追踪选定的ROI或面临任何错误,这块代码会在视频帧上打印 "错误"。
第19行:使用'cv2.imshow'函数在一个单独的窗口上显示视频帧。
第20-21行:如果用户点击'escape'按钮,则停止执行。
第22行:使用OpenCV的'destroyAllWindows()'函数来关闭所有徘徊的窗口(如果有)。
输出
KCF执行
ii) CSRT对象跟踪
CSRT是CSR-DCF(Channel and Spatial Reliability of Discriminative Correlation Filter)的OpenCV实现,它是一种先进的算法,可以适应像放大和非矩形物体的变化。从本质上讲,它使用HoG特征和SRM(空间可靠性地图)进行物体定位和跟踪。
OpenCV Python中的CSRT物体追踪
CSRT物体追踪是在OpenCV python的TrackerCSRT_create()模块中实现的。它可以用于与上一节类似的视频。只要将跟踪器变量改为CSRT变量,就可以了。
tracker = cv2.TrackerCSRT_create()
video = cv2.VideoCapture('video.mp4')
ok,frame=video.read()
bbox = cv2.selectROI(frame)
ok = tracker.init(frame,bbox)
while True:
ok,frame=video.read()
if not ok:
break
ok,bbox=tracker.update(frame)
if ok:
(x,y,w,h)=[int(v) for v in bbox]
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2,1)
else:
cv2.putText(frame,'Error',(100,0),cv2.FONT_HERSHEY_SIMPLEX,1,(0,0,255),2)
cv2.imshow('Tracking',frame)
if cv2.waitKey(1) & 0XFF==27:
break
cv2.destroyAllWindows()
输出
CSRT的实现
OpenCV中的其他物体跟踪算法
OpenCV的对象跟踪API提供了多种跟踪器。你可以通过简单地改变跟踪器变量的值来尝试一些其他的跟踪算法。
GOTURN算法
tracker = cv2.TrackerGOTURN_create()
MIL算法
tracker = cv2.TrackerMIL_create()
iv) 用于物体追踪的直方图密度算法
i) 使用平均移位算法进行物体追踪
Mean Shift是一种物体追踪算法,它使用不同图像/直方图中的像素密度逻辑来追踪物体。它为一个像素点找到最接近的聚类,并反复向它移动,直到到达聚类中心或误差低于一个阈值。这基本上意味着它在一幅图像上一次又一次地运行自己(比较像素值以寻找匹配),直到找到我们要追踪的对象(聚类)。如果无法找到确切的图像,那么就会选择一个具有最大匹配度的区域。
MeanShift的实施例子
OpenCV Python中的平均移位物体追踪器的实现
cap = cv2.VideoCapture('video.mp4')
ret,frame=cap.read()
x,y,w,h = cv2.selectROI(frame)
track_window = (x, y, w, h)
roi = frame[y:y+h, x:x+w]
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
roi_hist = cv2.calcHist([hsv_roi],[0],mask,[180],[0,180])
cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX)
term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )
while(1):
ret, frame = cap.read()
if ret == True:
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)
ret, track_window = cv2.meanShift(dst, track_window, term_crit)
x,y,w,h = track_window
img2 = cv2.rectangle(frame, (x,y), (x+w,y+h), 255,2)
cv2.imshow('img2',img2)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
else:
break
cv2.destroyAllWindows()
第1-3行:加载视频(要对其进行跟踪),在'frame'变量中获取第一帧。最后,对第一帧使用'selectROI'函数,并在'bbox'变量中存储物体的位置。这实际上使我们能够手动选择我们的ROI,而不是硬编码它。
第4-5行:在这里我们通过使用用户提供的ROI值来设置跟踪窗口的初始位置。我们初始化'roi'变量,该变量持有要追踪的图像部分。
第6-9行。首先,我们将ROI的色彩空间改为 "HSV "色彩空间,然后定义一个掩码变量,其范围为 "roi "变量中的最大到最小值(像素)。我们对 "ROI "进行直方图均衡化,最后,我们对像素值进行标准化处理。
第10行:我们定义一个终止标准(作为参数传递给'meanShift'算法函数),一个整数定义了迭代次数(10),另一个整数定义了将我们的计算方块移动多少单位(1),如图所示。
第11行:运行一个while循环,循环播放视频。
第12行:使用'cv2''read()'函数来获取连续的帧。
第13 行:如果标志变量 "ret "为真,则执行 "if "语句中的代码。
第14-15行。正如我们在第5行所做的那样,我们需要改变每一个连续帧的色彩空间,以进行跟踪,因此我们再次应用这一过程。接下来,正如我们在定义中所讨论的,该算法使用背投,因此我们使用'calcBackProject()'函数。
第16行:我们调用'meanShift'函数,该函数将我们需要检测和追踪物体的图像、终止标准以及要检测的物体的位置坐标作为参数。它返回一个矩形的坐标值,这个矩形可以作为边界框参数('ret')的点。
第17-19行。首先,我们更新被追踪物体的位置,并将其存储起来(单位:x,y,w,h)。接下来,在物体周围放置一个边界框(使用'rectangle'函数),最后显示图像(使用'imshow')。
第20-22行。这个代码块确保如果用户点击'escape'按钮,执行将停止。
第21-24行。如果标志变量'ret'为false,则执行流程将脱离循环。
第25行。关闭所有的窗口。
输出
平均移位的实现
ii) 使用Cam Shift算法的物体跟踪
均匀移动算法的问题是,边界框的大小总是保持不变(即使物体开始接近摄像机并最终增大,反之亦然)。连续自适应均值移位或CAM算法为我们解决了这个问题(它在前一个窗口和新的按比例搜索窗口上应用均值移位)。它应该更新窗口的大小为
s=2×√M/256
并找到适合我们对象的最佳椭圆,并返回其小轴和主轴。
CamShift实现示例
OpenCV Python中Cam Shift物体追踪器的实现
cap = cv2.VideoCapture('video.mp4')
ret,frame=cap.read()
x,y,w,h = cv2.selectROI(frame)
track_window = (x, y, w, h)
roi = frame[y:y+h, x:x+w]
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
roi_hist = cv2.calcHist([hsv_roi],[0],mask,[180],[0,180])
cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX)
term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )
while(1):
ret, frame = cap.read()
if ret == True:
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)
ret, track_window = cv2.CamShift(dst, track_window, term_crit)
pts = cv2.boxPoints(ret)
pts=np.int0(pts)
img2 = cv2.polylines(frame, [pts], True, 255,2)
cv2.imshow('img2',img2)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
else:
break
cv2.destroyAllWindows()
这个Cam Shift的实现类似于Mean Shift的实现。这里我们只是把'meanShift'函数改为'CamShift'函数。
第16-19行。这次由于坐标不需要是一个完美的矩形,因此我们使用第一个var 'ret'。我们需要将其类型化为'integer',以便发送到'polylines'函数。
输出
凸轮轴的实现
- 同时阅读 - YOLOv5物体检测教程
- 还可以阅读 - YOLOv4物体检测教程与图像和视频。初学者指南
The postLearn Object Tracking in OpenCV Python with Code Examplesappeared first onMLK - Machine Learning Knowledge.
推荐阅读
-
[姿势估计] 实践记录:使用 Dlib 和 mediapipe 进行人脸姿势估计 - 本文重点介绍方法 2):方法 1:基于深度学习的方法:。 基于深度学习的方法:基于深度学习的方法利用深度学习模型,如卷积神经网络(CNN)或递归神经网络(RNN),直接从人脸图像中学习姿势估计。这些方法能够学习更复杂的特征表征,并在大规模数据集上取得优异的性能。方法二:基于二维校准信息估计三维姿态信息(计算机视觉 PnP 问题)。 特征点定位:人脸姿态估计的第一步是通过特征点定位来检测和定位人脸的关键点,如眼睛、鼻子和嘴巴。这些关键点提供了人脸的局部结构信息,可用于后续的姿势估计。 旋转表示:常见的旋转表示方法包括欧拉角和旋转矩阵。欧拉角通过三个旋转角度(通常是俯仰、偏航和滚动)描述头部的旋转姿态。旋转矩阵是一个 3x3 矩阵,表示头部从一个坐标系到另一个坐标系的变换。 三维模型重建:根据特征点的定位结果,三维人脸模型可用于姿势估计。通过将人脸的二维图像映射到三维模型上,可以估算出人脸的旋转和平移信息。这就需要建立人脸的三维模型,然后通过优化方法将模型与特征点对齐,从而获得姿势估计结果。 特征点定位 特征点定位是用于检测人脸关键部位的五官基础部分,还有其他更多的特征点表示方法,大家可以参考我上一篇文章中介绍的特征点检测方案实践:人脸校正二次定位操作来解决人脸校正的问题,客户在检测关键点的代码上略有修改,坐标转换部分客户见上图 def get_face_info(image). img_copy = image.copy image.flags.writeable = False image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) results = face_detection.process(image) # 在图像上绘制人脸检测注释。 image.flags.writeable = True image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) box_info, facial = None, None if results.detections: for detection in results. for detection in results.detections: mp_drawing.Drawing.detection = 无 mp_drawing.draw_detection(image, detection) 面部 = detection.location_data.relative_keypoints 返回面部 在上述代码中,返回的数据是五官(6 个关键点的坐标),这是用 mediapipe 库实现的,下面我们可以尝试用另一个库:dlib 来实现。 使用 dlib 使用 Dlib 库在 Python 中实现人脸关键点检测的步骤如下: 确保已安装 Dlib 库,可使用以下命令: pip install dlib 导入必要的库: 加载 Dlib 的人脸检测器和关键点检测器模型: 读取图像并将其灰度化: 使用人脸检测器检测图像中的人脸: 对检测到的人脸进行遍历,并使用关键点检测器检测人脸关键点: 显示绘制了关键点的图像: 以下代码将参数 landmarks_part 添加到要返回的关键点坐标中。
-
python图像处理:测量物体大小 用 OpenCV 测量图像中物体的大小-效果
-
用Python、OpenCV和深度学习打造的车道线识别竞赛 - 面向自动驾驶的技术实践(卷三:CNN实例)
-
用代码实例学习OpenCV Python中的物体追踪