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

图像Crop/Resize

在Ascend 310上编程,图像crop/resize推荐使用DVPP来实现。

图1 crop/resize运行示意图

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)输入。
分享:

    相关文档

    相关产品