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

2023-11-23 19:40

本文主要是介绍CANN体验官第四期——Ascend 310P 推理应用开发体验(CC++)随笔,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

活动介绍

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 neighborg_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 对齐后的输出图片进行原分辨率裁剪(可以考虑进阶体验一中的抠图,抠出原分辨率大小的图,原则上方法很多,大家可以考虑下其他的方法),目的是去除无效数据对图像精度的影响。

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

这篇关于CANN体验官第四期——Ascend 310P 推理应用开发体验(CC++)随笔的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/420284

相关文章

基于Python开发电脑定时关机工具

《基于Python开发电脑定时关机工具》这篇文章主要为大家详细介绍了如何基于Python开发一个电脑定时关机工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 简介2. 运行效果3. 相关源码1. 简介这个程序就像一个“忠实的管家”,帮你按时关掉电脑,而且全程不需要你多做

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

将Python应用部署到生产环境的小技巧分享

《将Python应用部署到生产环境的小技巧分享》文章主要讲述了在将Python应用程序部署到生产环境之前,需要进行的准备工作和最佳实践,包括心态调整、代码审查、测试覆盖率提升、配置文件优化、日志记录完... 目录部署前夜:从开发到生产的心理准备与检查清单环境搭建:打造稳固的应用运行平台自动化流水线:让部署像

什么是 Linux Mint? 适合初学者体验的桌面操作系统

《什么是LinuxMint?适合初学者体验的桌面操作系统》今天带你全面了解LinuxMint,包括它的历史、功能、版本以及独特亮点,话不多说,马上开始吧... linux Mint 是一款基于 Ubuntu 和 Debian 的知名发行版,它的用户体验非常友好,深受广大 Linux 爱好者和日常用户的青睐,

Linux中Curl参数详解实践应用

《Linux中Curl参数详解实践应用》在现代网络开发和运维工作中,curl命令是一个不可或缺的工具,它是一个利用URL语法在命令行下工作的文件传输工具,支持多种协议,如HTTP、HTTPS、FTP等... 目录引言一、基础请求参数1. -X 或 --request2. -d 或 --data3. -H 或

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要