0x01 Yolo-Fastest
github:Yolo-Fastest 的中文快速上手教程,包括 mAP 计算、darknet 转 tflite
等
目前有个检测的任务,需要轻量级的检测网络,在 NanoDet 和 Yolo-Fastest 中最终选择了后者,
不过要将作者的网络做进一步删减,目标平台(ART-PI)的 FLOPS 要求不超过0.1B
将 yolo-fastest 搬到 artpi 开发板上,且搭载 rt-thread 系统的工具是 RT-AK ,即将开放内测资格,这条仅对嵌入式小伙伴公布
2020.10 之前 号称是全网最轻量级的目标检测网络,有多轻量级呢?请看下面数据:
↓
这是 VOC 数据上的
Network |
Model Size |
mAP(VOC 2017) |
FLOPS |
Tiny YOLOv2 |
60.5MB |
57.1% |
6.97BFlops |
Tiny YOLOv3 |
33.4MB |
58.4% |
5.52BFlops |
YOLO Nano |
4.0MB |
69.1% |
4.51Bflops |
MobileNetv2-SSD-Lite |
13.8MB |
68.6% |
&Bflops |
MobileNetV2-YOLOv3 |
11.52MB |
70.20% |
2.02Bflos |
Pelee-SSD |
21.68MB |
70.09% |
2.40Bflos |
Yolo Fastest |
1.3MB |
61.02% |
0.23Bflops |
Yolo Fastest-XL |
3.5MB |
69.43% |
0.70Bflops |
MobileNetv2-Yolo-Lite |
8.0MB |
73.26% |
1.80Bflops |
这是 COCO 数据集上的
Network |
COCO mAP(0.5) |
Resolution |
Run Time(Ncnn 1xCore) |
Run Time(Ncnn 4xCore) |
FLOPS |
Params |
Weight size |
Yolo-Fastest |
23.65 |
320X320 |
6.74ms |
4.42ms |
0.23BFlops |
0.325M |
1.3M |
Yolo-Fastest-XL |
32.45 |
320X320 |
15.15ms |
7.09ms |
0.70BFlops |
0.875M |
3.5M |
这是 前段时间超级火的 NanoDet
Model |
COCO mAP |
Resolution |
Latency(ARM 4xCore) |
FLOPS |
Params |
Model Size(ncnn bin) |
NanoDet-m |
20.6 |
320*320 |
10.23ms |
0.72B |
0.95M |
1.8mb |
NanoDet-m |
21.7 |
416*416 |
16.44ms |
1.2B |
0.95M |
1.8mb |
YoloV3-Tiny |
16.6 |
416*416 |
37.6ms |
5.62B |
8.86M |
33.7mb |
YoloV4-Tiny |
21.7 |
416*416 |
32.81ms |
6.96B |
6.06M |
23.0mb |
什么?没看懂?!
请详细关注下 FLOPS
和Params
还有Model Size
mAP
啊!!!
兄弟,要是还看不懂,emmm,
0x02 Prepare
由于该项目是基于 Darknet 训练和测试的,在开始之前需要先配置好 Darknet 环境
step1 clone
git clone https://github.com/dog-qiuqiu/Yolo-Fastest
step2 make
System: linux
windows 编译 darknet的请看这:How to compile on Windows
修改 Makefile
, 且编译 make -j
, 成功标志是出现 darknet
这个可执行文件
-
财力充足:GPU
GPU=1
CUDNN=1
CUDNN_HALF=1
OPENCV=1
...
# 我用的是 1080ti, 所以要把前面几行删除
ARCH= -gencode arch=compute_52,code=[sm_52,compute_52] \
-gencode arch=compute_61,code=[sm_61,compute_61]
...
ifeq ($(CUDNN), 1)
COMMON+= -DCUDNN
ifeq ($(OS),Darwin) #MAC
CFLAGS+= -DCUDNN -I/usr/local/cuda/include
LDFLAGS+= -L/usr/local/cuda/lib -lcudnn
else
# CFLAGS+= -DCUDNN -I/usr/local/cudnn/include
# LDFLAGS+= -L/usr/local/cudnn/lib64 -lcudnn
CFLAGS+= -DCUDNN -I/usr/local/cuda/include
LDFLAGS+= -L/usr/local/cuda/lib64 -lcudnn
endif
endif
在这个地方,可能会遇到一些问题。
Makefile
文件中检索的CUDA
路径可能会遇到一些问题。
我习惯了用 conda
来傻瓜式安装 tensorflow
,但是这个时候,这个笨笨的 Makefile 竟然不会识别 conda
环境下的 CUDA
路径
为了简单的快速上手,我选择了脱离 conda
,在服务器上手动安装CUDA
、cudnn
,并且安装了一个 tensorflow-gpu
, 所以上面需要更改 CUDNN
路径
此时,顺利的话,执行 make -j
之后,就应该可以看到当前文件夹下出现一个 darknet
的可执行文件。
Soft |
Version |
CUDA |
11.0.228 |
CUDNN |
cudnn-11.0-linux-x64-v8.0.5.39 |
tensorflow-gpu |
2.4.0 |
当然,还有不顺利的情况,意外频频有,今年特别多。
有一个问题我不记得了,出现的时候没有记录,问题的原因是找不到 nvcc
解决方法:
- 查看
/usr/local/cuda/bin
下是否有nvcc可执行程序
- 添加环境变量,打开
~/.bashrc
,添加环境变量 export PATH=$PATH:/usr/local/cuda/bin
- 如果找不到,重新安装
sudo apt install nvidia-cuda-toolkit
- 是否安装成功命令:
nvcc --version
-
囊中羞涩:CPU
好了,上面的一些巨佬的一些配置通通跟咱们没有任何的关系。
高兴的话,在 Makefile
的第4行,将 OPENCV=0
改成1,保不齐啥时候咱会用到 opencv
这个大杀器。一般我都会必装 opencv
的。
执行:
make -j
在当前文件夹下面,生成了 darknet
可执行文件
step3 run darknet
图片检测验证:
bash image_yolov3.sh
# 等同于
./darknet detector test ./data/coco.data ./Yolo-Fastest/COCO/yolo-fastest.cfg ./Yolo-Fastest/COCO/yolo-fastest.weights data/person.jpg -thresh 0.55
# 不显示图片,因为有时候在服务器上,不能显示图片,会报这个warning,有点看不顺眼
# Gtk-WARNING **: 17:42:47.783: cannot open display:
./darknet detector test ./data/coco.data ./Yolo-Fastest/COCO/yolo-fastest.cfg ./Yolo-Fastest/COCO/yolo-fastest.weights data/person.jpg -thresh 0.55 -dont_show
# 神奇的命令
./darknet detector test ./data/coco.data ./Yolo-Fastest/COCO/yolo-fastest.cfg ./Yolo-Fastest/COCO/yolo-fastest.weights -thresh 0.55 -dont_show
视频检测验证:
# 这个时候就不能直接使用下面这个命令了
# sh video_yolov3.sh
# 需要指定视频路径
./darknet detector demo ./data/coco.data ./Yolo-Fastest/COCO/yolo-fastest.cfg ./Yolo-Fastest/COCO/yolo-fastest.weights /home/lebhoryi/RT-Thread/Detection_API/video/000.mp4 -thresh 0.55
0x03 Train
作者的建议是先获取训练好的权重文件,然后在此基础上做训练。嗯,按照作者的思路走,不会有坑
以训练单个person类别为例,VOC数据集
step1 获取权重文件
./darknet partial yolo-fastest.cfg yolo-fastest.weights yolo-fastest.conv.109 109
step2 准备数据集
# 该步骤来自:https://pjreddie.com/darknet/yolo/
# Training YOLO on VOC
# Get The Pascal VOC Data
wget https://pjreddie.com/media/files/VOCtrainval_11-May-2012.tar
wget https://pjreddie.com/media/files/VOCtrainval_06-Nov-2007.tar
wget https://pjreddie.com/media/files/VOCtest_06-Nov-2007.tar
tar xf VOCtrainval_11-May-2012.tar
tar xf VOCtrainval_06-Nov-2007.tar
tar xf VOCtest_06-Nov-2007.tar
# Generate Labels for VOC
# <object-class> <x> <y> <width> <height>
# 记得修改代码文件中对应的路径,由于要训练一个person类别,classes那里也需要做更改
# classes = ['person']
wget https://pjreddie.com/media/files/voc_label.py
python voc_label.py
ls
# 2007_test.txt VOCdevkit
# 2007_train.txt voc_label.py
# 2007_val.txt VOCtest_06-Nov-2007.tar
# 2012_train.txt VOCtrainval_06-Nov-2007.tar
# 2012_val.txt VOCtrainval_11-May-2012.tar
cat 2007_train.txt 2007_val.txt 2012_*.txt > train.txt
step3 修改 data/voc.data 和 data/voc.names
classes= 1
train = <path-to-voc>/train.txt
valid = <path-to-voc>/2007_test.txt
names = data/voc.names
backup = backup # 模型存储文件夹
将 data/voc.names
文件中的类别删除只剩下 person
step4 train
./darknet detector train voc.data ./Yolo-fastest/VOC/yolo-fastest.cfg yolo-fastest.conv.109
训练好的模型文件将会保存在backup
文件夹下面。
step5 mAP
# 我选择了最简单的,更多信息请戳下面链接
# https://github.com/MuhammadAsadJaved/darknet#how-to-calculate-map-on-pascalvoc-2007
# points 11 是VOC 数据集,101 是 MS COCO,0 是 ImageNet, PascalVOC 2010-2012, your custom dataset
./darknet detector map data/voc.data Yolo-Fastest/VOC/yolo-fastest.cfg Yolo-Fastest/VOC/yolo-fastest.weights -points 11
这个时候,就很奇怪,我测出来是 56.19 %,没有到作者说的61.02%,可能是数据集不对,我用 VOC2007 测得,作者上写的是 VOC2017
这个不重要,重要的是我成功获取了mAP
这个指标。嗯,距离大佬又近了一步。
0x04 darknet 转 keras、tflite
既然看到了这里,差不多大家都可以获取到 darknet
训练好的模型
但是在下对 darknet
不熟啊,要搬到目标平台,还是 keras
和 tflite
更适合我
然后,认真的看了两圈作者的仓库,没有发现如何转 tensorflow
的教程,嗯,问题不大,因为我发现了这个:
NCNN
和 MNN
,这些都吸引不了我,我一眼就相中了 TensorRT
,正好手里有一块 Jetson nano
,等下周挤出点时间折腾一下。
darknet
转 keras
、tflite
仓库:
david8862/keras-YOLOv3-model-set
step1 darknet 转 keras
git clone https://github.com/david8862/keras-YOLOv3-model-set
cd keras-YOLOv3-model-set
pip install -r requirement.txt
# -f 是固定输入,否则你会发现输入是 None×None×3
# -p 是将神经网络结构图保存为 <name>.png
python tools/model_converter/convert.py <path-to-cfg>/yolo-fastest.cfg <path-to-weights>/yolo-fastest.weights weights/yolo-s.h5 -f -p
如果你训练的时候,输入是 weight×height×1,则需要改动:
...
print('Creating Keras model.')
if width and height and args.fixed_input_shape:
# input_layer = Input(shape=(height, width, 3), name='image_input')
input_layer = Input(shape=(height, width, 1), name='image_input')
else:
# input_layer = Input(shape=(None, None, 3), name='image_input')
input_layer = Input(shape=(None, None,1), name='image_input')
...
step2 keras 转 tflite
python tools/model_converter/custom_tflite_convert.py --keras_model_file ./weights/yolo-fastest.h5 --output_file ./weights/yolo-fastest.tflite
step3 keras 转 int8 量化的 tflite
python tools/model_converter/post_train_quant_convert.py --keras_model_file ./weights/yolo-fastest.h5 --annotation_file <path-to-voc>/2007_test.txt --model_input_shape 320x320 --sample_num 30 --output_file ./weights/yolo-fastest.tflite
如果你训练的时候,输入是 weight×height×1,则需要改动:
...
image = np.array([image], dtype=np.float32)
image = image[..., -1]
image = np.expand_dims(image, axis=-1)
yield [image]
...
0x05 魔改网络结构
Model |
mAP(%) |
Input |
BFLOPS |
Size |
Inference |
Data |
yolo-fastest |
56.19 |
320x320x3 |
0.238 |
613.6k |
Failed |
01/09 |
yolo-xl |
44.51 |
320x320x1 |
0.096 |
224.1k |
Failed |
01/08 |
yolo-l |
22.67 |
320x320x1 |
0.057 |
176.7k |
787ms |
01/12 |
yolo-s |
28.41 |
160x160x1 |
0.012 |
146.5k |
|
~~01/13 ~~ |
yolo-s 单类别检测(人):21.58%,在 art-pi 上的推理时间是 50ms
推理时间是在 rt-thread
系统 + ART-PI
开发板下做的测试
Size
是量化后的 tflite
模型大小
i5-9400
yolo-fastest
的推理时间是 50ms,mAP 56.19%
i5-9400
yolo-xl
的推理时间是 19ms,mAP 44.51%
i5-9400
yolo-l
的推理时间是 10ms,mAP 22.67%
有一个问题,1080ti 服务器下的推理时间是150ms
,不知道为啥
好了,下一步就是将yolo-fastest
请上jetson nano
…
0x06 参考文献