2022-05-08 10:56:05 体育
在本教程中,我们将进修如何基于 和 实现工具跟踪。
首先要搞清楚物体检测和物体跟踪有什么区别:
我们将首先接头工具检测,然后接头如何将工具跟踪应用于检测。
1.有哪些大概的应用?
大概有差异的应用,譬喻,计较一个区域中有几多人,查抄传送带上有几多物体通过,可能计较高速公路上的车辆。
虽然,阅读本教程后,您可以轻松想到数以千计的合用于现实糊口或大概合用于家产的想法。
2.我们需要什么?
在本教程中,我们将利用 3 个文件:
3.物体检测
首先我们需要挪用 .mp4 文件并建设一个掩码:
cap = cv2.VideoCapture("highway.mp4") # 来自不变相机的物体检测 object_detector = cv2.createBackgroundSubtractorMOG2() while True: ret, frame = cap.read() # 1. 物体检测 mask = object_detector.apply(frame)
在示例代码中可以看到,我们也利用了函数,该函数返回配景的比例,然后建设遮罩。
蒙版可视化功效:
可是,如您所见,图像中有许多噪点。因此,让我们通过移除所有较小的元素来改造提取,,并将留意力会合在大于特定区域的工具上。
_, mask = cv2.threshold(mask, 254, 255, cv2.THRESH_BINARY) contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: # 计较面积,去除小元素 area = cv2.contourArea(cnt) if area > 100: # 显示
利用 的 cv2. 函数绘制表面,我们获得了这个功效。
4.我们界说一个感乐趣的区域
阐明整个窗口对付本教程的目标并不重要。我们只对计较在某个点通过的所有车辆感乐趣,因此opencv举动方针跟踪,我们必需界说一个感乐趣的区域 ROI 并仅在该区域应用掩码。
while True: ret, frame = cap.read() height, width, _ = frame.shape # 提取感乐趣区域 roi = frame[340: 720,500: 800] # 1. 物体检测 mask = object_detector.apply(roi) _, mask = cv2.threshold(mask, 254, 255, cv2.THRESH_BINARY) contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: # 计较面积并去除小元素 area = cv2.contourArea(cnt) if area > 100: cv2.drawContours(roi, [cnt], -1, (0, 255, 0), 2)
功效可视化如下:
cv2. yes 开头添加,没有界说参数,此刻让我们看看如何进一步改造我们的功效。是第一个参数,在本例中配置为 100,因为相机是牢靠的。将其变动为 40,因为该值越低,误报的时机就越大。在这种环境下,我们只对较大的工具感乐趣。
# 来自不变相机的物体检测 object_detector = cv2.createBackgroundSubtractorMOG2(history=100, varThreshold=40)
5.在工具周围画一个框
在处理惩罚矩形之前,我们对图像举办了进一步的清理。为此,阈值函数就派上用场了。从我们的蒙版开始,我们汇报它我们只想显示白色或玄色值,因此通过写入 254、255,只会思量 254 和 255 之间的值。
_, mask = cv2.threshold(mask, 254, 255, cv2.THRESH_BINARY)
然后我们将找到的工具的坐标插入到if条件中,绘制矩形
x, y, w, h = cv2.boundingRect(cnt) cv2.rectangle(roi, (x, y), (x + w, y + h), (0, 255, 0), 3)
这是最终功效:
6.工具追踪
我们此刻只需要导入和集成跟踪成果。
from tracker import * # Create tracker object tracker = EuclideanDistTracker()
建设工具后,我们必需获取界线框的每个位置并将它们插入到单个数组中。
detections.append([x, y, w, h])
通过在屏幕上显示功效,您可以看到通过 ROI 的所有通道是如何被识此外,以及它们的位置是如何被插值到阵列中的特定位置的。显然,识此外摩托车越多,我们的数组就越大。
7.将独一 ID 关联到工具
此刻让我们将一个包括位置的数组通报给 .( )。我们将再次得到一个包括位置的数组,但另外,每个工具都将被分派一个独一的 ID。
从代码中可以看出,我们可以利用 for 轮回阐明所有内容。此时我们只需要绘制矩形并显示车辆ID即可。
# 2. 方针跟踪 boxes_ids = tracker.update(detections) for box_id in boxes_ids: x, y, w, h, id = box_id cv2.putText(roi, str(id), (x, y - 15), cv2.FONT_HERSHEY_PLAIN, 2, (255, 0, 0), 2) cv2.rectangle(roi, (x, y), (x + w, y + h), (0, 255, 0), 3)
在图片中你可以看到功效
8.完整代码
tracker.py import math class EuclideanDistTracker: def __init__(self): # 存储工具的中心位置 self.center_points = {} # 保持id的计数 # 每次检测到新的工具 id 时,计数将增加 1 self.id_count = 0 def update(self, objects_rect): # 工具框和 ID objects_bbs_ids = [] # 获取新工具的中心点 for rect in objects_rect: x, y, w, h = rect cx = (x + x + w) // 2 cy = (y + y + h) // 2 # 查明是否已经检测到该工具 same_object_detected = False for id, pt in self.center_points.items(): # 计较中心点之间的欧式间隔 dist = math.hypot(cx - pt[0], cy - pt[1]) # 假如欧氏间隔小于25即表白是沟通的方针 if dist < 25: self.center_points[id] = (cx, cy) 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] = (cx, cy) objects_bbs_ids.append([x, y, w, h, self.id_count]) self.id_count += 1 # 按中心点清理字典以删除不再利用的 IDS new_center_points = {} for obj_bb_id in objects_bbs_ids: _, _, _, _, 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
main.py