Skip to content

Commit 05f4f7f

Browse files
committed
🎉 提交代码
1 parent 9b1c9bf commit 05f4f7f

17 files changed

+2577
-0
lines changed

.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ __pycache__/
33
*.py[cod]
44
*$py.class
55

6+
# 模型和视频文件忽略
7+
model_data/mars-small128.pb
8+
model_data/market1501.pb
9+
model_data/yolov4.weights
10+
model_data/yolov4.h5
11+
test.mp4
12+
613
# C extensions
714
*.so
815

README.md

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Deep SORT —— YOLO V4 目标检测跟踪
2+
3+
## 介绍
4+
5+
项目采用 `YOLO V4` 算法模型进行目标检测,使用 `Deep SORT` 目标跟踪算法。
6+
7+
**运行环境**
8+
9+
- Keras==2.4.3
10+
- tensorflow-gpu==2.2.0
11+
- opencv-python==4.3.0.36
12+
- image==1.5.32
13+
- NVIDIA GPU CUDA
14+
15+
## 目录结构
16+
17+
```text
18+
deep-sort-yolov4
19+
20+
┌── deep_sort DeepSort目标跟踪算法
21+
│ ├── detection.py
22+
│ ├── generate_detections.py
23+
│ ├── iou_matching.py
24+
│ ├── kalman_filter.py
25+
│ ├── linear_assignment.py
26+
│ ├── nn_matching.py
27+
│ ├── preprocessing.py
28+
│ ├── track.py
29+
│ └── tracker.py
30+
├── model_data 模型文件数据
31+
│ ├── market1501.pb
32+
│ ├── mars-small128.pb
33+
│ ├── yolov4.h5
34+
│ ├── yolov4.weights
35+
│ └── README.md
36+
├── yolo4 YOLOV4目标检测
37+
│ ├── model.py
38+
│ └── yolo.py
39+
│─── convertToH5.py
40+
│─── detect_video_tracker.py
41+
│─── requirements.txt
42+
│─── test.mp4
43+
└─── README.md
44+
```
45+
46+
## 执行
47+
48+
模型的权重文件要先转出模型H5文件哦
49+
50+
```shell
51+
# 安装依赖
52+
pip install -r requirements.txt
53+
54+
# 模型权重 `yolov4.weights` 转 `yolo4.h5`
55+
python convertToH5.py --input_size 608 --min_score 0.3 --iou 0.5 --model_path model_data/yolov4.h5 --weights_path model_data/yolov4.weights
56+
57+
# 执行视频目标检测跟踪
58+
python detect_video_tracker.py --video test.mp4 --min_score 0.3 --model_yolo model_data/yolov4.h5 --model_feature model_data/mars-small128.pb
59+
```
60+
61+
## 推荐
62+
63+
- [Object-Detection-and-Tracking](https://github.com/yehengchen/Object-Detection-and-Tracking)
64+
- [Deep Sort](https://github.com/nwojke/deep_sort)
65+
- [关于 Deep Sort 的一些理解](https://zhuanlan.zhihu.com/p/80764724)

convertToH5.py

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import os
2+
import argparse
3+
import numpy as np
4+
from keras import backend as K
5+
from keras.models import load_model
6+
from keras.layers import Input
7+
import tensorflow as tf
8+
9+
from yolo4.model import yolo_eval, yolo4_body
10+
11+
# 执行参数 python convertToH5.py --input_size 608 --min_score 0.3 --iou 0.5 --model_path model_data/yolov4.h5 --weights_path model_data/yolov4.weights
12+
# 外部参数配置
13+
parser = argparse.ArgumentParser()
14+
parser.add_argument('--input_size', type=int, default=608, help='Image input size 320 416 512 608.')
15+
parser.add_argument('--min_score', type=float, default=0.3, help='minimum output score.')
16+
parser.add_argument('--iou', type=float, default=0.5, help='target threshold.')
17+
parser.add_argument('--model_path', type=str, default='model_data/yolov4.h5', help='model save type.')
18+
parser.add_argument('--weights_path', type=str, default='model_data/yolov4.weights', help='weight file.')
19+
ARGS = parser.parse_args()
20+
21+
# 数据集识别80类别
22+
CLASSES = {0: 'person', 1: 'bicycle', 2: 'car', 3: 'motorbike', 4: 'aeroplane', 5: 'bus', 6: 'train', 7: 'truck',
23+
8: 'boat', 9: 'traffic light', 10: 'fire hydrant', 11: 'stop sign', 12: 'parking meter', 13: 'bench',
24+
14: 'bird', 15: 'cat', 16: 'dog', 17: 'horse', 18: 'sheep', 19: 'cow', 20: 'elephant', 21: 'bear',
25+
22: 'zebra', 23: 'giraffe', 24: 'backpack', 25: 'umbrella', 26: 'handbag', 27: 'tie', 28: 'suitcase',
26+
29: 'frisbee', 30: 'skis', 31: 'snowboard', 32: 'sports ball', 33: 'kite', 34: 'baseball bat',
27+
35: 'baseball glove', 36: 'skateboard', 37: 'surfboard', 38: 'tennis racket', 39: 'bottle',
28+
40: 'wine glass', 41: 'cup', 42: 'fork', 43: 'knife', 44: 'spoon', 45: 'bowl', 46: 'banana', 47: 'apple',
29+
48: 'sandwich', 49: 'orange', 50: 'broccoli', 51: 'carrot', 52: 'hot dog', 53: 'pizza', 54: 'donut',
30+
55: 'cake', 56: 'chair', 57: 'sofa', 58: 'potted plant', 59: 'bed', 60: 'dining table', 61: 'toilet',
31+
62: 'tvmonitor', 63: 'laptop', 64: 'mouse', 65: 'remote', 66: 'keyboard', 67: 'cell phone',
32+
68: 'microwave', 69: 'oven', 70: 'toaster', 71: 'sink', 72: 'refrigerator', 73: 'book', 74: 'clock',
33+
75: 'vase', 76: 'scissors', 77: 'teddy bear', 78: 'hair drier', 79: 'toothbrush'}
34+
35+
anchors = np.array([12,16, 19,36, 40,28, 36,75, 76,55, 72,146, 142,110, 192,243, 459,401], dtype=np.float)
36+
37+
class Yolo4(object):
38+
39+
def __init__(self, score, iou, model_path, weights_path,input_size, gpu_num=1):
40+
self.score = score
41+
self.input_size = input_size
42+
self.weights_path = weights_path
43+
self.model_path = model_path
44+
self.iou = iou
45+
self.gpu_num = gpu_num
46+
self.load_yolo()
47+
48+
# 加载权重
49+
def load_weights(self,model, weights_file):
50+
wf = open(weights_file, 'rb')
51+
major, minor, revision, seen, _ = np.fromfile(wf, dtype=np.int32, count=5)
52+
53+
j = 0
54+
for i in range(110):
55+
conv_layer_name = 'conv2d_%d' % i if i > 0 else 'conv2d'
56+
bn_layer_name = 'batch_normalization_%d' % j if j > 0 else 'batch_normalization'
57+
58+
conv_layer = model.get_layer(conv_layer_name)
59+
filters = conv_layer.filters
60+
k_size = conv_layer.kernel_size[0]
61+
in_dim = conv_layer.input_shape[-1]
62+
63+
if i not in [93, 101, 109]:
64+
# darknet weights: [beta, gamma, mean, variance]
65+
bn_weights = np.fromfile(wf, dtype=np.float32, count=4 * filters)
66+
# tf weights: [gamma, beta, mean, variance]
67+
bn_weights = bn_weights.reshape((4, filters))[[1, 0, 2, 3]]
68+
bn_layer = model.get_layer(bn_layer_name)
69+
j += 1
70+
else:
71+
conv_bias = np.fromfile(wf, dtype=np.float32, count=filters)
72+
73+
# darknet shape (out_dim, in_dim, height, width)
74+
conv_shape = (filters, in_dim, k_size, k_size)
75+
conv_weights = np.fromfile(
76+
wf, dtype=np.float32, count=np.product(conv_shape))
77+
# tf shape (height, width, in_dim, out_dim)
78+
conv_weights = conv_weights.reshape(conv_shape).transpose([2, 3, 1, 0])
79+
80+
if i not in [93, 101, 109]:
81+
conv_layer.set_weights([conv_weights])
82+
bn_layer.set_weights(bn_weights)
83+
else:
84+
conv_layer.set_weights([conv_weights, conv_bias])
85+
86+
assert len(wf.read()) == 0, 'failed to read all data'
87+
wf.close()
88+
89+
# 保存为h5模型
90+
def load_yolo(self):
91+
model_path = os.path.expanduser(self.model_path)
92+
assert model_path.endswith('.h5'), 'Keras model or weights must be a .h5 file.'
93+
94+
self.class_names = CLASSES
95+
self.anchors = np.array(anchors).reshape(-1, 2)
96+
97+
num_anchors = len(self.anchors)
98+
num_classes = len(self.class_names)
99+
100+
self.sess = tf.compat.v1.Session()
101+
102+
# Load model, or construct model and load weights.
103+
self.yolo4_model = yolo4_body(Input(shape=(self.input_size, self.input_size, 3)), num_anchors//3, num_classes)
104+
105+
# Read and convert darknet weight
106+
self.load_weights(self.yolo4_model, self.weights_path)
107+
108+
self.yolo4_model.save(self.model_path)
109+
110+
self.input_image_shape = K.placeholder(shape=(2, ))
111+
self.boxes, self.scores, self.classes = yolo_eval(
112+
self.yolo4_model.output,
113+
self.anchors,
114+
len(self.class_names),
115+
self.input_image_shape,
116+
score_threshold=self.score
117+
)
118+
print('Dome.')
119+
120+
def close_session(self):
121+
self.sess.close()
122+
123+
if __name__ == '__main__':
124+
125+
yolo4_model = Yolo4(ARGS.min_score, ARGS.iou, ARGS.model_path, ARGS.weights_path, ARGS.input_size)
126+
127+
yolo4_model.close_session()

deep_sort/detection.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# vim: expandtab:ts=4:sw=4
2+
import numpy as np
3+
4+
5+
class Detection(object):
6+
"""
7+
This class represents a bounding box detection in a single image.
8+
9+
Parameters
10+
----------
11+
tlwh : array_like
12+
Bounding box in format `(x, y, w, h)`.
13+
confidence : float
14+
Detector confidence score.
15+
feature : array_like
16+
A feature vector that describes the object contained in this image.
17+
18+
Attributes
19+
----------
20+
tlwh : ndarray
21+
Bounding box in format `(top left x, top left y, width, height)`.
22+
confidence : ndarray
23+
Detector confidence score.
24+
feature : ndarray | NoneType
25+
A feature vector that describes the object contained in this image.
26+
27+
"""
28+
29+
def __init__(self, tlwh, score, classe, color, feature):
30+
self.tlwh = np.asarray(tlwh, dtype=np.float)
31+
self.score = float(score)
32+
self.classe = classe
33+
self.color = color
34+
self.feature = np.asarray(feature, dtype=np.float32)
35+
36+
def to_tlbr(self):
37+
"""Convert bounding box to format `(min x, min y, max x, max y)`, i.e.,
38+
`(top left, bottom right)`.
39+
"""
40+
ret = self.tlwh.copy()
41+
ret[2:] += ret[:2]
42+
return ret
43+
44+
def to_xyah(self):
45+
"""Convert bounding box to format `(center x, center y, aspect ratio,
46+
height)`, where the aspect ratio is `width / height`.
47+
"""
48+
ret = self.tlwh.copy()
49+
ret[:2] += ret[2:] / 2
50+
ret[2] /= ret[3]
51+
return ret

0 commit comments

Comments
 (0)