图像Crop/Resize
在Ascend 310上编程,图像crop/resize推荐使用DVPP来实现。
crop/resize运行示意图如图1所示,它可以完成在图像中对ROI区域进行截图并使用这个截图进行重采样的过程。截图称为crop,重采样称之为resize。当resize系数为1时,相当于只做crop。当crop为原图时,相当于只做resize。
crop/resize对输入的限制如下:
- 输入数据地址(os虚拟地址):16字节对齐。
- 输入图像宽度内存限制:16字节对齐。
- 输入图像高度内存限制:2字节对齐。
基于上述限制,高性能的编程方式要实现“0拷贝”则需要满足从Device(接收端)给用户的内存地址开始就满足限制。一般的做法根据输入不同分为以下两种做法。
- 方法一:在Host进行解码或者在其他硬件进行解码的应用,在Host发送端将数据就做好裁剪或者padding,满足16*2对齐,这样框架在数据接收端会自动的申请满足上述限制的数据内存。
示例的输入数据是YUV图片,所以计算图片SIZE都是通过(ImageWidth * ImageHeight) * 3/2的方式,其他格式的数据,根据图片格式自行调整。
static const uint32_t ALIGN_W = 16; static const uint32_t ALIGN_H = 2; uint32_t imageWidth = 500; uint32_t imageHeight = 333; uint32_t imageSize = imageWidth * imageHeight *3/2; uint32_t align_width = image_width, align_height = image_height; // 进行宽高对齐 alignWidth = (alignWidth % ALIGN_W) ? alignWidth : (imageWidth + ALIGN_W)/ALIGN_W* ALIGN_W; alignHeight = (alignHeight % ALIGN_H) ? alignHeight : (imageHeight + ALIGN_H)/ALIGN_H * ALIGN_H; uint32_t alignSize = alignWidth * alignHeight *3/2; // 读取文件数据, 拷贝对齐内存 FILE *fpIn = fopen(filePath.data(), "rb"); Uint8_t* imageBuffer = (uint8_t*) malloc(imageSize); HIAI_StatusT getRet = hiai::HIAIMemory::HIAI_DMalloc(fileLen, (void*&)alignBuffer, 10000); size_t size = fread(imageBuffer, 1, imageSize, fpIn); // 进行拷贝 Uint32_t tempLen = imageWidth * imageHeight; if (alignWidth == imageWidth) { if(alignHeight > imageHeight) { memcpy_s(alignBuffer, tempLen, imageBuffer, tempLen); memcpy_s(alignBuffer + alignHeight * alignWidth, tempLen/2, imageBuffer + tempLen, tempLen/2); } } else { for(int32_t n=0;n<imageHeight;n++) { memcpy_s(alignBuffer+n*alingWidth,imageWidth, imageBuffer+n*imageWidth,imageWidth); } for(int32_t n=0;n<imageHeight/2;n++) { memcpy_s(alignBuffer+n*alignWidth+alignHeight* alignWidth, imageWidth, imageBuffer+n* imageWidth + imageHeight*imageWidth,imageWidth);//UV } }
- 方法二:在Device进行图片解码、视频解码以后输出为16*2对齐,可直接作为DVPP VPC(Crop&&Resize)输入。