对象跟踪是指跟踪或保持移动对象的身份,无论其移动到哪里。在OpenCV中执行对象跟踪有多种技术。对象跟踪可以用于两种情况:单对象跟踪和多对象跟踪。在这里,将执行多对象跟踪方法,因为在单个时间帧中有多个车辆。
DEEP SORT:这是最广泛使用且非常有效的对象跟踪算法之一,它基于YOLO对象检测工作。它使用卡尔曼滤波器进行跟踪。
质心跟踪算法:质心跟踪算法易于理解且非常有效。这是一个多步骤过程。
获取检测到的对象的边界框坐标,并使用边界框的坐标计算质心。
对于每个后续帧,使用边界框坐标计算质心,并为这些边界框分配ID,并计算每个质心之间可能的欧几里得距离。
假设是,给定的对象可能会在后续帧中移动,它们质心之间的欧几里得距离将是与其他对象相比的最小距离。
在后续帧之间最小移动的质心分配相同的ID。
随着计算能力的增长,对象跟踪正在变得先进。对象跟踪的一些主要用例包括交通跟踪和避免碰撞、人群跟踪、家中无人时的宠物跟踪、导弹跟踪和空中画布笔。
本文中使用的所有代码源文件和测试视频可以通过此链接下载。以上讨论的所有步骤都可以使用一些数学计算来执行。构建了一个名为EuclideanDistTracker的类来进行对象跟踪。
import math
class EuclideanDistTracker:
def __init__(self):
# 存储对象中心的位置
self.center_points = {}
# 边界框ID计数
# 每次捕获新对象时,ID将增加1
self.id_count = 0
def update(self, objects_rect):
objects_bbs_ids = []
# 计算对象的中心
for rect in objects_rect:
x, y, w, h = rect
center_x = (x + x + w) // 2
center_y = (y + y + h) // 2
# 查找是否已经检测到对象
same_object_detected = False
for id, pt in self.center_points.items():
dist = math.hypot(center_x - pt[0], center_y - pt[1])
if dist < 25:
self.center_points[id] = (center_x, center_y)
print(self.center_points)
objects_bbs_ids.append([x, y, w, h, id])
same_object_detected = True
break
# 为检测到的对象分配ID
if same_object_detected is False:
self.center_points[self.id_count] = (center_x, center_y)
objects_bbs_ids.append([x, y, w, h, self.id_count])
self.id_count += 1
# 清理不再使用的字典ID
new_center_points = {}
for obj_bb_id in objects_bbs_ids:
var,var,var,var, object_id = obj_bb_id
center = self.center_points[object_id]
new_center_points[object_id] = center
# 更新不再使用的ID的字典
self.center_points = new_center_points.copy()
return objects_bbs_ids
可以创建一个名为tracker.py的文件并粘贴跟踪器的代码,或者直接使用此链接下载跟踪器文件。
从已经创建的tracker.py文件中导入EuclideanDistTracker类。
import cv2
import numpy as np
from tracker import EuclideanDistTracker
tracker = EuclideanDistTracker()
cap = cv2.VideoCapture('highway.mp4')
ret, frame1 = cap.read()
ret, frame2 = cap.read()
cap.read()
它返回帧和布尔值,需要捕获帧。
while cap.isOpened():
diff = cv2.absdiff(frame1, frame2)
gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 0 )
height, width = blur.shape
print(height, width)
_, threshold = cv2.threshold(blur, 23, 255, cv2.THRESH_BINARY)
dilated = cv2.dilate(threshold, (1,1), iterations=1)
contours, _ = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
detections = []
for contour in contours:
(x,y,w,h) = cv2.boundingRect(contour)
if cv2.contourArea(contour) <300:
continue
detections.append([x,y,w,h])
boxes_ids = tracker.update(detections)
for box_id in boxes_ids:
x,y,w,h,id = box_id
cv2.putText(frame1, str(id),(x,y-15), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,0,255), 2)
cv2.rectangle(frame1, (x,y),(x+w, y+h), (0,255,0), 2)
cv2.imshow('frame',frame1)
frame1 = frame2
ret, frame2 = cap.read()
key = cv2.waitKey(30)
if key == ord('q'):
break
cv2.destroyAllWindows()