Jetson Nano 2GB 系列文章(22): “Hello AI World” 图像分类代码

前一篇文章已经带着大家使用 Hello AI World 项目的 imagenet 指令进行了深度学习图像分类的推理识别实验,但这些演示与测试只是个学习的过程,最终的目的还是要能用起这个项目的资源,为自己开发合适的应用代码。因此本文就延续上一篇文章来向大家介绍 “Hello AI World” 图像分类代码。

选择使用 ~/jetson-inference/python/examples下面的 my-recognition.py 这只代码,其“输入源”的部分选择以下函数:

WeChat Image_20210530124521.jpg

这部分其实造成了一些不便之处,因为 “loadImage()” 一次只能读取一张图像,大大降低了这只代码的实用性,因此我们建议选择用 /usr/local/bin/imagenet.py 这只代码,它能够广泛接受更多样化的输入源,完整地实现 imagenet 的所有功能。

以下就是 /usr/local/bin/imagenet.py 的完整代码,请不要被这 33 行代码吓到,真正与图像分类推理计算的部分也只有 4 行,我们在下面会详细说明。

1.png

2.png

3.png

如果将代码区分为以下 4 部分,就能很容易理解:

参数解析:5~19 行,请参考前面文章关于参数解析的部分,可忽略
输入输出:21、22、25、29、30 等 5 行,与videoSource、videoOutput 有关
文字叠加:23 与 28 行是为了将显示结果,用文字叠加到图像上
图像分类:20、26、27行,以及30行的 net.GetNetworkFPS() 部分

现在我们主要解说与“图像分类”有关的这 4 行代码:

  1. 第20行: net = jetson.inference.imageNet(opt.network, sys.argv),用 jetson.inference 深度学习模块的 imageNet() 图像分类函数,来建立 net 这个对象,现在这个 net 对象就具备了“图像分类”的属性。
  2. 第26行:class_id, confidence = net.Classify(img) img是从25行的input.Capture() 获取的一帧图像,将 img 传入 net.Classify 进行图像分类的检测,将“置信度最高”的分类编号传回给 class_id 变量、将置信度值传回给 confidence 变量。

这里要说明的,在执行 Classify(img) 的过程,可能会检测出非常多的“可能性”,但最终回传“置信度最高”一个类别。当我们后面执行检测时,会看到终端上打印出类似下图的信息:

4.png

在本帧图像进行分类识别时,会出现 8 种可能性,但最后回传置信度最高的分类编号(0951)给 class_id、置信度(0.276245)给 confidence。

下面比对一下检测结果的输出图像,如下图:

5.jpg

这里可以确认,回传的值只有一组,就是“置信度最高”的,不管这个置信度数值有多低。

虽然在上面的终端中已经显示出了这个类别编号的名称,但实际上这个函数回传的值就只有两个,因此我们自己还需要用下一行的代码,来找出类别编号所对应的名称与描述。

  1. 第27行:class_desc = net.GetClassDesc(class_id)

这行的目的,是用类别编号 class_id 去找到对应的类别名称与描述,语法非常直观,不多做解释。重要的是这个类别名称与描述的内容,存放在哪个文件里面。

从上一篇文章中,知道这个代码预设使用的网络模型为 GOOGLENET,使用的数据集是 ImageNet 的 1000 分类数据集,这个在系统里面对应的类别名称与描述文件,在~/jetson-inference/data/networks/ilsvrc12_synset_words.txt 里面,用文字编辑器打开后,看看第 951 行(如下图)是什么内容?

6.jpg

很不幸的,951 行出现的是 “orange”,而 “lemon” 出现在第 952 行,这个差异主要是因为类别编号是从 “0” 开始,而编辑器的行数是从 “1” 开始,所以中间会有这样的差距,现在知道之后就很简单了。

  1. 第30行:net.GetNetworkFPS()

这部分显示识别性能,其实是对图像分类的应用,是无关紧要的,不过这个项目其实也是很神奇的,过去我们自己用 OpenCV 撰写性能标识的代码,其实还挺繁琐的,但是在 jetson-inference 项目中,无论是图像分类,还是后面要说明的物件识别、语义分割等应用,用这个 GetNetworkFPS() 函数就轻松得到计算的性能,真是不能再方便了!

看完之后就会发现,其实整个代码中的关键,就是在一开始用 imageNet() 函数去建立图像分类的对象,然后将读入的图像传给 Classify() 函数进行分类的推理计算,这两个步骤几乎就完成了 90% 的工作了。

相信有了这样的解说会让您更清楚该如何使用 jetson.inference 这个深度学习的模块,去开发您自己的图像分类应用。

WeChat Image_20210507101211.jpg

9 阅读 295
推荐阅读
0 条评论
关注数
2678
内容数
32
深耕嵌入式 AI 计算,助力自主机器研发
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
Arm中国学堂公众号
关注Arm中国学堂
实时获取免费 Arm 教学资源信息
Arm中国招聘公众号
关注Arm中国招聘
实时获取 Arm 中国职位信息