前面文章已经简单介绍NVIDIA VPI视觉开发接口的架构以及主要元素,组成这个高阶封装的易用接口(NVIDIA VPI初探(1):用NVIDIA VPI高阶封装接口,快速开发GPU视觉应用 ),本文重点在于提供更多图像处理的算法,让大家更加深刻体会到VPI的简便性。本文范例在NVIDIA Jeston AGX Xavier上进行,主要以功能实践为主,不做性能方面的比较。
正常使用Jetpack 4.5.1之后版本安装Jetson设备,就会连同VPI开发库一起安装好,不过samples部分可能需要手动安装,请检查/opt/nvidia/vpi下面是否有samples文件夹?如果没有的话,直接执行下面命令就可以安装:
$ sudo apt install libnvvpi1 vpi1-dev vpi1-samples vpi1-demos
现在就能在samples目录下看到有15个项目以及一个assets的数据目录。
一开始先挑两个最简单的算法合并在一起演示,可以节省一些重复的设定代码,这样就能更清楚看到VPI的简便。
下面代码是将Samples的01-convolue_2d与04-rescale合并的代码,并且直接指定输入与输出文件,全部都用CUDA这个后端进行计算:
import cv2, vpi # 这个顺序不能颠倒
import numpy as np
from PIL import Image
# 指定输入文件
IMG_INPUT1 = "/usr/src/tensorrt/data/resnet50/binoculars.jpeg"
IMG_INPUT4 = "/home/nvidia/Desktop/maskTest2.png"
# 设定使用的后端
backend = vpi.Backend.CUDA
# 为范例1定义一个简单的边缘检测的卷积核
kernel = [[ 1, 0, -1], [ 0, 0, 0], [-1, 0, 1]]
# 为范例4定义宽与高的缩放倍数
scale_w = 0.3
scael_h = 0.5
# 将第1个范例使用的图像,用vpi.image类读入图像,并转换成灰阶格式
input1 = vpi.asimage(np.asarray(Image.open(IMG_INPUT1)))
input1 = input1.convert(vpi.Format.U8, backend=backend)
# 将第4个范例使用的图像,用vpi.image类读入图像,并转换成NV12格式
input4 = vpi.asimage(np.asarray(Image.open(IMG_INPUT4)))
temp = input4.convert(vpi.Format.NV12_ER, backend=backend)
# 开始计算:
with backend:
#===== 01-convolve_2d
output1 = input1.convolution(kernel, border=vpi.Border.ZERO)
#===== 04-harris_corners
temp = temp.rescale((int(input4.width*scale_w), int(input4.height*scale_h)))
output4 = temp.convert(input4.format, backend=backend)
# 将结果写入文件:
Image.fromarray(output1.cpu()).save('01-convolve_2d.png')
Image.fromarray(output4.cpu()).save('04-scaled.png')
可以看到上面在处理卷积计算与缩放的计算,在VPI也就是一行代码的事情,其他部分主要都是在做格式转换的任务,其实也都是一行指令就完成很多任务了。
这个合并代码的用意,就是让大家能更清楚感受到VPI提供的高阶封装接口,能让开发者如此轻松就完成过去相对复杂的事情。现在来看看输出结果:
1
01-convolve_2d:透过卷积计算找出图像的边缘线条,左边是原图、右边是结果:
2
04-rescale:将图像执行任意比例缩放,下面是原图,左上角黄框内是缩放后结果:
3
如果觉得这些范例太过简单,请继续尝试02-stereo_disparity的Python实验,这里就不列出个别目录里main.py的代码内容,请自行开启。
VPI将最核心耗时的算法封装成一道简单指令。在02-stereo_disparity/main.py第92行“disparity = vpi.stereodisp(参数)”就是这样的用法,后面的工作再根据disparity结果去进行格式、颜色空间、置信图的转换。
现在就执行以下指令来进行实验:
$ cd /opt/nvidia/vpi1/samples/02-stereo_disparity
$ python3 main.py cuda ../assets/chair_stereo_left.png \
../assets/chair_stereo_right.png
下面是执行的输出结果:
4
接着再看看03-harris_corners/main.py第59行“corners,scores = input.harriscorners(sensitivity=0.01)”也是一样的状况,整个计算也是一道指令就完成,后面再根据corners去绘制“角点”的位置,并根据scores给定不同的颜色。
这里只推荐修改最后一行“cv2.circle(out_data, kpt, 5, color, -1)”的粗体参数,将半径分改为5以上的值,否则所画的圆点太小,不容易识别出效果。
我们挑选assets/fisheye下面的image-002.jpg作为输入,可以找到更多的“角点(corner)”。请执行以下指令来体验这个范例:
$ cd /opt/nvidia/vpi1/samples/03-harris_corners
$ python3 main.py cuda ../assets/fisheye/image-002.jpg
下面是执行的输出结果:
如何?这几个范例都是让大家体验到,VPI将一些常用算法封装成简单指令的形式,对开发人员来说是非常便利的,而且大幅度提高可阅读性。
这几个范例中都使用到OpenCV库,这就能证明VPI并不是要全面取代OpenCV,而是为计算机视觉的“算法”部分,提供更有效的调用方法,更快速地在NVIDIAGPU设备上开发出高效的应用。
近期活动: