deepsort 挺经典的一篇论文了。
这里我使用的是github上的pytorch版本,链接在这里。
run demos阶段。
这里我们借鉴了github上这位同学的代码,用来实现MOT20图片到视频的转化。
这里首先下载yolov3的权重和deepsort的权重。
Download YOLOv3 parameters
cd detector/YOLOv3/weight/
wget https://pjreddie.com/media/files/yolov3.weights
wget https://pjreddie.com/media/files/yolov3-tiny.weights
cd ../../../
Download deepsort parameters ckpt.t7
cd deep_sort/deep/checkpoint
# download ckpt.t7 from
https://drive.google.com/drive/folders/1xhG0kRH1EX5B9_Iz8gQJb7UNnn_riXi6 to this folder
cd ../../../
在这里有一个让我疑惑的点是:他这个是基于pytorch的代码,可是pjreddie的代码应该是基于C的,我直接运行却没有任何问题,当我尝试使用torch.load
查看yolov3.weight
的时候,却报错了。_pickle.UnpicklingError: invalid load key, '\x00'
Traceback (most recent call last):
File "/home/wlj/Desktop/VOT&S/deep_sort_pytorch-master/demo.py", line 9, in <module>
checkpoint0 = torch.load('/home/wlj/Desktop/VOT&S/deep_sort_pytorch-master/detector/YOLOv3/weight/yolov3.weights')
File "/home/wlj/anaconda3/lib/python3.7/site-packages/torch/serialization.py", line 386, in load
return _load(f, map_location, pickle_module, **pickle_load_args)
File "/home/wlj/anaconda3/lib/python3.7/site-packages/torch/serialization.py", line 563, in _load
magic_number = pickle_module.load(f, **pickle_load_args)
_pickle.UnpicklingError: invalid load key, '\x00'.
这里参考这篇博客找到了github上yolov4和v5作者的讨论和代码,yolov5的作者提供了.pt和.weight的双向转换代码
晕晕乎乎degug了半小时,我收获了什么呢?首先,我知道了打开yolov3.weight 文件的方式:
with open('yolov3.weight', 'rb') as f:
# Read Header https://github.com/AlexeyAB/darknet/issues/2914#issuecomment-496675346
self.version = np.fromfile(f, dtype=np.int32, count=3) # (int32) version info: major, minor, revision
self.seen = np.fromfile(f, dtype=np.int64, count=1) # (int64) number of images seen during training
weights = np.fromfile(f, dtype=np.float32) # the rest are weights
并且文件的第一行代表训练的图片数,第三行代表的是版本信息。还有一个是生成的.pt文件,它的内部字典都是什么呢?
chkpt = {'epoch': -1,
'best_fitness': None,
'training_results': None,
'model': model.state_dict(),
'optimizer': None}
可以看到,yolov5作者记录了五个信息在里面,我们需要的其实就一个model
。
然后对于整体代码的转换,现在没有必要所有都懂,我们只需要知道这样做能够实现转换就行了。
那么问题来了,对于我找的这个第三方pytorch版本的deepsort,他没有这个转化是怎么实现模型权重的加载的呢?
这里首先找到了加载yolov3权重的文件在detector/YOLOv3/detector.py
中,加载deepsort模型权重的文件在deep_sort/deep/feature_extractor.py
中,deepsort文件的格式是pytorch的标准格式,这里就不在赘述。
15:21 debug目的:尝试替代掉原始的加载权重的方式,使用.pt加载的方式。(测试阶段)
- 修改
yolov3_deepsort.py
中的检测器定义
# self.detector = build_detector(cfg, use_cuda=use_cuda) 原始的
"""
这里我们导入几个包,这是我自己工程下的文件,不具有参考性
"""
from models_ios import Darknet
self.detector = Darknet(cfg='configs/yolov3.cfg', namesfile='detector/YOLOv3/cfg/coco.names')
self.detector.load_state_dict(torch.load('detector/YOLOv3/weight/yolov3.pt')['model'])
但是紧接着就遇到的问题是:
Traceback (most recent call last):
File "/home/wlj/Desktop/VOT&S/deep_sort_pytorch-master/yolov3_deepsort.py", line 157, in <module>
vdo_trk.run()
File "/home/wlj/Desktop/VOT&S/deep_sort_pytorch-master/yolov3_deepsort.py", line 90, in run
bbox_xywh, cls_conf, cls_ids = self.detector(im)
RuntimeError: Expected 4-dimensional input for 4-dimensional weight 32 3 3, but got 3-dimensional input of size [1080, 1920, 3] instead
这位同学写的检测器和官方写的检测器好像有些不匹配,但是这位同学是可以成功加载原始的yolov3.weight
,那么就又要进一步看看这位同学和alxexy这个yolov3的内部网络层到底有什么不同了。
well,今天应该是跑不出来了,要改的地方有点多,那么debug一下午有什么收获呢?
- 我们知道了测试的流程,在主代码中,我们现在是卡在了检测器的构建之中,
self.detector = build_detector(cfg, use_cuda=use_cuda)
我一开始就是想让模型加载我转化后的.pt模型,现在是成功加载上了,但是当我们把数据传到检测器中,对数据的处理就开始报错了,这是因为这位同学的检测代码是基于它的model命名来写的,我们的模型不适用,所以,开始想着换一种思路。 - 经过这一个下午的debug,我发现其实这位同学的检测器的实现主要依靠两个文件,分别是
detector/YOLOv3/detector.py
和detector/YOLOv3/darknet.py
,在darknet.py
中实现了对detector/YOLOv3/cfg/yolo_v3.cfg
的model化,然后在detector中实现了对yolov3.weight
的模型加载,那么其实基于这个,我对yolo的代码实现应该有了一个大致的理解了,那么我其实可以基于此,改写成yolov4,那么它的测试过程应该就会顺利进行了。