1 数据预处理概述
1.1 典型使用场景
受网络结构和训练方式等因素的影响,绝大多数神经网络模型对输入数据都有格式上的限制。在计算视觉领域,这个限制大多体现在图像的尺寸、色域、归一化参数等。如果源图或视频的尺寸、格式等与网络模型的要求不—致时,我们需要将源图或视频处理成符合模型要求的图或视频。
1.2 多种处理方式
CANN提供了两套专门用于数据预处理的方式:AIPP和DVPP。AIPP、DVPP可以分开独立使用,也可以组合使用。组合使用场景下,一般先使用DVPP对图片/视频进行解码、抠图、缩放等基本处理,但由于DVPP硬件上的约束,DVPP处理后的图片格式、分辨率有可能不满足模型的要求,因此还需要再经过AIPP进一步做色域转换、抠图、填充等处理。
1.2.1 AIPP
AIPP (Artificial Intelligence Pre-Processing)人工智能预处理,在Al Core上完成数据预处理。主要功能包括改变图像尺寸(抠图、填充等)、色域转换(转换图像格式)﹒减均值/乘系数(改变图像像素等。
AIPP区分为静态AIPP和动态AIPP。您只能选择静态AIPP或动态AIPP方式来处理图片,不能同时配置静态AIPP和动态AIPP两种方式。
- 静态AIPP:模型转换时设置AIPP模式为静态,同时设置AIPP参数,模型生成后,AIPP参数值被保存在线模型(*.om)中,每次模型推理过程采用固定的AIPP预处理参数(无法修改)。如果使用静态AIPP方式。多Batch情兄下共用同一份AIPP参数。
- 动态AIPP:模型转换时仅设置AIPP模式为动态,每次模型推理前,根据需求,在执行模型前设置动态AIPP参数值,然后在模型执行时可使用不同的AIPP参数。如果使用动态AIPP方式,多Batch可使用不同的AIPP参数。
1.2.2 DVPP
DVPP(Digital Video Pre-Processing)是昇腾AI处理器内置的图像处理单元,通过AscendCL媒体数据处理接口提供强大的媒体处理硬加速能力,主要功能包括缩放、抠图、格式转换、图片编解码、视频编解码等。
1.3 在开发应用中的位置
示例场景说明:输入一张JPEG的图片文件(源图格式为YUV420),经过JPEGD+VPC后,输出一张YUV420SP格式的图片,再通过AIPP将图片格式转换为RGB,同时进行归一化配置,最后将图片送给模型进行推理。
2 DVPP接口概述
2.1 关键功能的性能规格
2.2 不同功能模块支持的格式转换
昇腾Al处理器内置图像处理单元DVPP (Digital Video Pre-Processor),提供强大的媒体处理硬加速能力。同时,异构计算架构CANN提供了使用图像处理硬件算力的入口:AscendCL接口,开发者可通过接口来进行图像处理,以便利用昇腾AI处理器的算力。
2.3 接口对齐
由于硬件对图片宽、高对齐的要求,DVPP数据预处理中存在宽stride和高stride两个概念,分别用于表示对齐后的宽、对齐后的高,DVPP中的不同功能,对不同格式的输入或输出图片的宽、高对齐要求也不同,在使用DVPP中的多个功能串接(例如JPEGD+vPC)时,需特别注意接口文档中的对齐说明。
2.4 AscendCL的同步VS异步
在AscendCL中当提及“同步&异步”的时候,都是站在调用者.执行者的角度来看的。
- 同步:当前线程发起一个方法调用。然后阻塞在调用点等待被调用方法执行完毕返回,再继续向下走。
- 异步:调用者向执行者下发一个任务之后,不等待任务执行完,而是立即返回往下走,暂且不管这个任务是否执行完毕。
aclError aclrtSynchronizeStream(aclrtStream stream)
2.5 DVPP 接口
2.5.1 内存申请与释放
acldvppMalloc
- 函数功能:
该接口主要用于分配内存给Device侧媒体数据处理时使用,申请的大页内存满足数据处理的要求(例如,内存首地址128对齐),同步接口。 - 约束说明:
- 频繁调用acldvppMalloc及acldvppFree接口操作内存,会损耗性能,建议用户提前做内存预先分配或二次管理,避免频繁申请/释放内存。〉
- 调用该接口申请内存会对输入的size向上对齐成32整数倍后再加32字节申请。如用户使用该接口申请大块内存并自行管理内存,需管理n张大小为len字节图片的内存,应按照n*(ALIGN_UP[len]+32字节)大小管理,每张图片的内存地址按(ALIGN_UP[len]+32字节)为单位偏移。
ALIGN_UP表示向上按32字节对齐:((len-1)/32+1)*32。 - 调用该接口申请大页内存失败,仅表示系统内的大页内存不够;调用该接口申请内存后,必须使用acldvppFree接口释放内存。
- 函数原型:
aclError acldvppMalloc(void **devPtr, size_t size)
acldvppFree
- 函数原型
aclError acldvppFree (void *devPtr)
2.5.2 通道创建与释放
acldvppCreateChannelDes
- 函数功能:
创建acldvppChannelDesc类型的数据,表示创建图片数据处理通道时的通道描述信息。同步接口。
- 函数原型:
acldvppChannelDesc *acldvppCreateChannelDesc)
- 返回值说明:
返回acldvppChannelDesc类型,表示成功。
返回null,表示失败。
acldvppDestroyChannelDesc
- 函数功能:
销毁acldvppChannelDesc类型的数据,只能销毁通过acldvppCreateChannelDesc接口创建的acldvppChannelDesc类型。该接口为同步接口。
必须在调用acldvppDestroyChannel接口销毁channel通道之后再调用acldvppDestroyChannelDesc接口释放acld
数据,否则报错。
- 函数原型:
aclError acldvppDestroyChannelDesc(acldvppChannelDesc*channelDesc)
acldvppCreateChannel
- 函数功能:创建图片数据处理的通道,同一个通道可以重复使用,销毁后不再可用,同步接口。
- 约束说明:
通道为非线程安全,即不同线程要求创建不同的通道;同一个通道不能同时在多个Stream中并发使用。
- 函数原型:
aclError acldvppCreateChannel(acldvppChannelDesc *channelDesc)
acldvppDestroyChannel
·函数原型:
aclError acldvppDestroyChannel(acldvppChannelDesc *channelDesc)
- 约束说明:
如果在调用该接口销毁通道前,已调用acldvppDestroyChannelDesc接口销毁了通道描述信息,那么在调用该接口销毁通道时会报错。
2.5.3 图片描述信息创建与销毁
acldvppCreatePicDesc
- 函数功能:
创建图片描述信息。同步接口。
- 函数原型:
acldvppPicDesc *acldvppCreatePicDesc)
- 返回值说明:
返回acldvppPicDesc类型,表示成功。
返回null,表示失败。
acldvppDestroyPicDesc
- 函数功能:
销毁图片描述信息,只能销毁通过acldvppCreatePicDesc接口创建的图片描述信息。
- 函数原型:
aclError acldvppDestroyPicDesc(acldvppPicDesc*picDesc)
acldvppDestroyChannel
- 函数原型:
aclError acldvppDestroyChannel(acldvppChannelDesc*channelDesc)
2.5.4 图片描述参数设置
acldvppSetPicDesc系列接口
- 函数功能:设置图片描述参数,同步接口。
- 函数原型:
aclError acldvppSetPicDescData(acldvppPicDesc *picDesc, void *dataDev);
aclError acldvppSetPicDescSize(acldvppPicDesc*picDesc, uint32_t size);
aclError acldvppSetPicDescFormat(acldvppPicDesc *picDesc, acldvppPixelFormat format);
aclError acldvppSetPicDescWidth(acldvppPicDesc *picDesc, uint32_t width);
aclError acldvppSetPicDescHeight(acldvppPicDesc *picDesc, uint32_t height);
aclError acldvppSetPicDescWidthStride(acldvppPicDesc *picDesc, uint32_t widthStride);
aclError acldvppSetPicDescHeightStride(acldvppPicDesc *picDesc, uint32_t heightStride);
aclError acldvppSetPicDescRetCode(acldvppPicDesc *picDesc,uint32_t retCode)
- 返回值说明:
返回0表示成功,返回其它值表示失败。
3 JPEGD图片解码
3.1 功能
JPEGD (JPEG Decoder)实现jpg、 jpeg、.JPG、.JPEG图片文件的解码。针对不同的源图编码格式,解码后,输出如下格式的图片:
- jpeg(YUV444SP) -> YUV444SP、YVU444 SP、YUV420SP NV12 、YUV420SP NV21。
- jpeg(YUV422SP) -> YVU422SP 、 YUV422SP、 YUV420SP NV12、 YUV420SP NV21。
- jpeg(YUV420SP)-> YUV420SP NV12、YUV420SP NV21。
- jpeg(YUV400) -> YUV420SP,UV数据采用0 x 80填充。
- jpeg(YUV440)-> YVU440SP.YUV440SP、 YUV420SP NV12、YUV420SP NV21。
3.2 约束
- 关于输入图片的约束
最大分辨率:81928192,最小分辨率:3232;只支持Huffman编码,码流的colorspace为YUV,码流的subsample为444/422/420/400;不支持算术编码;不支持渐进JPEC格式;不支持JPEG2000格式; - 关于输出图片的宽高对齐要求
输出图片的widthStride (对齐后的宽度),对齐到128;输出图片的heightStride(对齐后的高度),对齐到16. - 关于输出内存大小
输出内存大小与图片数据的格式相关,计算公式如下:
YUV420SP: widthStrideheightStride3/2
YUV422SP: widthStrideheightStride2YUV444SP: widthStrideheightStride3 - 关于硬件约束
最多支持4张Huffman表,其中包括2张DC(直流)表和2张AC(交流)表;最多支持3张量化表;只支持8bit采样精度;只支持对顺序式编码的图片进行解码;只支持基于DCT (Discrete Cosine Transform)变换的JPEC格式解码;
只支持一个Sos (Start of Scan)标志的图片解码。
-** 关于软件约束**
支持3个sOS标志的图片解码;
支持mcu (Minimum Coded Unit)数据不足的异常图片解码。
3.3 调用流程
3.4 接口
acldvppJpegDecodeAsync
- 函数功能:
解码.jpg…jpeg…JPG、.JPEG图片,异步接口。
- 函数原型:
aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, const void datauint32 t size, acldvppPicDescoutputDesc, aclrtStream stream)
acldvppJpegGetlmagelnfo
- 函数功能
从Host上存放JPEG图片数据的内存中读取JPEG图片的宽、高。同步接口。
- 函数原型
aclError acldvppJpegGetlmagelnfo(const void 'data,uint32 t size.uint32 t *width,uint32 t *height,int32 t *components)·参数说明:参数名
acldvppJpegPredictDecSize
- 函数功能
根据Host上存放JPEG图片数据的内存计算出JPEG图片解码后所需的输出内存的大小。同步接口。
- 函数原型
acError acldvpplpegPredictDecSize(const void data,uint32 t dataSize,acldvppPixelFormat outputPixelFormatuint32,tdecSize)
4 VPC视觉预处理
4.1 功能
- 抠图
从输入图片中抠出需要用的图片区域。 - 缩放
◆针对不同分辨率的图像,当前支持8K及非8K缩放。
◆可分为单图裁剪缩放((支持非压缩格式)、一图多框裁剪缩放(支持非压缩格式)。
◆其它缩放方式,如:原图缩放、等比例缩放(缩放前后图片的宽高比例相同)。 - 叠加
- 从输入图片中抠出来的图,对抠出的图进行缩放后,放在用户输出图片的指定区域,输出图片可以是空白图片(由用户申请的空输出内存产生的),也可以是已有图片(由用户申请输出内存后将已有图片读入输出内存),只有当输出图片是已有图片时,才表示叠加.
- 拼接,从输入图片中抠多张图片,对抠出的图进行缩放后,放到输出图片的指定区域。
- 格式转换,支持RGB格式、YUV格式之间的格式转换。
- 图像灰度化,将彩色图像转化为灰度图像。需注意,输入为灰度图像、输出只能为灰度图像。