欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

用代码实例学习OpenCV Python中的物体追踪

最编程 2023-12-31 09:49:36
...

简介

在这篇文章中,我们将实现和比较OpenCV Python库中的物体跟踪算法。 我们将首先了解什么是物体追踪,然后看到OpenCV python的几个物体追踪模块的代码例子,如KCF, CSRT, Mean Shift, 和Cam Shift算法。

什么是物体追踪?

物体跟踪是一项计算机视觉任务,指的是寻找和跟踪视频帧中正在移动的预定义物体的位置的过程。

物体跟踪与物体检测

有时,初学者会将物体追踪与物体检测混淆,并将这两个词交替使用。但这两者之间有细微的差别------。

在物体检测任务中,我们在特定的帧或场景中识别物体,该场景可能只是一个静态图像。而在物体追踪中,我们追踪的是视频中连续运动的物体。事实上,如果我们对视频的每一帧都进行物体检测,其结果就只是物体跟踪的效果。

物体追踪的应用

物体追踪有许多有趣而有用的应用,其中一些应用如下所示

  • 人机互动
  • 安全和监控
  • 扩增现实
  • 交通控制
  • 医学成像
  • 视频编辑

物体跟踪算法的类型

i) 单一物体跟踪

单一物体追踪是指选择一个感兴趣的区域(在视频的初始帧中)并追踪该物体在接下来的视频帧中的位置(即坐标)的过程。我们将在本文中介绍一些用于单一物体追踪的算法。

Single object detector example

单一物体检测器实例

二)多物体追踪(MOT)

多物体追踪是追踪视频中不止一个物体的任务。在这种情况下,该算法为视频帧中检测到的每个物体分配一个唯一的变量。随后,它在视频的连续/未来帧中识别并跟踪所有这些多个物体。

由于视频中可能有大量的物体,或者视频本身不清晰,而且物体的运动方向可能不明确,所以多物体追踪是一项困难的任务,因此它依赖于单帧物体检测。

Multiple object detection example

多重物体检测实例

安装库

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()'函数来关闭所有徘徊的窗口(如果有)。

输出

Object tracking in OpenCV Python - KCF implementation

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()

输出

Object tracking in OpenCV Python - CSRT implementation

CSRT的实现

OpenCV中的其他物体跟踪算法

OpenCV的对象跟踪API提供了多种跟踪器。你可以通过简单地改变跟踪器变量的值来尝试一些其他的跟踪算法。

GOTURN算法

tracker = cv2.TrackerGOTURN_create()

MIL算法

tracker = cv2.TrackerMIL_create()

iv) 用于物体追踪的直方图密度算法

i) 使用平均移位算法进行物体追踪

Mean Shift是一种物体追踪算法,它使用不同图像/直方图中的像素密度逻辑来追踪物体。它为一个像素点找到最接近的聚类,并反复向它移动,直到到达聚类中心或误差低于一个阈值。这基本上意味着它在一幅图像上一次又一次地运行自己(比较像素值以寻找匹配),直到找到我们要追踪的对象(聚类)。如果无法找到确切的图像,那么就会选择一个具有最大匹配度的区域。

MeanShift example gif

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行。关闭所有的窗口。

输出

Object tracking in OpenCV Python - Meanshift implementation

平均移位的实现

ii) 使用Cam Shift算法的物体跟踪

均匀移动算法的问题是,边界框的大小总是保持不变(即使物体开始接近摄像机并最终增大,反之亦然)。连续自适应均值移位或CAM算法为我们解决了这个问题(它在前一个窗口和新的按比例搜索窗口上应用均值移位)。它应该更新窗口的大小为

s=2×√M/256

并找到适合我们对象的最佳椭圆,并返回其小轴和主轴。

CamShift implementation gif

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'函数。

输出

Object tracking in OpenCV Python - Camshift implementation

凸轮轴的实现

  • 同时阅读 - YOLOv5物体检测教程
  • 还可以阅读 - YOLOv4物体检测教程与图像和视频。初学者指南

The postLearn Object Tracking in OpenCV Python with Code Examplesappeared first onMLK - Machine Learning Knowledge.

推荐阅读