CANN体验官第四期——Ascend 310P 推理应用开发体验(C&C++)随笔

活动介绍

CANN体验官第四期,是基于 Ascend 310P 进行推理应用开发体验,体验尝鲜 Ascend 310 → Ascend 310P 的应用迁移及Ascend 310P 的新特性:媒体数据处理V2版本接口!

注: Ascend 310P 应该就是Ascend 710,如果执行如下命令:

npu-smi info

可得

image.png

环境说明

  1. 华为官方提供了硬件和指导书,可以远程登录硬件使用,只是需要通过 VPN 登录,而 VPN 登录指导书和活动体验指引以及体验报告模板,可以到活动页面下载。
    关于 VPN 的登录,由于官方给的文档很详细,这里就不赘述了。远程登录推荐使用MobaXterm,非常好用!这里可能有的同学会更习惯 VS Code,不过使用 MobaXterm 亦可通过 VS Code 来编辑代码文件,没有错,是不是很棒,而且 MobaXterm 还提供了强大的代码文件比对功能,让你快速知道不同代码文件的差异,非常适合基于官方代码改进和完善的同学。

  2. CANN的toolkit是root用户安装的,运行在非root用户,需要先设置环境。以运行用户在任意目录下执行如下命令,打开.bashrc文件:

vi ~/.bashrc

在文件最后一行后面添加:

. /usr/local/Ascend/ascend-toolkit/set_env.sh  # 注意.和/之间有空格

执行命令保存文件并退出:

:wq!

最后记得执行命令使其立即生效:

source ~/.bashrc
  1. 配置环境变量
export DDK_PATH=/usr/local/Ascend/ascend-toolkit/latest/arm64-linux
export NPU_HOST_LIB=$DDK_PATH/acllib/lib64/stub
  1. 软硬件配置

image.png

活动体验

基础体验:体验 Ascend 310->Ascend 310P 的推理应用迁移

image.png

评分规则

image.png

我们可以看到官方的体验指引非常详细,而且给了参考案例,还贴心地给了提示。总的来说,这个体验还是比较简单的,主要是在于模型的转换,而官方也给了建议需将--soc_version 参数设置为 Ascend710 。剩下的就很简单了。

不过这里,我并没有选用官方推荐的案例,而是自选一个我认为更有意思的——基于Caffe ResNet-50网络实现图片分类(图片解码+抠图缩放+图片编码+同步推理)

这里案例主要是基于Caffe ResNet-50网络(单输入、单Batch)实现图片分类的功能。根据运行应用的入参,可实现以下功能:

  1. 将一张YUV420SP格式的图片编码为*.jpg格式的图片。
  2. 将两张*.jpg格式的解码成两张YUV420SP NV12格式的图片,缩放,再进行模型推理,分别得到两张图片的推理结果后,处理推理结果,输出最大置信度的类别标识以及top5置信度的总和。
  3. 将两张*.jpg格式的解码成两张YUV420SP NV12格式的图片,抠图,再进行模型推理,分别得到两张图片的推理结果后,处理推理结果,输出最大置信度的类别标识以及top5置信度的总和。
  4. 将两张*.jpg格式的解码成两张YUV420SP NV12格式的图片,抠图贴图,再进行模型推理,分别得到两张图片的推理结果后,处理推理结果,输出最大置信度的类别标识以及top5置信度的总和。
  5. 将YUV420SP NV12格式的图片(分辨率81928192)缩放,得到40004000。

实现的功能更全面。注意这里用于推理的模型文件是*.om 文件(适配昇腾AI处理器的离线模型),转换模型时,需配置色域转换参数,用于将 YUV420SP 格式的图片转换为RGB 格式的图片,才能符合模型的输入要求。

按照指引,体验还是很流畅的,顺利通过了编译。

image.png

并可以成功运行。

image.png

这里我只展示了第一个功能,有兴趣的同学可以试试其他功能,多体验一下。

进阶体验一:体验 Ascend 310P 缩放功能

image.png

评分规则

image.png

我们可以看到,我们要实现的功能是使用媒体数据处理 V2 将一个图片做缩放,主要部分是对一张 1920 * 1080 分辨率、YUV420SP NV12 格式的图片(官方已提供)缩放为 1280 * 720 分辨率、YUV420SP NV12 格式的图片。

这里官方很好的给出了参考样例,我选择基于官方给出的参考样例进行改造,下面按照评分规则,逐项介绍。在此之前,先来看一下我们要处理的官方给出的 .yuv 原图,.yuv 格式无法直接查看,一般可以通过 ffmpeg 直接在服务器上查看,但服务器并没有安装,而由于没有 root 权限,我也无法自行安装,所以选择了下载到本地查看,这里介绍一个免费的查看工具 YUView,支持包括 Windows、Linux 和 Mac 主流平台,使用起来非常方便,而且提供了安装包,直接下载安装即可。

这里需要说明一下,直接打开后可能无法查看,因为 YUV 文件需要设置如下三项:

image.png

关于 YUV Format,可能没有上图中的选项,这时我们按照如下操作,勾选相应选项即可。

image.png

image.png

注意这里的Chroma Subsampling一定选择 420,因为我们这里所采用的格式都是 YUV420SP NV12 ,这一点要注意,如果遇到不是该格式的情况,请手动选择该格式,以便能正常显示。

下面我们来看看,来自官方的原始图片 dvpp_vpc_1920x1080_nv12.yuv,通过YUView可看到:

image.png

这张图片我们后面会一直用到哦。

对于评分规则第一点,是让我们跑通所给参考样例,按照 README 操作还是比较容易的,顺利完成编译和运行。

image.png

image.png

最后得到 resize_out.yuv 图片,我们来看看:

image.png

第一点实现还是比较简单的,由易到难,循序渐进,下面来看看第二点的要求。第二点要求我们缩放后的分辨率为 1280 * 720,也就是在第一点的基础上,改输出分辨率,通过查看代码和所用 API 的参数设置,可以很快解决。

首先,我们可以找到主函数,可以看到先设置了相关参数,其中就有outWidthoutHeight,通过查找资料和分析,可以知道这是设置输出图像的分辨率,我们将其分别设置成我们想要的 1280 和 720 就行了,之后按照之前的流程编译运行就好了,还是比较简单的。运行结果为:

image.png

image.png

我们来看看效果:

image.png

搞定!

第三点是在第二点的基础上,进一步做图片格式的转换,要求从之前的 YUV420SP NV12 格式转换成 RGB888 格式,也就是输出格式变了,我们还是先返回,看看代码。首先,通过查看官方文档,我们对

hi_mpi_vpc_resize(chnId, &inputPic, &outputPic, fx, fy, interpolation, &taskID, -1)

这个接口有了基本了解,而通过主函数的参数设置,结合查阅文档,我们基本知道了参数的意义。

    // 参数结构体
    VpcAttr g_vpc_attribute;
    // 输入图像宽度
    g_vpc_attribute.width = 1920;
    // 输入图像高度
    g_vpc_attribute.height = 1080;
    // 输入图像格式
    g_vpc_attribute.format = 1;
    // 输出图像宽度
    g_vpc_attribute.outWidth = 1280;
    // 输出图像高度
    g_vpc_attribute.outHeight = 720;
    // 输出图像格式
    g_vpc_attribute.outFormat = 1;
    // x方向的缩放比例,用于当输出宽高设置为0时,启动等比例缩放功能,根据参数配置宽高
    g_vpc_attribute.fx = 0;
    // y方向的缩放比例,用于当输出宽高设置为0时,启动等比例缩放功能,根据参数配置宽高
    g_vpc_attribute.fy = 0;
    // 缩放算法。其中0:bilinear,1:nearest neighbor
    g_vpc_attribute.interpolation = 0;
    // 输入图像
    strcpy(g_vpc_attribute.inputFileName, "../data/dvpp_vpc_1920x1080_nv12.yuv");
    // 输出图像
    strcpy(g_vpc_attribute.outputFileName, "resize_output_dvpp_vpc_1280x720_nv12.yuv");

可以看到,我们可以设置输出图像格式,那就简单了,不过这个图像格式是直接用数字来指代,这一点很常用,比如在 OpenCV 中就很多参数是用数字来指代,那么指代关系怎么找呢?换句话说,我们想要的 RGB888 格式是哪个数字表示呢?这里说句题外话,我们根据上述代码中的 1 推断,1 应该直达的就是 YUV420SP NV12了,一会验证一下。通过查看文档,我们可以得到:

image.png

更全的在这里:

HI_PIXEL_FORMAT_YUV_400 = 0,            // YUV400 8bit
HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // YUV420SP NV12 8bit
HI_PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // YUV420SP NV21 8bit
HI_PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // YUV422SP NV12 8bit
HI_PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // YUV422SP NV21 8bit
HI_PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // YUV444SP NV12 8bit
HI_PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // YUV444SP NV21 8bit
HI_PIXEL_FORMAT_YUYV_PACKED_422 = 7,    // YUV422P YUYV 8bit
HI_PIXEL_FORMAT_UYVY_PACKED_422 = 8,    // YUV422P UYVY 8bit
HI_PIXEL_FORMAT_YVYU_PACKED_422 = 9,    // YUV422P YVYU 8bit
HI_PIXEL_FORMAT_VYUY_PACKED_422 = 10,   // YUV422P VYUY 8bit
HI_PIXEL_FORMAT_YUV_PACKED_444 = 11,    // YUV444P 8bit
HI_PIXEL_FORMAT_RGB_888 = 12,           // RGB888
HI_PIXEL_FORMAT_BGR_888 = 13,           // BGR888
HI_PIXEL_FORMAT_ARGB_8888 = 14,         // ARGB8888
HI_PIXEL_FORMAT_ABGR_8888 = 15,         // ABGR8888
HI_PIXEL_FORMAT_RGBA_8888 = 16,         // RGBA8888
HI_PIXEL_FORMAT_BGRA_8888 = 17,         // BGRA8888
HI_PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, // YUV440SP NV12 8bit
HI_PIXEL_FORMAT_YVU_SEMIPLANAR_440 = 1001, // YUV440SP NV21 8bit

看样子,我们想要的 RGB888 格式应该就是用 12 来指代了,顺便验证一下 1 应该就是 YUV420SP NV12 了,是 8 bit表示的。当然,这里除了用数字指代,我们还可以直接用HI_PIXEL_FORMAT_BGR_888,不过代码相应的要改一下,把之前的映射去掉。这一点就随意了,都可以。

对了,输出文件那里也要改下,不能再叫.yuv了。

之后,就是编译和推理了,也很顺利。

image.png

image.png

最后因为输出不能直接查看,这里通过 Python 代码转化为 .bmp 格式查看。

image.png

好了,下面看看第四点,要求从中心区域抠出一个分辨率 600 * 800 的子图,也就是抠图了,这个还是要看文档和代码,好好啃文档吧。这里主要修改的是:

    // 裁剪图片的宽度。
    g_vpc_attribute.cropWidth = 600;
    // 裁剪图片的高度。
    g_vpc_attribute.cropHeight = 800;
    // 裁剪图片的左偏移。
    g_vpc_attribute.cropX = (g_vpc_attribute.width - g_vpc_attribute.outWidth) / 2;
    // 裁剪图片的上偏移。
    g_vpc_attribute.cropY = (g_vpc_attribute.height - g_vpc_attribute.outHeight) / 2;
    // 剪裁图片数量,硬件支持剪裁多张图片。
    g_vpc_attribute.multiCount = 1;

最后的结果为:

image.png

当然,啃文档还是挺无聊的,不过慢慢啃,慢慢理解,就有意思了,特别是时而的柳暗花明,会带给人意外的惊喜,果然,实战才是最好的老师啊。

进阶体验二:体验 Ascend 310P 的 JPEG 解码 + 缩放组合功能

image.png

评分规则

image.png

纸上得来终觉浅,绝知此事要躬行,这里就不详细展开了,说多了,都是探索的“喜悦”,讲多了也作用不大,还是要自己亲自动手做一遍,即使不成功,也能有不错的理解,结合文档和参考样例,多试试就好了。这里展示下结果:

对于第一点:

image.png

对于第二点:

image.png

对于第三点:

image.png

可以看到最下方有些绿边,应该是在联合使用 JPEG 图片解码、图片缩放处理后的输出图片,由于图片宽、高的对齐约束所致。如果后续用于推理,可能会影响最终进度,可以通过“抠图”或其他方法解决,更多详情可参考 JPEGD + VPC + 模型推理(含AIPP)串联使用时的精度提升建议

这里要说一下,在昇腾710 AI处理器上,JPEGD + VPC串联使用时,由于 JPEGD解码后的输出图片的宽stride高stride有6416对齐的约束,因此解码后的输出图片的宽、高有一些补边的无效数据,所以 VPC 在处理图片前,应首先对 JPEGD 对齐后的输出图片进行原分辨率裁剪(可以考虑进阶体验一中的抠图,抠出原分辨率大小的图,原则上方法很多,大家可以考虑下其他的方法),目的是去除无效数据对图像精度的影响。

好了,到此,基本就告一段落了,有机会再来更新!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值