更新时间:2021-03-18 GMT+08:00
分享

数据预处理(图片解码+缩放)

基本原理

数据传输到Device后,经过数据预处理(解码、缩放)后,输出源图编码格式或YUV420 SP格式的图片,作为模型推理的输入。

  • 解码
    • 针对不同的源图编码格式,解码后,输出如下格式的图片:
      • jpeg(YUV444SP) -> YUV444SP V在前U在后 、YUV420 SP V在前U在后、YUV420SP U在前V在后。
      • jpeg(YUV422SP) -> YUV422SP V在前U在后、YUV420SP V在前U在后、YUV420SP U在前V在后。
      • jpeg(YUV420SP) -> YUV420SP V在前U在后、YUV420SP U在前V在后。
      • jpeg(YUV400) -> YUV420SP,UV数据采用0 x 80填充。
    • 解码对输出图片的宽高有对齐要求:宽128对齐、高16对齐。
    • 解码后输出图片内存的计算公式:
      • YUV420SP:对齐后的宽*对齐后的高*3/2
      • YUV422SP:对齐后的宽*对齐后的高*2
      • YUV444SP:对齐后的宽*对齐后的高*3
  • 缩放
    • 缩放对图片的宽、高有对齐要求(宽16对齐、高2对齐)。
    • 缩放后输出图片内存根据YUV420SP格式计算,计算公式:对齐后的宽*对齐后的高*3/2。
  • 资源释放
    • 数据预处理结束后,除数据预处理的输出内存(要作为模型推理的输入,需等模型推理结束后才能释放),其它相关资源需及时释放,例如数据预处理的输入内存、图片描述信息等。
    • 与数据预处理相关的内存必须通过acldvppMalloc接口申请,通过acldvppFree接口释放。

关于其它数据预处理的功能,请参见数据预处理

示例代码

调用接口后,需增加异常处理的分支,同时通过ERROR_LOG记录报错日志、通过INFO_LOG记录各动作的提示日志,示例代码中不一一列举。

示例代码如下,您可以从acl_dvpp_resnet50样例的“src/sample_process.cpp”“src/dvpp_process.cpp”文件中查看完整样例代码。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include "acl/acl.h"
#include "acl/ops/acl_dvpp.h"
//......
//初始化变量,请参见样例代码

//循环处理每张图片,testPic是自定义的一个结构体,用于描述图片的名称picName、图片宽width、图片高height。
for (size_t index = 0; index < sizeof(testPic) / sizeof(testPic[0]); ++index) {

    //1. 申请缩放输出内存resizeOutBufferDev_
    //内存大小resizeOutBufferSize_根据计算公式得出(YUV420SP:对齐后的宽*对齐后的高*3/2)
    aclError ret = acldvppMalloc(&resizeOutBufferDev_, resizeOutBufferSize_)

    //2. 申请解码输出内存,并创建解码输出图片的描述信息

    //2.1 申请解码输出内存decodeOutDevBuffer_,内存大小decodeOutBufferSize根据计算公式得出(YUV420SP:对齐后的宽*对齐后的高*3/2)
    ret = acldvppMalloc(&decodeOutDevBuffer_, decodeOutBufferSize)

    //2.2 创建解码输出图片的描述信息,设置各属性值
    decodeOutputDesc_ = acldvppCreatePicDesc();
    acldvppSetPicDescData(decodeOutputDesc_, decodeOutDevBuffer_);
    acldvppSetPicDescFormat(decodeOutputDesc_, PIXEL_FORMAT_YUV_SEMIPLANAR_420);
    acldvppSetPicDescWidth(decodeOutputDesc_, inputWidth_);
    acldvppSetPicDescHeight(decodeOutputDesc_, inputHeight_);
    acldvppSetPicDescWidthStride(decodeOutputDesc_, decodeOutWidthStride);
    acldvppSetPicDescHeightStride(decodeOutputDesc_, decodeOutHeightStride);
    acldvppSetPicDescSize(decodeOutputDesc_, decodeOutBufferSize);


    //3. 执行异步解码,再调用aclrtSynchronizeStream接口阻塞Host运行,直到指定Stream中的所有任务都完成
    ret = acldvppJpegDecodeAsync(dvppChannelDesc_, inDevBuffer_, inDevBufferSize_, decodeOutputDesc_, stream_);

    ret = aclrtSynchronizeStream(stream_);

    //4. 解码结束后,释放资源,包括解码输出图片的描述信息
    acldvppDestroyPicDesc(decodeOutputDesc_);
   
    //5. 创建缩放输入图片的描述信息,并设置各属性值
    resizeInputDesc_ = acldvppCreatePicDesc();
    acldvppSetPicDescData(resizeInputDesc_, decodeOutDevBuffer_);
    acldvppSetPicDescFormat(resizeInputDesc_, PIXEL_FORMAT_YVU_SEMIPLANAR_420);
    acldvppSetPicDescWidth(resizeInputDesc_, inputWidth_);
    acldvppSetPicDescHeight(resizeInputDesc_, inputHeight_);
    acldvppSetPicDescWidthStride(resizeInputDesc_, jpegOutWidthStride);
    acldvppSetPicDescHeightStride(resizeInputDesc_, jpegOutHeightStride);
    acldvppSetPicDescSize(resizeInputDesc_, jpegOutBufferSize);

    //6. 创建缩放输出图片的描述信息,resizeOutBufferDev_内存中的数据作为模型推理的输入
    resizeOutputDesc_ = acldvppCreatePicDesc();
    acldvppSetPicDescData(resizeOutputDesc_, resizeOutBufferDev_);
    acldvppSetPicDescFormat(resizeOutputDesc_, PIXEL_FORMAT_YUV_SEMIPLANAR_420);
    acldvppSetPicDescWidth(resizeOutputDesc_, modelInputWidth_);
    acldvppSetPicDescHeight(resizeOutputDesc_, modelInputHeight_);
    acldvppSetPicDescWidthStride(resizeOutputDesc_, resizeOutputWidthStride);
    acldvppSetPicDescHeightStride(resizeOutputDesc_, resizeOutputHeightStride);
    acldvppSetPicDescSize(resizeOutputDesc_, resizeOutBufferSize_);

    //7. 执行异步缩放,再调用aclrtSynchronizeStream接口阻塞Host运行,直到指定Stream中的所有任务都完成
    ret = acldvppVpcResizeAsync(dvppChannelDesc_, resizeInputDesc_,
        resizeOutputDesc_, resizeConfig_, stream_);
    ret = aclrtSynchronizeStream(stream_);

    //8. 释放资源
    //8.1 缩放结束后,释放资源,包括解码的输出内存、缩放输入图片的描述信息、输出图片描述信息
    (void)acldvppFree(decodeOutDevBuffer_);
    acldvppDestroyPicDesc(resizeInputDesc_);
    acldvppDestroyPicDesc(resizeOutputDesc_); 
   
    //8.2 释放其它资源,包括缩放配置、图片数据处理的通道及其描述信息
    acldvppDestroyResizeConfig(resizeConfig_);
    aclError ret = acldvppDestroyChannel(dvppChannelDesc_);
    acldvppDestroyChannelDesc(dvppChannelDesc_);

    //8.3释放通过acldvppMalloc接口申请的数据预处理的输入内存picDevBuffer
    (void)acldvppFree(picDevBuffer);

    //TODO: 模型推理
}
//......
分享:

    相关文档

    相关产品

close