当前位置:   article > 正文

CUDA库之NPP入门(三):NPP实现Resize操作_cuda nppi

cuda nppi

博主将在 编程语言|CUDA入门中不定期更新NPP库相关知识



一、前言

本文主要利用npp实现图像中的resize操作,主要步骤如下:

  • 1、利用Opencv读取图像;
  • 2、将图像数据拷贝到设备端;
  • 3、调用nppiResize函数,实现resize操作
  • 4、将nppiResize后的图像数据拷贝到Mat,并保存验证结果

二、nppiResize_8u_C3R函数定义

NppStatus 
nppiResize_8u_C3R(const Npp8u * pSrc, int nSrcStep, NppiSize oSrcSize, NppiRect oSrcRectROI, 
                        Npp8u * pDst, int nDstStep, NppiSize oDstSize, NppiRect oDstRectROI, int eInterpolation);

  • 1
  • 2
  • 3
  • 4
  • nSrcStep 指的是步长,即每行数据所占字节数,一般用opencv读取的图像,步长数都是 W ∗ 3 W * 3 W3
    也可以调用matSrc.step来获取步长;
  • **NppiSize**指感兴趣区域操作,这里赋值为图像的大小即可
  • **eInterpolation** e开头,显然是个枚举,这里指resize中所使用插值类型

npp支持的插值类型都定义在NppiInterpolationMode这个枚举中,可以在nppdefs.h中查看

常见的有最近邻、线程插值、三次插值等

typedef enum 
{
    NPPI_INTER_UNDEFINED         = 0,
    NPPI_INTER_NN                = 1,        /**<  最近邻插值 */
    NPPI_INTER_LINEAR            = 2,        /**<  线性插值 */
    NPPI_INTER_CUBIC             = 4,        /**<  三次插值 */
    NPPI_INTER_CUBIC2P_BSPLINE,              /**<  Two-parameter cubic filter (B=1, C=0) */
    NPPI_INTER_CUBIC2P_CATMULLROM,           /**<  Two-parameter cubic filter (B=0, C=1/2) */
    NPPI_INTER_CUBIC2P_B05C03,               /**<  Two-parameter cubic filter (B=1/2, C=3/10) */
    NPPI_INTER_SUPER             = 8,        /**<  Super sampling. */
    NPPI_INTER_LANCZOS           = 16,       /**<  Lanczos filtering. */
    NPPI_INTER_LANCZOS3_ADVANCED = 17,       /**<  Generic Lanczos filtering with order 3. */
    NPPI_SMOOTH_EDGE             = (1 << 31) /**<  Smooth edge filtering. */
} NppiInterpolationMode; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

三、Demo示例

通常调用opencv的resize函数,即可实现resize操作

cv::resize(matSrc, matDst, cv::Size(nRzW, nRzH));
  • 1

但当出现图像内存解码在GPU上,总不能从GPU将数据拷贝到host端,再调用opencv的resize函数,再从host端拷贝到device端,再执行模型推断,那中间这个拷贝的过程显然是没有必要的。 好在NVIDIA已经提供了nppiResize函数用来实现这个功能;

const int nRzH = 450;
const int nRzW = 800;
void npp_resizeData()
{
    cv::Mat matSrc = cv::imread("./data/Fig0638(a)(lenna_RGB).jpg");
    int nH = matSrc.rows;
    int nW = matSrc.cols;
    int nC = matSrc.channels();
    int nStep = matSrc.step;
    printf("nH = %d, nW = %d, nC = %d, nStep = %d\n", nH, nW, nC, nStep);
    // 1. 将图像数据拷贝到设备端
    Npp8u *pu8srcData_dev = NULL;
    cudaMalloc((void **)&pu8srcData_dev, nH * nW * nC * sizeof(Npp8u));
    cudaMemcpy(pu8srcData_dev, matSrc.data, nH * nW * nC * sizeof(Npp8u), cudaMemcpyHostToDevice);

    // 2. 在设备端开辟空间
    Npp8u *pu8dstData_dev = NULL;
    NppiSize npp_srcSize{nW, nH};
    NppiSize npp_dstSize{nRzW, nRzH};
    cudaMalloc((void **)&pu8dstData_dev, nRzH * nRzW * nC * sizeof(Npp8u));
    cudaMemset(pu8dstData_dev, 0, nRzH * nRzW * nC * sizeof(Npp8u));
    // 3.调用nppiresize函数
    nppiResize_8u_C3R( (Npp8u*)pu8srcData_dev, nStep,  npp_srcSize,  NppiRect{0, 0, nW, nH},
                       (Npp8u*)pu8dstData_dev, nRzW * 3, npp_dstSize, NppiRect{0, 0, nRzW, nRzH},
                       NPPI_INTER_LINEAR );

    // 将resize后的图像内存(设备端)拷贝到host端
    cv::Mat newimage(nRzH, nRzW, CV_8UC3);
    cudaMemcpy(newimage.data, pu8dstData_dev, nRzH * nRzW * 3, cudaMemcpyDeviceToHost);
    if (pu8dstData_dev != NULL)
    {
        cudaFree(pu8dstData_dev);
        pu8dstData_dev = NULL;
    }
    if (pu8srcData_dev != NULL)
    {
        cudaFree(pu8srcData_dev);
        pu8srcData_dev = NULL;
    }
    // 保存图像,验证结果
    cv::imwrite("./rzImage_npp.jpg", newimage);
}

  • 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

原图: 512 ∗ 512 512*512 512512大小
在这里插入图片描述
resize后 450 ∗ 800 450*800 450800大小
在这里插入图片描述

四、祈福

为河北祈福
在这里插入图片描述
为栖霞矿难祈福
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/432406?site
推荐阅读
相关标签
  

闽ICP备14008679号