第4回:训练模型转换和目标检测
这次,我们使用了SSD Mobilenet v2 coco的对象检测方法,该方法是使用COCO数据集进行训练的模型,可以检测90种目标,并且使用了Google Colab在第2部分中创建的原始学习模型。 介绍目标检测方法。
使用SSD_mobilenet_v2进行对象检测
首先,我想使用SSD Mobilenet v2 coco检测对象。
①下载SSD Mobilenet v2 coco
首先,下载SSD Mobilenet v2 coco模型。 顺便说一句,训练后的模型称为“模型动物园”,可以从“ Tensor Flow 1 Detection Model Zoo”站点下载。
$ cd $ wget http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v2_coco_2018_03_29.tar.gz ・・・省略・・・ $
②解压缩档案 下载完成后,解压缩tar.gz存档。 您有一个类似于创建原始学习模型时的文件,例如Frozen_inference_graph.pb。 解压缩后,移动目录。
③创建用于uff转换的配置文件 Tensorflow pb文件在Jetson nano的TensorRT中无法按原样提供。 因此,您需要将TensorRT的pb文件转换为uff文件。 创建转换所需的配置文件“ config.py”,如下所示。 NVIDIA开发者论坛在此介绍了此内容。
import graphsurgeon as gs import tensorflow as tf Input = gs.create_node("Input", op="Placeholder", dtype=tf.float32, shape=[1, 3, 300, 300]) PriorBox = gs.create_plugin_node(name="GridAnchor", op="GridAnchor_TRT", numLayers=6, minSize=0.2, maxSize=0.95, aspectRatios=[1.0, 2.0, 0.5, 3.0, 0.33], variance=[0.1,0.1,0.2,0.2], featureMapShapes=[19, 10, 5, 3, 2, 1]) NMS = gs.create_plugin_node(name="NMS", op="NMS_TRT", shareLocation=1, varianceEncodedInTarget=0, backgroundLabelId=0, confidenceThreshold=1e-8, nmsThreshold=0.6, topK=100, keepTopK=100, numClasses=91, ########################################### #inputOrder=[0, 2, 1], inputOrder=[1, 0, 2], ########################################### confSigmoid=1, isNormalized=1, scoreConverter="SIGMOID") concat_priorbox = gs.create_node(name="concat_priorbox", op="ConcatV2", dtype=tf.float32, axis=2) concat_box_loc = gs.create_plugin_node("concat_box_loc", op="FlattenConcat_TRT", dtype=tf.float32, axis=1, ignoreBatch=0) concat_box_conf = gs.create_plugin_node("concat_box_conf", op="FlattenConcat_TRT", dtype=tf.float32, axis=1, ignoreBatch=0) namespace_plugin_map = { "MultipleGridAnchorGenerator": PriorBox, "Postprocessor": NMS, "Preprocessor": Input, "ToFloat": Input, "image_tensor": Input, # "MultipleGridAnchorGenerator/Concatenate": concat_priorbox, "Concatenate": concat_priorbox, "concat": concat_box_loc, "concat_1": concat_box_conf } def preprocess(dynamic_graph): all_assert_nodes = dynamic_graph.find_nodes_by_op("Assert") dynamic_graph.remove(all_assert_nodes, remove_exclusive_dependencies=True) all_identity_nodes = dynamic_graph.find_nodes_by_op("Identity") dynamic_graph.forward_inputs(all_identity_nodes) dynamic_graph.collapse_namespaces(namespace_plugin_map) dynamic_graph.remove(dynamic_graph.graph_outputs, remove_exclusive_dependencies=False) dynamic_graph.find_nodes_by_op("NMS_TRT")[0].input.remove("Input")
④转换为uff文件 创建config.py后,使用NVIDIA版本Tensorflow中包含的“ convert_to_uff.py”将pb文件转换为uff文件,如下所示。 我在这里跌跌撞撞,担心了大约两个星期
$ python3 /usr/lib/python3.6/dist-packages/uff/bin/convert_to_uff.py frozen_inference_graph.pb -o frozen_inference_graph.uff -O NMS -p config.py ・・・省略・・・ NOTE: UFF has been tested with TensorFlow 1.15.0. WARNING: The version of TensorFlow installed on this system is not guaranteed to work with UFF. UFF Version 0.6.9 === Automatically deduced input nodes === [name: "Input" op: "Placeholder" attr { key: "dtype" value { type: DT_FLOAT } } attr { key: "shape" value { shape { dim { size: 1 } dim { size: 3 } dim { size: 300 } dim { size: 300 }
⑤nvinfer_custom_impl的副本 接下来,为SSD模型创建一个nvinfer自定义插件。 即使它是一个自定义插件,也按原样使用NVIDIA示例。 首先,复制NVIDIA源。 复制的源中的“ objectDetector_SSD”目录中存在nvinfer_custom_impl。
⑥建立nvinfer_custom_impl 然后构建nvinfer_custom_impl。 构建需要“ CUDA_VER”环境变量,因此请在构建之前进行设置。 如果构建成功,将创建“ libnvdsinfer_custom_impl_ssd.so”。 将创建的“ libnvdsinfer_custom_impl_ssd.so”复制到uff文件所在的目录。
$ export CUDA_VER=10.2 $ echo $CUDA_VER 10.2 $ make -C nvdsinfer_custom_impl_ssd make: Entering directory '/home/test/ssd_mobilenet_v2_coco_2018_03_29/sources/objectDetector_SSD/nvdsinfer_custom_impl_ssd' g++ -o libnvdsinfer_custom_impl_ssd.so nvdsparsebbox_ssd.cpp nvdsiplugin_ssd.cpp -Wall -Werror -std=c++11 -shared -fPIC -Wno-error=deprecated-declarations -I../../includes -I/usr/local/cuda-10.2/include -Wl,--start-group -lnvinfer -lnvparsers -L/usr/local/cuda-10.2/lib64 -lcudart -lcublas -Wl,--end-group make: Leaving directory '/home/test/ssd_mobilenet_v2_coco_2018_03_29/sources/objectDetector_SSD/nvdsinfer_custom_impl_ssd' $ ls -l nvdsinfer_custom_impl_ssd/ total 120 -rw-r--r-- 1 test test 1865 12月 12 19:18 Makefile -rwxrwxr-x 1 test test 97888 12月 12 19:22 libnvdsinfer_custom_impl_ssd.so -rw-r--r-- 1 test test 11515 12月 12 19:18 nvdsiplugin_ssd.cpp -rw-r--r-- 1 test test 4670 12月 12 19:18 nvdsparsebbox_ssd.cpp $ cp nvdsinfer_custom_impl_ssd/libnvdsinfer_custom_impl_ssd.so ../../
⑦创建标签文件 接下来,使用检测到的对象的名称创建一个标签文件。 您可以在此处下载COCO型号标签列表。 但是,似乎必须将第一行设置为“未定义”,因此请将“未定义”添加到第一行。
$ cd ../../ $ wget https://raw.githubusercontent.com/amikelive/coco-labels/master/coco-labels-paper.txt $ ls -l coco-labels-paper.txt -rw-rw-r-- 1 test test 702 12月 12 21:42 coco-labels-paper.txt $sed -i '1s/^/Undefined\n/' coco-labels-paper.txt $
⑧创建nvinfer设置文件 如下创建nvinfer配置文件“ config_infer.txt”。 在此文件中,描述到目前为止准备的三个文件(分别是uff,label)的路径。 顺便说一下,模型引擎文件是自动生成的,因此目前没有文件。
⑨创建应用程序设置文件 最后,为Deep Stream应用程序创建一个配置文件“ app_config.txt”。 关键是配置文件部分。 请通过参考上一篇文章来自定义[source0]和[sink0]。
⑩确认所需文件 完成到目前为止的步骤后,您将拥有以下5个文件,因此让我们检查一下! !!
11.运行DeepStream应用 现在,让我们运行DeepStream应用程序并测试是否可以检测到对象!
以下是物体检测结果的视频。 可以检测到汽车,人和公共汽车!
这样就可以使用SSD Mobilenet v2 coco完成对象检测。
使用原始模型进行物体检测
从这里开始,我们将使用IBM Cloud Annotations进行注释,并使用通过Google Colab学习的原始模型执行对象检测。 该过程与SSD Mobilenet v2的过程相同,但是原始模型具有可检测到的不同数量的对象,因此需要更改此部分。 ①上传模型文件 首先,创建一个工作目录“ myModel”,上传在Google Colab中创建的模型,然后将其解压缩。 另外,上传测试视频文件“ input.mp4”。
②所需文件的副本 复制为SSD Mobilenet v2 coco创建的“ config.py”,“ app_config.txt”,“ config_infer.txt”文件和“ sources”目录。
③编辑配置文件以进行uff转换 首先,将“ config.py”的第23行上的“ numClasses = 91”描述更改为“ numClasses = 3”。 数字“ 3”是标签数+1。 在原始模型中,定义了两个标签“ Untitled Label”和“ flower”,因此为“ 3”。 另外,由于原始模型包含“ Cost”操作,并且会发生错误,因此请在“ config.py”的最后一行添加两行以删除“ Cast”操作。
import graphsurgeon as gs import tensorflow as tf Input = gs.create_node("Input", op="Placeholder", dtype=tf.float32, shape=[1, 3, 300, 300]) PriorBox = gs.create_plugin_node(name="GridAnchor", op="GridAnchor_TRT", numLayers=6, minSize=0.2, maxSize=0.95, aspectRatios=[1.0, 2.0, 0.5, 3.0, 0.33], variance=[0.1,0.1,0.2,0.2], featureMapShapes=[19, 10, 5, 3, 2, 1]) NMS = gs.create_plugin_node(name="NMS", op="NMS_TRT", shareLocation=1, varianceEncodedInTarget=0, backgroundLabelId=0, confidenceThreshold=1e-8, nmsThreshold=0.6, topK=100, keepTopK=100, numClasses=3, ########################################### #inputOrder=[0, 2, 1], inputOrder=[1, 0, 2], ########################################### confSigmoid=1, isNormalized=1, scoreConverter="SIGMOID") concat_priorbox = gs.create_node(name="concat_priorbox", op="ConcatV2", dtype=tf.float32, axis=2) concat_box_loc = gs.create_plugin_node("concat_box_loc", op="FlattenConcat_TRT", dtype=tf.float32, axis=1, ignoreBatch=0) concat_box_conf = gs.create_plugin_node("concat_box_conf", op="FlattenConcat_TRT", dtype=tf.float32, axis=1, ignoreBatch=0) namespace_plugin_map = { "MultipleGridAnchorGenerator": PriorBox, "Postprocessor": NMS, "Preprocessor": Input, "ToFloat": Input, "image_tensor": Input, # "MultipleGridAnchorGenerator/Concatenate": concat_priorbox, "Concatenate": concat_priorbox, "concat": concat_box_loc, "concat_1": concat_box_conf } def preprocess(dynamic_graph): all_assert_nodes = dynamic_graph.find_nodes_by_op("Assert") dynamic_graph.remove(all_assert_nodes, remove_exclusive_dependencies=True) all_identity_nodes = dynamic_graph.find_nodes_by_op("Identity") dynamic_graph.forward_inputs(all_identity_nodes) dynamic_graph.collapse_namespaces(namespace_plugin_map) dynamic_graph.remove(dynamic_graph.graph_outputs, remove_exclusive_dependencies=False) dynamic_graph.find_nodes_by_op("NMS_TRT")[0].input.remove("Input") cast_nodes = dynamic_graph.find_nodes_by_op("Cast") dynamic_graph.remove(cast_nodes, remove_exclusive_dependencies=False)
④转换为uff文件
编辑“ config.py”后,将pb文件转换为uff文件。
$python3 /usr/lib/python3.6/dist-packages/uff/bin/convert_to_uff.py frozen_inference_graph.pb -o frozen_inference_graph.uff -O NMS -p config.py ・・・省略・・・ UFF Version 0.6.9 === Automatically deduced input nodes === [name: "Input" op: "Placeholder" input: "Cast" attr { key: "dtype" value { type: DT_FLOAT } } attr { key: "shape" value { shape { dim { size: 1 } dim { size: 3 } dim { size: 300 } dim { size: 300 } } } } ] ========================================= Using output node NMS Converting to UFF graph ・・・省略・・・ No. nodes: 644 UFF Output written to frozen_inference_graph.uff $ ls -l *.uff -rw-rw-r-- 1 test test 18839555 12月 13 10:08 frozen_inference_graph.uff $
⑤编辑nvinfer_custom_impl 然后编辑nvinfer_custom_impl。 将“ sources / objectDetector_SSD / nvdsinfer_custom_impl_ssd / nvdsparsebbox_ssd.cpp”的第52行上的“ NUM_CLASSES_SSD = 91;”重写为“ NUM_CLASSES_SSD = 3;”。
⑥建立nvinfer_custom_impl 重写后,构建并重新创建“ libnvdsinfer_custom_impl_ssd.so”,并将其复制到uff文件所在的目录中。
$ cd sources/objectDetector_SSD/ $ export CUDA_VER=10.2 $ make -C nvdsinfer_custom_impl_ssd make: Entering directory '/home/test/myModel/sources/objectDetector_SSD/nvdsinfer_custom_impl_ssd' g++ -o libnvdsinfer_custom_impl_ssd.so nvdsparsebbox_ssd.cpp nvdsiplugin_ssd.cpp -Wall -Werror -std=c++11 -shared -fPIC -Wno-error=deprecated-declarations -I../../includes -I/usr/local/cuda-10.2/include -Wl,--start-group -lnvinfer -lnvparsers -L/usr/local/cuda-10.2/lib64 -lcudart -lcublas -Wl,--end-group make: Leaving directory '/home/test/myModel/sources/objectDetector_SSD/nvdsinfer_custom_impl_ssd' $ ls -l nvdsinfer_custom_impl_ssd/ total 128 -rw-r--r-- 1 test test 1865 12月 13 10:02 Makefile -rwxrwxr-x 1 test test 97888 12月 13 10:15 libnvdsinfer_custom_impl_ssd.so -rw-r--r-- 1 test test 11515 12月 13 10:02 nvdsiplugin_ssd.cpp -rw-r--r-- 1 test test 4669 12月 13 10:14 nvdsparsebbox_ssd.cpp $ cp nvdsinfer_custom_impl_ssd/libnvdsinfer_custom_impl_ssd.so ../../ $ cd ../../
⑦创建标签文件 接下来,在与uff文件相同的目录中创建标签文件“ mylabels.txt”。 看起来如下。
⑧编辑nvinfer设置文件 由于标签文件的名称已更改,因此请在“ config_infer.txt”中更改标签文件的名称。 另外,更改输入视频的文件名。
⑨编辑应用程序设置文件 要更改为应用设置文件“ app_config.txt”,您只需更改要输入的视频的文件名。
#uri=file:///opt/nvidia/deepstream/deepstream-5.0/samples/streams/sample_1080p_h264.mp4 uri=file://./input.mp4
⑩确认所需文件 通过以上工作,确认准备了以下6个文件。
11.运行DeepStream应用 现在,让我们使用原始模型执行对象检测,这是本系列的最终目的! 让我们如下启动DeepStream应用程序! !
以下是目标检测的视频。 已正确检测到“向日葵”! !! 我印象深刻

- 关于NVIDIA Jetson AGX Orin模组,这些信息很重要
- 对计算能力9.0+GPU卡特性的探索
- 在自动光学检测(AOI)领域中推广Jetson Xavier 方案到底解决哪些痛点?
- 关于Jetson AGX Orin产品你不知道的关键点都在这里
- 揭秘 Jetson 上的统一内存
- NVIDIA Jetson 软件: 将 NVIDIA 加速技术带到边缘
- 新一代Jetson NANO开发套件(B01)开箱
- 从Tensorflow生成TensorRT引擎的方法
- 实战教程:利用NVIDIA TensorRT优化一个推荐系统
- NVIDIA机器人开发工具包ISAAC实战(英文)
- 如何搭建一个NVIDIA JetBot小车(英文)
- Jetson TX2进行摄像头驱动的开发