嘿!您似乎在 United States,您想使用我们的 English 网站吗?
Switch to English site
Skip to main content

深入使用NVIDIA Jetson Inference机器学习项目 - 对象辨识、语意分割以及训练自己的对象辨识模型

作者

张嘉钧

难度

普通

材料表

1.     Jetson Nano

2.     Webcam

对象辨识Objected Detection

对象辨识与图片分类的最大差别就在于会提供「坐标信息」,并且通常会用于「多个对象」上面;因此训练的时候就不是提供一个照片跟标签,而是提供照片、卷标以及坐标信息等其他信息 ( Xmin、Xmax、Ymin、Ymax )。

0142_c6dd7007edd182c693b561c8e3fb6e0c84e69c39.png

 

执行 detectnet

由于三个计算机视觉的范例执行方法都雷同,这部分就不多做解释

$ cd build/aarch64/bin
$ ./detectnet.py ./images/airplane_1.jpg ./images/test/airplane_1.jpg

推论完会将输出的信息覆写在图片上,与图片分类不同的地方在于因为objected detection有提供坐标信息,所以我们可以在inference的图片上看到坐标框出来的内容,并且也有辨识的结果:

0236_4f0c34bb4a42396b60cf459805a874f38798f644.jpg

此外终端机的内容也提供相当多的信息,辨识到几个对象,每个对象的开头会是 <detectNet.Detection object>,接下来的ClassID就是在标签当中编号第几个,Confidence则是信心指数,接着就是坐标的信息。

0337_f804f7ab834a93e8c6aef96b3dd2fd36267f2325.png

如果要使用USB网络摄影机运行实时影像的话则是使用:

$ ./detectnet.py /dev/video0

 

可以辨识哪些种类?

Jetson-Inference在对象辨识的部分提供了不同种的神经网络模型,同时也有不同的数据集,接下会稍微介绍一下各神经网络模型可以辨识的类别。

可以使用哪些神经网络模型?

我们默认使用的神经网络模型是用ssd-mobilenet-v2,而所有神经网络的信息如下

 Model

CLI argument

NetworkType enum

Object classes

SSD-Mobilenet-v1

ssd-mobilenet-v1

SSD_MOBILENET_V1

91 (COCO classes)

SSD-Mobilenet-v2

ssd-mobilenet-v2

SSD_MOBILENET_V2

91 (COCO classes)

SSD-Inception-v2

ssd-inception-v2

SSD_INCEPTION_V2

91 (COCO classes)

DetectNet-COCO-Dog

coco-dog

COCO_DOG

dogs

DetectNet-COCO-Bottle

coco-bottle

COCO_BOTTLE

bottles

DetectNet-COCO-Chair

coco-chair

COCO_CHAIR

chairs

DetectNet-COCO-Airplane

coco-airplane

COCO_AIRPLANE

airplanes

ped-100

pednet

PEDNET

pedestrians

multiped-500

multiped

PEDNET_MULTI

pedestrians, luggage

facenet-120

facenet

FACENET

faces

在最后一个字段是他所使用的数据集,从数据集可以看出这个神经网络模型可以辨识什么样的资料,第一个coco dataset就是日常所见的91个类别,像是人、计算机、水果、食物类的都有,而接下来的神经网络使用的类别,感觉是从COCO当中取出特定类别;官方提供的ped是pedestrians只有行人的意思,multiped则包含luggage (行李),dacenet则是只有脸。

该如何使用其他神经网络模型?

三种计算机视觉任务都可以使用 --network来使用其他模型:

$ ./detectnet.py --network=pednet ./images/peds_1.jpg ./images/test/peds_1.jpg

这边我使用的是peds_1.jpg,照片包含一个人跟一台车,如果使用默认的神经网络模型的话 (SSD_MOBILENET_V2) 车子将会被辨识到;若使用pednet的话,由于只辨识行人所以车子就不会被匡列进去。

SSD-Mobilenet-v2:

0433_1d22a68cc3e75730442754c2841d68a9e9af09a6.jpg

ped-100:

0528_7c287d86c0eda478a2796ac820f10df07e98ff1b.jpg

语意分割Image Segmentation

语意分割、语意分析,在三种计算机视觉的任务当中算是最难的一个,因为它需要把所有的像素(pixel)都进行分类;图片分类只需要在图片中辨识到对应对象就好;对象辨识需要将图片每个对象辨识、并框出位置;语意分割则是把每个像素都进行辨识,最后可以框出该对象的轮廓,因为每个像素都被进行分类了!

常常用于无人机的环境了解,毕竟这个比对象辨识还要更细部,通常可以获得更多信息;常见的AI去背景,有些也是用类似的技术。

执行 segnet

由于三个计算机视觉的范例执行方法都雷同,所以我就不多做解释,在这边我们使用的是segnet.py。

$ cd build/aarch64/bin
$ ./segnet.py ./images/horse_0.jpg ./images/test/horse_0.jpg

推论完会将输出的信息一样会覆写在图片上,这边会提供给你一张含有分割色块的原图,并一个则是单纯色块能更清楚的了解语意:

0627_e7b11875f7b85b9263e942d11672ffa513ea5c2e.jpg

 

可以分割哪些对象?

可以注意到这里用其不太一样,也没有提到神经网络模型,因为我们使用的都是fcn-resnet18这个模型,差别只在于数据集而已,所以我们稍后会针对数据集介绍一下,这里我们默认使用的神经网络模型是用PascalVOC,而所有的信息如下

 Dataset

Resolution

CLI Argument

Accuracy

Cityscapes

512x256

fcn-resnet18-cityscapes-512x256

83.3%

Cityscapes

1024x512

fcn-resnet18-cityscapes-1024x512

87.3%

Cityscapes

2048x1024

fcn-resnet18-cityscapes-2048x1024

89.6%

DeepScene

576x320

fcn-resnet18-deepscene-576x320

96.4%

DeepScene

864x480

fcn-resnet18-deepscene-864x480

96.9%

Multi-Human

512x320

fcn-resnet18-mhp-512x320

86.5%

Multi-Human

640x360

fcn-resnet18-mhp-512x320

87.1%

Pascal VOC

320x320

fcn-resnet18-voc-320x320

85.9%

Pascal VOC

512x320

fcn-resnet18-voc-512x320

88.5%

SUN RGB-D

512x400

fcn-resnet18-sun-512x400

64.3%

 

Pascal VOC Dataset ( default )

这个数据集总共可以辨识19个对象,在该数据集的介绍当中区分为四个类别Vehicles、Household、Animals、Person又各分细项:

Vehicles 汽车

Car、Bus、Bicycle、Motorbike、Boat、Train

Household 家庭

Chair、Sofa、Dining table、TV/monitor、Bottle、Potted plant

Animals 动物

Cat、Dog、Cow、Horse、Sheep、Bird

Person 人

Person

 

Cityscapes

这个也是能辨识19个类别,他是在不同的程序去搜集「街景」,所以日常在街景可以看到的东西,都被收纳在这个数据集当中。

DeepScene

这个数据集则比较小一点,能辨识的类别也只有6个,分别为 无效(void),道路(trail),草丛(grass),植被(vegetation),天空(sky)和障碍物(obstacle)。

SUN RGB

这个数据集主要用于室内设计上面,提供了10,335张不同的室内图片,总共的类别有墙、地板、门、窗户、桌子、台灯等21个类别。

Multi-Human

这个部分也是提供了21个类别,但主要着重在人体上的语意分割,像是 头发、T-shirt、袜子、脚、眼镜等等的。

如何查看神经网络模型辨识的卷标

我们可以在工作的文件夹发现除了有Images的文件夹也有Network文件夹,这个Network存放的是所有下载的神经网络模型,我们可以透过进入那些神经网络的文件夹寻找classes.txt来获取它所有的标签类别哦!这边以Pascal为例:

$ cd /jetson-inference/data/networks/FCN-ResNet18-Pascal-VOC-320x320
$ ls -la

0737_bd6ccb6debb3bc17ba6d05114edbc4009fc5a666.png

接着我们可以直接使用cat来查看内容,这边我加上了 -n 让内容可以显示行号,进而知道我们的标签总共有多少个哦!

$ cat -n classes.txt

0832_2026a65374d8e82be237617d475c0aa9b2cb4cdf.png

这样你就知道怎么样去查到一个神经网络模型到底可以辨识哪一些类别了!

如何使用其他神经网络模型?

使用其他神经网络模型的方法也是一样的,使用--network即可。

$ ./segnet.py --network= fcn-resnet18-mhp-512x320 ./images/peds_1.jpg ./images/test/peds_1.jpg

 

程序解析

在这里我们将会解析Jetson Inference的imagenet.py、detectnet.py、segnet.py,这将能帮助到想要使用Jetson Inference来开发的使用者,因为Jetson Infernece已经提供训练好的模型,并且已经转成可以用TensorRT加速的onnx了 ( 这部分下一篇会再介绍 ),所以使用Jetson Inference开发真的是快速又方便;可以注意到我上述的介绍式写 .py代表我们接下来会介绍的都是Python语言,而PyTorch底层是C++所以Inference也有提供C++的程序。

Imagenet.py

1、首先一定要导入它提供的API:

#!/usr/bin/python3

import jetson.inference	
import jetson.utils

2、接着按照官方的范例会导入外部变量的函式库 (argparse) 以及撰写了可以从外部导入「档案」、「网络」的程序:

import argparse

# parse the command line
parser = argparse.ArgumentParser()
parser.add_argument("filename", type=str, help="filename of the image to process")
parser.add_argument("--network", type=str, default="googlenet", help="model to use, can be:  googlenet, resnet-18, ect.")
args = parser.parse_args()

3.导入图片(输入数据)、神经网络模型:

# load an image (into shared CPU/GPU memory)
img = jetson.utils.loadImage(args.filename)

# load the recognition network
net = jetson.inference.imageNet(args.network)

4、进行分类,会取得两个数值分别是类别的编号以及该信心指数:

# classify the image
class_idx, confidence = net.Classify(img)

5、取得类别编号的内容并显示结果:

# find the object description
class_desc = net.GetClassDesc(class_idx)

# print out the result
print("image is recognized as '{:s}' (class #{:d}) with {:f}% confidence".format(class_desc, class_idx, confidence * 100))

 

Detectnet.py

1、首先一样导入函式库:

import jetson.inference
import jetson.utils

2、这边的范例使用的是影像串流,所以他会先撷取到摄影机对象,接着再用While循环不断撷取当前画面,来达到实时影像的功能:

net = jetson.inference.detectNet("ssd-mobilenet-v2", threshold=0.5)
camera = jetson.utils.videoSource("csi://0")      # '/dev/video0' for V4L2

while display.IsStreaming():

3、在循环当中,第一步要撷取当前影像,接着将影像丢进模型当中,这边会自动帮你做overlay的动作,也就是辨识完的结果会直接显示在图片上:

    img = camera.Capture()
    detections = net.Detect(img)

4、最后使用Render将图片覆写,使用SetStatus设定标题的内容:

    display.Render(img)
    display.SetStatus("Object Detection | Network {:.0f} FPS".format(net.GetNetworkFPS()))

使用Docker的请注意

使用Docker的同学,记得先新增一个文件夹、并且每次开启Docker的时候都要做mount的动作,当然也可以写进.sh当中,每次执行就不用再额外宣告。

1、新建要挂载的目录,并将程序改为执行文件:

$ cd ~/
$ mkdir my-recognition-python
$ cd my-recognition-python
$ touch my-recognition.py
$ chmod +x my-recognition.py

2、开启Docker的时候需要进行mount:

$ docker/run.sh --volume ~/my-recognition-python:/my-recognition-python   # mounted inside the container to /my-recognition-python

结论

到目前为止,一些基本的使用方式都已经带给各位了,也有教基本的程序代码使用,因为Jetson Inference的整合让整个AI应用变得相当简单,未来会在出一篇进阶版本的,会教导如何使用Open Image的数据集训练客制化的模型,也会教导如何搜集自己的数据,可以尽请期待哦!

CAVEDU Education is devoted into robotics education and maker movement since 2008, and is intensively active in teaching fundamental knowledge and skills. We had published many books for readers in all ages, topics including Deep Learning, edge computing, App Inventor, IoT and robotics. Please check CAVEDU's website for more information: http://www.cavedu.com, http://www.appinventor.tw