yolov5+deepsort实现车辆跟踪

**
源码下载: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已跟踪目标间外观特征的相似度指标,若这个指标对跟踪效果的影响小,说明外观特征对持续跟踪所起的作用不大。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值