**
源码下载:https://github.com/duongcongnha/Vehicle-tracking
问题一:显示类别信息
**
1. deepsort的输入
# deepsort原有的输入
deepsort.update(xyhw, confidence, im0)
# deepsort修改后的输入
deepsort.update(xyhw, confidence, im0, labels)
# 其中labels是有目标检测阶段生成的预测标签, 题主使用是list,每个元素是one hot 格式的标签
2.修改deepsort的update函数
2.1 修改update函数
修改后的update函数
def update(self, bbox_xywh, confidences, ori_img,labels): # 修改处,新增了labels输入
self.height, self.width = ori_img.shape[:2]
# generate detections
features = self._get_features(bbox_xywh, ori_img)
bbox_tlwh = self._xywh_to_tlwh(bbox_xywh)
detections = [Detection(bbox_tlwh[i], conf, features[i],labels[i]) for i, conf in enumerate(
confidences) if conf > self.min_confidence] #修改处,对于detections新增了相应目标的label
# run on non-maximum supression
boxes = np.array([d.tlwh for d in detections])
scores = np.array([d.confidence for d in detections])
# update tracker
self.tracker.predict()
self.tracker.update(detections)
# output bbox identities
outputs = []
for track in self.tracker.tracks:
if not track.is_confirmed() or track.time_since_update > 1:
continue
box = track.to_tlwh()
x1, y1, x2, y2 = self._tlwh_to_xyxy(box)
track_id = track.track_id
label = track.label# 新增此处,通过track.label取到track的label
outputs.append(np.array([x1, y1, x2, y2, label,track_id], dtype=np.int)) # 修改此处,使得outputs中包含了label
if len(outputs) > 0:
outputs = np.stack(outputs, axis=0)
return outputs
由于修改了Detection的输入因此也需要对Detection类进行相应修改
2.2 修改Detection类
detections修改前
class Detection(object):
def __init__(self, tlwh, confidence, feature):
self.tlwh = np.asarray(tlwh, dtype=np.float)
self.confidence = float(confidence)
self.feature = np.asarray(feature, dtype=np.float32)
# 修改后
class Detection(object):
def __init__(self, tlwh, confidence, feature,label): # 新增label
self.tlwh = np.asarray(tlwh, dtype=np.float)
self.confidence = float(confidence)
self.feature = np.asarray(feature, dtype=np.float32)
self.label = label # 新增此行
2.3 修改Tracker类
class Tracker:
def __init__(self, metric, max_iou_distance=0.7, max_age=70, n_init=3,label = None): # 新增label = None
……
self.label = label # 新增此行
……
def update(self, detections):
for track_idx, detection_idx in matches:
self.tracks[track_idx].update(self.kf, detections[detection_idx])
self.tracks[track_idx].label = detections[detection_idx].label # 新增此行
但是输出标签为数字为了对应,笔者手动加了类别对应,如果有更简单的方法欢迎提出。
for track in outputs:
bbox = track[:4]
track_id = track[-1]
tracklabel = class_mapping.get(track[4], "Unknown") #新增此行
同时增加映射类别,具体的可以自己添加,感觉应该阔以直接读yolov5的类别再映射,但由于时间紧促用了这粗暴方法,后续有时间再完善。
class_mapping = {
2: "car",
7: "truck",
# ... 其他类别ID和名称的映射
}
参考博客:https://blog.csdn.net/weixin_41826859/article/details/135135917
问题二:仅检测多个目标框
1.设定所需要检测的框
# 假设设定的框
predefined_boxes = [
(540, 180, 810, 410), # 框1shang
(920, 175, 1200, 390), # 框2上
(1170, 180, 1480, 370), # 框3上
# (1150, 620, 1750, 1080), # 框4下
# (1550, 600, 1920, 1080), # 框5下
# (1500, 150, 1700, 400), # 框6上
(1500, 130, 1880, 420) # 框7上
]
2.过滤跟踪结果
outputs = self.deepsort.update(bbox_xywh, cls_conf,ori_img,cls_ids)
print("原始跟踪结果",outputs,type(outputs))
# 过滤跟踪结果
outputs = np.array(filter_tracking_results(outputs, predefined_boxes))#新增此行
def filter_tracking_results(tracking_results, predefined_boxes, iou_threshold=0.3):
"""
过滤跟踪结果,只保留与预定义框的交并比(IOU)大于阈值的结果。
:param tracking_results: 跟踪结果列表,每个元素是一个列表,包含框的坐标和额外信息。
:param predefined_boxes: 预定义的框列表,每个元素是一个包含框坐标的元组。
:param iou_threshold: 交并比(IOU)的阈值,默认为0.8。
:return: 过滤后的跟踪结果列表。
"""
filtered_results = []
for result in tracking_results:
max_iou = 0
for predefined_box in predefined_boxes:
iou = calculate_iou(result, predefined_box)
if iou > max_iou:
max_iou = iou
if max_iou > iou_threshold:
filtered_results.append(result) # 将结果作为列表添加
return filtered_results
# 定义计算IOU的函数
def calculate_iou(box1, box2):
x1_min, y1_min, x1_max, y1_max = box1[:4]
x2_min, y2_min, x2_max, y2_max = box2[:4]
overlap_x = max(0, min(x1_max, x2_max) - max(x1_min, x2_min))
overlap_y = max(0, min(y1_max, y2_max) - max(y1_min, y2_min))
overlap_area = overlap_x * overlap_y
box1_area = (x1_max - x1_min) * (y1_max - y1_min)
box2_area = (x2_max - x2_min) * (y2_max - y2_min)
iou = overlap_area / min(box1_area, box2_area)
return iou
3.显示多个框
for box in predefined_boxes:
x_min, y_min, x_max, y_max = box
line=((y_max,x_min),(y_max,x_max))
lines.append(line)
# 绘制矩形框,颜色为红色,线宽为2
cv2.rectangle(ori_img, (x_min, y_min), (x_max, y_max), (0, 0, 255), 2)
三、跟踪参数调整
DEEPSORT:
REID_CKPT: “deep_sort_pytorch/deep_sort/deep/checkpoint/ckpt.t7”
MAX_DIST: 0.1 # 0.2 最大余弦距离 。在特征匹配过程中,这个值定义了特征向量之间的最大距离阈值。如果距离超过这个阈值,匹配将不会被接受。
MIN_CONFIDENCE: 0.5 #0.3 YOLOv5最小检测置信度,增大置信度可去除杂散干扰。
NMS_MAX_OVERLAP: 1. # 0.5。 非极大值抑制(Non-Maximum Suppression, NMS)的最大重叠阈值。在目标检测中,用于去除重叠过多的检测框。
MAX_IOU_DISTANCE: 0.5 # 0.7 IOU最大距离,此值小则不易匹配,将产生新的ID。
MAX_AGE: 70 # 70 这个参数定义了跟踪器在没有检测到目标的情况下可以持续多少帧。在这里,如果一个目标在15帧内没有被检测到,它的跟踪就会结束。
N_INIT: 6 # 3 track连续confirm数量,增大有助于减少新ID出现。这是将一个待定的跟踪器(tentative)转换为确定的跟踪器(confirmed)所需的最小帧数。
NN_BUDGET: 100 # track最大feature数量。
减小最大余弦距离(MAX_DIST),减小最大IOU距离(MAX_IOU_DISTANCE=0.5),可提高跟踪稳定性,跟踪目标被遮挡时仍可实现目标ID保持不变。其中,IOU距离影响效果较大,余弦距离的作用较小。余弦距离是比较yolov5检测目标和sort已跟踪目标间外观特征的相似度指标,若这个指标对跟踪效果的影响小,说明外观特征对持续跟踪所起的作用不大。