构建基于DeepStream的YOLOV3视频监控程式
本文提供了使用DeepStream开发基于YOLOV3的USB智能分析程式。
目标检测算法:YOLO V3
取像硬件:USB高速相机
运行平台:Jetson Nano
先决条件
- Ubuntu 18.04
- DeepStream SDK 5.0 or later
- Python 3.6
- Gst Python v1.14.5
安装DeepStream
假使这里已经有了一台安装了Jetpack 4.4的Jetson Nano(以下简称为Nano)。
使用如下指令安装DeepStream 5.0:
sudo apt-get install DeepStream-5.0
一切顺利的话,DeepStream会自动安装到以下目录下:
/opt/nvidia/deepstream/deepstream-5.0
安装DeepStream的Python绑定
先clone一下deepstream_python_apps
:
git clone https://github.com/NVIDIA-AI-IOT/deepstream_python_apps.git
clone完毕后会在Nano的home
目录下发现deepstrem_python_apps
文件夹。
此时deepstrem_python_apps文件夹的文件如下所示:
.
├── apps
│ ├── common
│ ├── deepstream-imagedata-multistream
│ ├── deepstream-ssd-parser
│ ├── deepstream-test1
│ ├── deepstream-test1-rtsp-out
│ ├── deepstream-test1-usbcam
│ ├── deepstream-test2
│ ├── deepstream-test3
│ ├── deepstream-test4
│ └── README
├── FAQ.md
├── HOWTO.md
├── LICENSE
├── notebooks
│ ├── deepstream_test_1.ipynb
│ └── deepstream_test_4.ipynb
└── README.md
执行以下指令将DeepStream的Python Apps拷贝至DeepStream目录下:
cp -r deepstream_python_apps /opt/nvidia/deepstream/deepstream-5.0/sources
SDK MetaData库是用C / C ++开发的。Python绑定提供了从Python应用程序对MetaData的访问。绑定在已编译的模块中提供,可用于x86_64和Jetson平台。该模块pyds.so
在DeepStream安装目录的lib
中提供。
把pyds.so
文件复制到deepstream_python_apps/apps
下:
cp /opt/nvidia/deepstream/deepstream-5.0/lib/pyds.so /opt/nvidia/deepstream/deepstream-5.0/sources/deepstream_python_apps/apps
此时deepstrem_python_apps文件夹的目录结构如下所示:
.
├── apps
│ ├── common
│ ├── deepstream-imagedata-multistream
│ ├── deepstream-ssd-parser
│ ├── deepstream-test1
│ ├── deepstream-test1-rtsp-out
│ ├── deepstream-test1-usbcam
│ ├── deepstream-test2
│ ├── deepstream-test3
│ ├── deepstream-test4
│ ├── README
│ └── pyds.so
├── FAQ.md
├── HOWTO.md
├── LICENSE
├── notebooks
│ ├── deepstream_test_1.ipynb
│ └── deepstream_test_4.ipynb
└── README.md
可以看到apps目录下多了个pyds.so文件。
运行示例程序
现在插入USB相机就可以运行示例程序了。
在/opt/nvidia/deepstream/deepstream-5.0/sources/deepstream_python_apps/apps/deepstream-test1-usbcam
目录下运行:
python3 deepstream_test_1_usb.py /dev/video0
可以看到此时基于USB相机的DeepStream示例程序启动了起来。
可以看到启动速度过慢。
查看配置文件,可以看到示例程序使用的是基于resnet10
的caffemodel
。
接下里我们尝试使用自定义的YOLO模型。
使用自定义YOLO模型
1-重新编译libnvdsinfer_custom_impl_Yolo.so
切换目录至/opt/nvidia/deepstream/deepstream-5.0/sources/objectDetector_Yolo/nvdsinfer_custom_impl_Yolo
下:
cd /opt/nvidia/deepstream/deepstream-5.0/sources/objectDetector_Yolo/nvdsinfer_custom_impl_Yolo
打开nvdsparsebbox_Yolo.cpp
gedit nvdsparsebbox_Yolo.cpp
更改NUM_CLASSES_YOLO常量的值以反映模型中的类数。例如,如果您的模型使用80个类:
static const int NUM_CLASSES_YOLO = 80;
在NvDsInferParseCustomYoloV3()
(如果使用YOLOv3
)或NvDsInferParseCustomYoloV3Tiny()
(如果使用)中用新的模型参数替换模型参数。以作为一个例子:tiny YOLOv3``YOLOv3
extern "C" bool NvDsInferParseCustomYoloV3(
std::vector<NvDsInferLayerInfo> const& outputLayersInfo,
NvDsInferNetworkInfo const& networkInfo,
NvDsInferParseDetectionParams const& detectionParams,
std::vector<NvDsInferParseObjectInfo>& objectList)
{
. . .
## 9 clusters from COCO dataset
const std::vector<float> kANCHORS =
{10.0, 13.0, 16.0, 30.0, 33.0, 23.0, 30.0, 61.0, 62.0,
45.0, 59.0, 119.0, 116.0, 90.0, 156.0, 198.0, 373.0, 326.0};
## Specifies which of the 9 anchors above to use
static const std::vector<std::vector<int>> kMASKS = {
{6, 7, 8},
{3, 4, 5},
{0, 1, 2}};
}
这里就是把锚点数据更改成自己模型的。
YOLOv2
和tiny YOLOv2
执行一样的操作即可。
切换至/opt/nvidia/deepstream/deepstream-5.0/sources/objectDetector_Yolo/nvdsinfer_custom_impl_Yolo
下:
cd /opt/nvidia/deepstream/deepstream-5.0/sources/objectDetector_Yolo/nvdsinfer_custom_impl_Yolo
执行如下步骤重新编译libnvdsinfer_custom_impl_Yolo.so:
export CUDA_VER=10.2 # 这里切换为目标设备CUDA的版本号
make -C nvdsinfer_custom_impl_Yolo
可以看到此时生成了libnvdsinfer_custom_impl_Yolo.so动态链接库文件。
2-构建工作文件夹
构建工作文件夹如下所示:
.
├── common
│ ├── bus_call.py
│ ├── FPS.py
│ ├── __init__.py
│ ├── is_aarch_64.py
│ ├── __pycache__
│ │ ├── bus_call.cpython-36.pyc
│ │ ├── __init__.cpython-36.pyc
│ │ └── is_aarch_64.cpython-36.pyc
│ └── utils.py
├── config_infer_primary_yoloV3_tiny.txt
├── deepstream_test_1_usb.py
├── labels.txt
├── libnvdsinfer_custom_impl_Yolo.so
├── pyds.so
├── yolov3-tiny.cfg
└── yolov3-tiny.weights
文件的来源如下表所示:
文件/文件夹 | 来源 |
---|---|
common | /opt/nvidia/deepstream/deepstream-5.0/sources/deepstream_python_apps/apps |
config_infer_primary_yoloV3_tiny.txt | /opt/nvidia/deepstream/deepstream-5.0/sources/objectDetector_Yolo |
deepstream_test_1_usb.py | /opt/nvidia/deepstream/deepstream-5.0/sources/deepstream_python_apps/apps/deepstream-test1-usbcam |
labels.txt | /opt/nvidia/deepstream/deepstream-5.0/sources/objectDetector_Yolo |
libnvdsinfer_custom_impl_Yolo.so | /opt/nvidia/deepstream/deepstream-5.0/sources/objectDetector_Yolo/nvdsinfer_custom_impl_Yolo |
pyds.so | /opt/nvidia/deepstream/deepstream-5.0/lib |
yolov3-tiny.cfg | darknet |
yolov3-tiny.weights | darknet |
修改config_infer_primary_yoloV3_tiny.txt如下所示:
[property]
gpu-id=0
net-scale-factor=0.0039215697906911373
#0=RGB, 1=BGR
model-color-format=0
custom-network-config=yolov3-tiny.cfg # 这里修改为自己的模型配置文件
model-file=yolov3-tiny.weights # 这里修改为自己的模型权重文件
#model-engine-file=yolov3-tiny_b1_gpu0_fp32.engine # 第一次运行后可以取消注释此行,并替换为自己的engine的文件名
labelfile-path=labels.txt # 标签文件文件地址,类似于darknet的coco.names文件
## 0=FP32, 1=INT8, 2=FP16 mode
network-mode=0
num-detected-classes=80 # 类别数
gie-unique-id=1
network-type=0
is-classifier=0
## 0=Group Rectangles, 1=DBSCAN, 2=NMS, 3= DBSCAN+NMS Hybrid, 4 = None(No clustering)
cluster-mode=2
maintain-aspect-ratio=1
parse-bbox-func-name=NvDsInferParseCustomYoloV3Tiny
custom-lib-path=libnvdsinfer_custom_impl_Yolo.so # libnvdsinfer_custom_impl_Yolo.so动态链接库的地址
engine-create-func-name=NvDsInferYoloCudaEngineGet
#scaling-filter=0
#scaling-compute-hw=0
[class-attrs-all]
nms-iou-threshold=0.3 # iou阈值
threshold=0.7 # 置信度
修改deepstream_test_1_usb.py
将下面这行:
pgie.set_property('config-file-path', "dstest1_pgie_config.txt") # 修改为自己的配置文件文件地址
修改为:
pgie.set_property('config-file-path', "config_infer_primary_yoloV3_tiny.txt")
修改labels.txt为自己模型的类别
这里有80个类别(不要有空行):
person
bicycle
car
motorbike
aeroplane
bus
train
truck
boat
traffic light
fire hydrant
stop sign
parking meter
bench
bird
cat
dog
horse
sheep
cow
elephant
bear
zebra
giraffe
backpack
umbrella
handbag
tie
suitcase
frisbee
skis
snowboard
sports ball
kite
baseball bat
baseball glove
skateboard
surfboard
tennis racket
bottle
wine glass
cup
fork
knife
spoon
bowl
banana
apple
sandwich
orange
broccoli
carrot
hot dog
pizza
donut
cake
chair
sofa
pottedplant
bed
diningtable
toilet
tvmonitor
laptop
mouse
remote
keyboard
cell phone
microwave
oven
toaster
sink
refrigerator
book
clock
vase
scissors
teddy bear
hair drier
toothbrush
现在就做完了所有的准备工作。
使用自定义的YOLO模型启动DeepStream的USB范例:
python3 deepstream_test_1_usb.py /dev/video0 # 使用USB 0 号相机
可以看到启动速度过慢。
此时会在同目录下生成一个后缀为engine的文件。
改善启动速度慢的问题
DeepStream程序每次启动的时候,都会先从YOLO的模型文件里读取数据,先生成一个engine文件。
这个阶段占用了大多数的启动时间。
尝试修改config_infer_primary_yoloV3_tiny.txt
文件中的model-engine-file
这一行:
- 先取消注释这一行
- 再把此行修改为生成的engine文件地址
[property]
gpu-id=0
net-scale-factor=0.0039215697906911373
#0=RGB, 1=BGR
model-color-format=0
custom-network-config=yolov3-tiny.cfg
# model-file=yolov3-tiny.weights # 注释这一行,不使用原生darknet的YOLO模型
model-engine-file=yolov3-tiny_b1_gpu0_fp32.engine # 这里取消注释,修改为生成的engine文件的文件地址
labelfile-path=labels.txt
## 0=FP32, 1=INT8, 2=FP16 mode
network-mode=0
num-detected-classes=80
gie-unique-id=1
network-type=0
is-classifier=0
## 0=Group Rectangles, 1=DBSCAN, 2=NMS, 3= DBSCAN+NMS Hybrid, 4 = None(No clustering)
cluster-mode=2
maintain-aspect-ratio=1
parse-bbox-func-name=NvDsInferParseCustomYoloV3Tiny
custom-lib-path=libnvdsinfer_custom_impl_Yolo.so
engine-create-func-name=NvDsInferYoloCudaEngineGet
#scaling-filter=0
#scaling-compute-hw=0
[class-attrs-all]
nms-iou-threshold=0.3
threshold=0.7
再次启动,发现DeepStream程序很快的就启动了起来。