本文作者:
转载自:
/swlh/nvidia-jetson-nano-custom-object-detection-from-scratch-using-tensorflow-and-opencv-113fe4dba134
本博客的目的是指导用户创建具有性能优化的自定义对象检测模型,以在NVidia Jetson Nano上使用。
文章目录:
所需材料
创建一个自定义数据集
预处理
打标
创建 TFRecords
CNN
训练
模型
Jetson Nano上安装树莓派摄像头
结论
所需材料:
TensorFlow
OpenCV的
Jupyter笔记本
Jetson Nano开发人员套件
树莓派V2摄像头
Python
选择标准
我们选择Python作为开发语言是因为它支持大量用于处理数据的库,并且因为它易于与TensorFlow集成。它也是一个功能强大的脚本工具,可帮助我们自动化繁琐的任务。此外,此博客中探讨的所有对象检测体系结构都提供了实用的Python脚本。
TensorFlow作为深度学习应用程序的知名框架,对于我们来说是一个不错的探索和学习的选择。它提供了很好的文档,并且可以在线获得许多示例。
根据我们在先前项目中的经验,OpenCV被证明是一个很好的图像处理库。它在本博客中描述的开发中非常有用,因为它有助于通过树莓派V2相机在Jetson Nano上进行图像检索和处理。
话虽这么说,让我们推出!
创建自定义数据集
我们需要执行的用于自定义对象检测的第一件事是创建我们自己的数据集。要训练的神经网络将需要在不同位置,不同条件,不同位置和不同背景下要检测的物体的几张图像。
例如,我们决定检测哥斯达黎加一些最受欢迎的啤酒,例如帝国啤酒,比尔森啤酒和波西米亚啤酒。快速浏览超市后,我们购买了六个不同品牌的啤酒,然后分别为它们拍摄了140张照片。以下是我们图像的一些示例:
既然我们有过多的图像(本例中为840个),我们需要准备它们以训练我们的自定义模型。目前,它们的分辨率太大,无法有效使用,因此我们选择将它们缩小为较小的分辨率。
请不要手动进行操作;您可以使用下面附带的代码缩小文件夹中的所有图像的尺寸。可以随意更改脚本中指定的高度和宽度,但请记住:图像越大,训练所需的计算量越大。
现在,我们需要根据图像所属的类别对图像进行分组。通过创建包含所有类别的“训练和测试”文件夹,我们可以走得更远。
贴标
随着图像的大小相应调整,现在我们需要对其进行标记。在此活动中,我们逐个图像地进行显示,并指出我们要检测的对象的坐标及其所属的标签。
我们使用了开源工具LabelImg来简化此过程。
您可以从https://tzutalin.github.io/labelImg/下载。
在该过程的最后,您应该使每个图像带有其相应的标签,以及一个带有对象位置的所有元数据的xml文件。
创建TFRecords
在为不同类别的图像标记完成后,下一步是将它们分为一组进行训练,而另一组进行测试。在这种情况下,我们将图像及其对应的.xml文件分离到不同的文件夹中。划分为80/20,这意味着80%的图像将进入Train文件夹,其余20%的图像将进入Test文件夹。
现在我们需要创建TFRecords!这些文件将包含训练神经网络的所有必需信息,包括图像。如果您想了解有关TFRecords的更多详细信息,可以自行搜索一下。
我们创建了一个脚本,为我们创建了TFRecords。要使用python脚本,您只需要进行两个更改:变量PATH_ *和函数class_text_to_int。该PATH_ *变量应指向数据集和输出文件(.record)的训练和测试文件夹。该class_text_to_int()函数的目的是为了对数据集的类转换成一个数字,所以你需要在标签相相加所有图像创建的标签。
CNN
现在,您可以使用任何所需的样式为所需的CNN创建模型。您甚至可以使用TensorFlow提供的一些模型配置,其中许多可用于对象检测:Tensor Flow CNN模型。
在我们的案例中,我们使用了2种不同的模型。首先,我们尝试了ssd_inception_v2_coco,然后尝试了ssdlite_mobilenet_v2_coco。它们表现出不同的性能和准确性。我们稍后将在此博客中讨论权衡问题。首先,让我们讨论如何在培训阶段配置所有内容。
我们建议创建一个新的培训文件夹。在其中,您将需要放置TFRecords,model.config(您从Tensor Flow CNN Models创建或下载的那个)和标签映射。
是的,我们还没有谈论标签图。但这很容易,只需使用以下格式创建一个新文件,其中包含标签名称和数字id。这应该映射在Python脚本中指定的ID以创建TFRecord。
现在,我们需要更改您选择的model.config上的某些字段:
首先,更改变量num_classes以满足所选数据集的正确数量的类。
另外,找到train_input_reader和eval_input_reader标记并更改输入路径。该路径应指向您创建的train.record和test.record文件。此外,label_map_path应该指向标签图的位置。
这些特定的更改是强制性的,但是我们还对模型进行了其他更改,以提高性能并为我们的方便定制模型,如下所述。
首先,我们将图像尺寸设置为固定的较低分辨率(360、270):
另外,我们将单个图像中可能的检测次数从1000减少到了1,从而简化了训练。
之后,我们还更改了fine_tune_checkpoint标记以指向您选择的模型:
训练
准备好配置文件后,就可以开始训练神经网络了!为此,您可以发出以下命令:
我们建议使用TensorBoard跟踪培训进度。
我们在配备第8代Intel i5且没有GPU的基本笔记本电脑上训练了我们的模型,大约花了20个小时才达到合理的总损失。
培训准备就绪后,您可以创建一个.pb文件,该文件将在Jetson Nano中用作输入,以将模型加载到Tensor Graph中。
训练期间不要喝啤酒。您稍后将需要它们。
模型
如前所述,我们尝试了两种不同的模型。第一个是SDD Inception V2。该模型建议在每个层上使用多个操作而不是仅一个,然后将结果连接起来。通常,在一个层上,我们选择进行固定大小的过滤器(1x1、3x3或5x5),最大池化层或其他操作。另一方面,在Inception模型中,我们将在单个层上使用所有这些模型。使用后者,可以获得更好的准确性分数,并且检测到所有不同啤酒品牌的准确性分数在85%至95%之间。为了达到这种精度,不必花足够的时间(相对)训练神经网络,大约需要12个小时。
使用的第二个型号是SSD Lite Mobilenet V2。创建此模型是为了在移动设备上运行;它将所有卷积拆分为不同的子库。最后,它完成的功能与传统卷积大致相同,但速度更快。对于SSD Lite Mobilenet V2,获得的精度在60%到85%之间。为了达到这种精度,有必要训练约20小时的神经网络。此外,我们决定将课程数量从2个减少到2个,以减少训练时间并简化模型。
您应该选择哪种型号?好吧,选择SDD Inception V2模型是很明显的,因为它表现出最好的性能。但是请记住,如果要在Jetson Nano上运行模型,则需要考虑几个因素。
与SDD Lite Mobilenet V2相比,SDD Inception V2需要更多的RAM才能工作。根据我们的经验,Jetson Nano甚至无法运行SDD Inception V2模型,因为在大多数情况下,它在内存用尽时崩溃。当可以运行该应用程序时,图像显示屏上的最佳性能约为0.9FPS。同时,SDD Lite Mobilenet V2的性能约为9FPS。因此,我们决定坚持使用SDD Lite Mobilenet V2体系结构,而不是SDD Inception V2。
配备Jetson Nano的树莓派V2相机
使用Jetson Nano Developer工具包将树莓派相机与Jeston Nano连接起来并不是什么大问题,该工具包已经安装了必要的驱动程序。因此,通过使用CSI-Camera GitHub存储库,我们可以轻松访问摄像机,因为NVidia的Jetson Nano支持MIPI和CSI摄像机。
将训练后的模型加载到TensorFlow Graph中后,我们一次从相机中检索了一帧,并将其输入到为其分配了Graph的Tensorflow Session中。预测结果(如果有)与包围检测到的对象的框一起叠加到要显示的帧中。
(本节中引用的代码可以在/memillopeloz/JetsonNano-RPICam上找到)
我们针对上述脚本cProfile运行了Python的profiler,以便可以更好地了解时间消耗。为了获得更强大且更具代表性的配置文件,我们将对象检测代码修改为在处理了固定数量的帧后自行停止,并在执行配置文件时将相机指向没有运动的区域;这样,我们可以获得几次运行的配置文件结果,这些运行结果真正反映了代码更改的影响。
借助Python的pstats提供的视觉帮助,接下来将给出初步结果。将结果缩小以显示前15个最耗时的功能。
有了结果,我们可以清楚地确定TensorFlow的Session是时间消耗的主要因素,因此我们研究了可以应用的任何可能的优化,很可能是通过参数进行的。我们偶然发现了tf.OptimizerOptions,它可能与Session的配置相关联,以便在构造Tensor Graph时应用它们。
在代码中使用tf.GraphOptions,tf.OptimizerOptions和tf.ConfigProto进行了优化,如下面的代码片段所示。
(有关优化选项的更多详细信息,请参见/tensorflow/tensorflow/blob/r1.8/tensorflow/core/protobuf/config.proto)
我们选择了优化L1,因为它执行常见的子表达式消除和常量折叠,目的是在某些循环张量操作上重用预先计算的结果。考虑到这一点,我们估计使用L1优化可以使整体执行时间至少缩短15%。通过分析优化的代码获得的结果如下所示。
这次我们选择显示较少的功能:
我们确实设法将执行时间从129.8秒减少到114.8秒,这总体上提高了约11.55%。它没有最初预期的那么高,但是确实提高了性能。恒定折叠优化功能可以用恒定的节点替换其张量可以预先确定的张量,这可能是所示改进背后的主要原因。
结论
创建我们自己的自定义对象检测神经网络非常有趣且充满挑战。我们必须考虑设置模型运行的硬件(Jetson Nano)的局限性,并相应地修改模型,以使性能最大化。
设置合适的环境对于顺利执行训练过程和目标检测本身至关重要。遇到的大多数问题是由于设置错误/不完整所致。
培训阶段需要大量的计算机资源,尤其是对于高度复杂的模型(例如Google的Inception或MobileNet)。此外,通过使用专用的高端设备,可以进一步减少培训时间,并提高准确性。
事实证明,MobileNet是资源受限的移动或嵌入式设备/模块的最有效架构。这主要是由于内存限制。
更多教程:
【技巧分享】如何在外网远程访问Jetson NANO桌面
【技巧分享】在Jetson Xavier NX/Jetson NANO开发套件上打开多个摄像头
[Jetson Nano]使用Nsight观察TensorFlow Lite应用程序的性能瓶颈
jetson nano opencv 打开 CSI摄像头_Nvidia Jetson Nano:使用Tensorflow和OpenCV从头开始自定义对象检测...