在本文中,将探讨如何使用Python和OpenCV设计一个跟踪系统,该系统能够追踪任何移动的对象,基于欧几里得距离跟踪和轮廓跟踪的概念。是否曾经在计算机视觉项目中工作过?是否想过无论对象移动到哪里都能追踪到它?对象跟踪是一种方法论,用于追踪并持续指向同一个对象,无论它移动到哪里。
使用OpenCV实现对象跟踪有多种技术,可以是单一对象跟踪或多对象跟踪。在本文中,将执行多对象跟踪,因为目标是跟踪在给定时间框架内通过的车辆数量。多种跟踪算法取决于复杂性和计算量。
多种跟踪算法依赖于复杂性和计算。DEEP SORT是广泛使用的跟踪算法之一,它是一个非常有效的对象跟踪算法,因为它使用了深度学习技术。它与YOLO对象检测一起工作,并使用卡尔曼滤波器进行跟踪。
质心跟踪算法是多个步骤过程的组合。它使用简单的计算通过欧几里得距离来跟踪点。这种跟踪算法也可以使用自定义代码实现。在本文中,将使用质心跟踪算法构建跟踪器。
步骤1:使用边界框坐标计算检测到的对象的质心。步骤2:对于每一帧,它都会做同样的事情;它使用边界框的坐标计算质心,并为每个检测到的边界框分配一个ID。最后,它计算每对质心之间可能的欧几里得距离。步骤3:假设同一个对象将移动最小的距离与其他质心相比,这意味着在连续帧中具有最小距离的两对质心被认为是同一个对象。步骤4:现在是时候为移动的质心分配ID,以指示同一个对象。
由于计算资源的增长和正在进行的研究工作,对象跟踪变得越来越强大。有多种主要用例,对象跟踪在其中得到了广泛的应用。交通跟踪和碰撞保护服务、追踪不受欢迎的行为、车辆跟踪、购物中心和购物综合体的跟踪器、安全系统。
构建了一个名为EuclideanDistTracker的类,用于对象跟踪,结合了学到的所有步骤。这包括欧几里得距离跟踪器背后的所有数学计算。
import math
class EuclideanDistTracker:
def __init__(self):
self.center_points = {}
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():
if distance < 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
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
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
self.center_points = new_center_points.copy()
return objects_bbs_ids
update → 它接受边界框坐标的数组。跟踪器输出一个包含[x,y,w,h, object_id]的列表。x,y,w,h是边界框坐标,object_id是分配给该特定边界框的ID。
导入必要的包以及最近制作的跟踪器类。
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()
使用OpenCV附带的高速公路视频作为示例视频。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)
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()