在树莓派上运行YOLO-v4

本文最后更新于:2022年7月29日 晚上

引言

需要在树莓派上完成调用YOLO-v4并且尽量减少推理时间的任务。

大部分时间在尝试如何在树莓派上运行基于PyTorch的YOLO-v4,最终使用基于OpenCV-Python调用YOLO-v4可行,推理时间4s左右。

OpenCV有加速库,所以比基于darknet的YOLO-v4推理速度更快一些,而基于OpenCV编译的darknet并没有加速,需要再实验论证。

环境&准备

为最大化树莓派效能,我们为树莓派刷入了Ubuntu 20.04 Server的基于arm64的系统。由于特殊原因,我们也使用了Ubuntu官网提供的Ubuntu 18.04 Desktop系统。

为了效率和方便,我们使用pip安装我们的深度学习环境,为了提升速度我们首先替换系统中的apt源和使用国内的pip源。又为了避免破坏系统环境的python,我们一般使用anaconda来管理深度学习环境。由于基于arm64的anaconda还没有发行,我们使用Miniforge来替代。直接下载bash安装后切换用户即可。

PyTorch相关第三方包Here

实现

基于PyTorch的YOLO-v4

在Github中搜索YOLO-v4,down下几个Top基于PyTorch实现的YOLO-v4库。然而,我发现这些基于PyTorch的YOLO-v4在推理照片的时候无法正常运行,所有数据都是错误的。我怀疑是树莓派内存太小导致模型无法正常加载,所以尝试使用darknet实现YOLO-v4。

在后来的实验中,我们同样验证了相同的结果,使用基于PyTorch的YOLO-v4-tiny是可以正常运行,但仍比基于darknet的YOLO-v4-tiny推理要慢。

基于Darknet的YOLO-v4

从Github上down下来官方的darknet库,按照要求解压进入文件夹进行make -j8编译,结果发现并不能正常编译,原来是Ubuntu20.10系统的g++版本太高,导致无法正常进行编译,所以我们使用Ubuntu18.04系统继续进行编译,编译可以正常通过。需要注意的是,如果考虑是否与OpenCV一起编译,请修改Makefile文件。若compile with OpenCV,请apt install libOpenCV-dev

基于Darknet的YOLO-v4的推理耗时在58s左右,YOLO-v4-tiny的推理时间在2s左右,这个数据并不能令我们满意,而且由于要使用flask,我们只得又使用Ubuntu20.10系统寻求新的方法。

基于OpenCV-python的YOLO-v4

我们知道OpenCV4已经内置了YOLO-v4的调用,所以我们使用pip install OpenCV-python==4.4.0,使用内置函数进行调用,可以正常使用,YOLO-v4推理时间为4s左右,YOLO-v4-tiny为0.4s左右,it is over。简单调用一个代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import cv2 as cv
import time
import os

basedir = os.path.abspath(os.path.dirname(__file__))
index = basedir.rfind('/')
basedir = basedir[:index]
model_dir=basedir+'/ming_net/'

def uav_detect(img_name, img):
net = cv.dnn_DetectionModel(model_dir+'YOLO-v4.cfg', model_dir+'YOLO-v4.weights')
net.setInputSize(320, 320)
net.setInputScale(1.0 / 255)
net.setInputSwapRB(True)
frame = cv.imread(img)
with open(model_dir+'coco.names', 'rt') as f:
names = f.read().rstrip('\n').split('\n')
startTime = time.time()
classes, confidences, boxes = net.detect(frame, confThreshold=0.1, nmsThreshold=0.4)
endTime = time.time()
print("Time: {}s".format(endTime - startTime))

for classId, confidence, box in zip(classes.flatten(), confidences.flatten(), boxes):
if classId==0:
coordinates = []
boxes_item_package = {}
label = '%.2f' % confidence
label = '%s: %s' % (names[classId], label)
labelSize, baseLine = cv.getTextSize(label, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1)
left, top, width, height = box
top = max(top, labelSize[1])
cv.rectangle(frame, box, color=(0, 255, 0), thickness=1)
cv.rectangle(frame, (left, top - labelSize[1]), (left + labelSize[0], top + baseLine), (0, 0, 255), cv.FILLED)
cv.putText(frame, label, (left, top), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0))

cv.waitKey(0)
return frame


基于YOLObile的尝试

由于我们的主要目的是最小化在树莓派这样性能羸弱的平台上推理YOLO网络的耗时,所以当我看到YOLObile宣称超越YOLO-v4-tiny时,我决定进行尝试。但是最终基于YOLO-v4推理一张图片耗时为40s。

猜想本次实验与其宣称的差异是因为树莓派没有独立GPU,而原文的对比试验是基于三星S20的GPU进行。

Note

  • 需要注意的是,为了推理速度,我们使用的所有输入尺寸都为320*320,请在各种cfg文件中修改。
  • 在Ubuntu 20.10系统中,matplotlib是无法安装的。
  • 在Ubuntu 18.04系统中安装一些软件会出现错误:缺少glibc2.28。因此无法使用flask,目前没有找到解决方法。

实验

设备/系统 backbone 置信度 耗费时间
树莓派arm64Ubuntu 20 YOLO-v4/OpenCV person5/0.95/0.91/0.87 3.49s
树莓派arm64Ubuntu 20 YOLO-v4-tiny/OpenCV person2/0.88/0.73 0.3911s
树莓派arm64Ubuntu 20 YOLO-v4-custom/OpenCV person3/0.83/0.83/0.68 3.49s
树莓派arm64Ubuntu 18 YOLO-v4/darknet person6 75s
树莓派arm64Ubuntu 18 YOLO-v4-tiny/darknet person2/0.88/0.73 2s
树莓派arm64Ubuntu 18 YOLO-v4/darknet-compiled with OpenCV person6 75s
树莓派arm64Ubuntu 20 YOLO-v4-tiny/pytorch 内存溢出
树莓派arm64Ubuntu 20 YOLO-v4-tiny/pytorch person2/0.88/0.73 5.68s