一、项目介绍:

二、环境安装:

  • 平台:windows 11
  • 编译器:pycharm
  • cuda 11.3
  • cudnn 8.2.0.53
conda create -n yolov5deepsort python=3.7
conda activate yolov5deepsort
pip install torch-1.11.0+cu113-cp38-cp38-win_amd64.whl
pip install torchvision-0.12.0+cu113-cp38-cp38-win_amd64.whl
pip install opencv-python
pip install tqdm
pip install pyyaml
pip install  matplotlib
pip install easydict pip install scipy

pytorch的轮子文件下载地址:https://download.pytorch.org/whl/torch_stable.html

三、执行代码

python track.py

核心代码:

'''首先在跟踪主程序track.py中找到下面这一行,这一行是对跟踪框进行更新,是跟踪算法的核
   得到的outputs存放以下信息:[x1, y1, x2, y2, track_id],即目标框的左上角和右下角坐标以及分配给它的ID
'''
outputs = self.deepsort.update(bbox_xcycwh, cls_conf, im)
# outputs = [x1, y1, x2, y2, track_id]
bbox_xyxy = outputs[:, :4]   # 提取前四列  坐标
identities = outputs[:, -1]  # 提取最后一列 ID
box_xywh = xyxy2tlwh(bbox_xyxy)  
# xyxy2tlwh是坐标格式转换从x1, y1, x2, y2转为top left x ,top left y, w, h 具体函数看文章最后
for j in range(len(box_xywh)):
    x_center = box_xywh[j][0] + box_xywh[j][2] / 2  # 求框的中心x坐标
    y_center = box_xywh[j][1] + box_xywh[j][3] / 2  # 求框的中心y坐标
    id = outputs[j][-1]
    center = [x_center, y_center]
    dict_box.setdefault(id, []).append(center)  
# 这个字典需要提前定义 在读取每一帧的循环外面定义 dict_box = dict(),这个字典的目的就是把ID和框的中心坐标对应起来ID是字典的key中心坐标是字典的Value这样才能把同ID的目标中心坐标连起来
 
# 以下为画轨迹原理就是将前后帧同ID的跟踪框中心坐标连接起来
if frame_cnt > 2:  # 第一帧无法连线所以设置从第二帧开始frame_cnt为当前帧号
    for key, value in dict_box.items():
        for a in range(len(value) - 1):
            color = COLORS_10[key % len(COLORS_10)]
            index_start = a
            index_end = index_start + 1
            cv2.line(ori_im, tuple(map(int, value[index_start])), tuple(map(int, value[index_end])), #map(int,"1234")转换为list[1,2,3,4]

COLOR10是给轨迹加颜色的一个参数,是为了设置不同目标的轨迹颜色不同,如果不想这么复杂,可以改成固定颜色。


COLORS_10 =[(144,238,144),(178, 34, 34),(221,160,221),(  0,255,  0),(  0,128,  0),(210,105, 30),(220, 20, 60),
            (192,192,192),(255,228,196),( 50,205, 50),(139,  0,139),(100,149,237),(138, 43,226),(238,130,238),
            (255,  0,255),(  0,100,  0),(127,255,  0),(255,  0,255),(  0,  0,205),(255,140,  0),(255,239,213),
            (199, 21,133),(124,252,  0),(147,112,219),(106, 90,205),(176,196,222),( 65,105,225),(173,255, 47),
            (255, 20,147),(219,112,147),(186, 85,211),(199, 21,133),(148,  0,211),(255, 99, 71),(144,238,144),
            (255,255,  0),(230,230,250),(  0,  0,255),(128,128,  0),(189,183,107),(255,255,224),(128,128,128),
            (105,105,105),( 64,224,208),(205,133, 63),(  0,128,128),( 72,209,204),(139, 69, 19),(255,245,238),
            (250,240,230),(152,251,152),(  0,255,255),(135,206,235),(  0,191,255),(176,224,230),(  0,250,154),
            (245,255,250),(240,230,140),(245,222,179),(  0,139,139),(143,188,143),(255,  0,  0),(240,128,128),
            (102,205,170),( 60,179,113),( 46,139, 87),(165, 42, 42),(178, 34, 34),(175,238,238),(255,248,220),
            (218,165, 32),(255,250,240),(253,245,230),(244,164, 96),(210,105, 30)]

四、报错指南

1、AttributeError: ‘Upsample’ object has no attribute ‘recompute_scale_factor’

解决办法:

1)进入目录

2)找到以下代码

def forward(self, input: Tensor) -> Tensor:
    return F.interpolate(input, self.size, self.scale_factor, self.mode, self.align_corners,
                         recompute_scale_factor=self.recompute_scale_factor)

改为

def forward(self, input: Tensor) -> Tensor: 
  return F.interpolate(input, self.size, self.scale_factor, self.mode, self.align_corners) 
  # return F.interpolate(input, self.size, self.scale_factor, self.mode, self.align_corners, 
  # recompute_scale_factor=self.recompute_scale_factor)

2、直接使用 yaml.load(stream) 报错如下:

File “D:\workplaces\python\GraphSAINT-master\graphsaint\utils.py, line 112, in parse_n_prepare
   train_config = yaml.load(f_train_config)
TypeError: load() missing 1 required positional argument:Loader

解决方案一:

显然,编译器提示 yaml 的 load()函数 缺少 1 个必要参数:’Loader’,这是因为 Yaml  5.1 版本后弃用了 yaml.load(file) 这个用法。

新版本 Yaml 的 load() 函数如下:

def load(stream, Loader):
    """
    Parse the first YAML document in a stream
    and produce the corresponding Python object.
    """
    loader = Loader(stream)
    try:
        return loader.get_single_data()
    finally:
        loader.dispose()

Yaml 5.1 之后的版本为了加强安全性要求指定具体的 Loader,禁止执行任意函数。

解决方案二

新版本修改为以下任意一种即可,即指定了 ‘Loader’

d1 = yaml.load(file, Loader=yaml.FullLoader) 
d1 = yaml.safe_load(file) 
d1 = yaml.load(file, Loader=yaml.CLoader)
with open(config_file) as stream:
    config_dict = yaml.safe_load(stream)