介绍
NVIDIA 2D Image And Signal Performance Primitives (NPP)
英伟达二维图像和信号高性能计算库
官方文档:NVIDIA 2D Image And Signal Performance Primitives (NPP): Image-Processing Specific API Conventions
函数命名
不同的图像数据处理函数根据不同的后缀进行区分:
- “A” 如果图像是 4 通道图像,处理函数将不会处理 alpha 通道;
- “Cn” 图像数据的排列方式为像素优先,n 可以是 1,2,3 或 4,OpenCV 图像数据采用像素优先排列方式;
- “Pn” 图像的数据排列方式为通道优先,n 可以是 1,2,3 或 4,GDAL 图像使用通道优先的方式,一般神经网络的数据输入输出也是这种方式;
- “I” 原地操作,图像处理直接在输入图像的内存地址进行;
- “M” M 即为 Mask,标识操作为蒙版操作,只有对应位置的蒙版图像的像素值不为0的位置的数据才会被处理。
- “R” R 即为 ROI,只有在指定的图像区域进行图像处理;
- “Sfs” 在输出结果之前,通过固定的缩放比例和饱和度进行处理;
实现OpenCV的 dnn::blobFromImage 函数
blobFromImage 函数主要做了两个操作:
- 图像 resize 到指定的大小
- 图像数据类型转为 float
npp中对应的两个函数,图像缩放函数 nppiResize_8u_C1R 和 数据类型转换函数 nppiConvert_8u32f_C1R。
// 1 channel 8-bit unsigned image resize.
NppStatus
nppiResize_8u_C1R(const Npp8u * pSrc, int nSrcStep, NppiSize oSrcSize, NppiRect oSrcRectROI, Npp8u * pDst, int nDstStep, NppiSize oDstSize, NppiRect oDstRectROI, int eInterpolation);// Single channel 8-bit unsigned to 32-bit floating-point conversion.
NppStatus
nppiConvert_8u32f_C1R(const Npp8u * pSrc, int nSrcStep, Npp32f * pDst, int nDstStep, NppiSize oSizeROI);
如果是三通道的图像,还涉及到图像数据排列方式的变换,nppiCopy_32f_C3P3R 函数将像素优先的排列方式转换成通道优先。
// 3 channel 8-bit unsigned image resize.
NppStatus
nppiResize_8u_C3R(const Npp8u * pSrc, int nSrcStep, NppiSize oSrcSize, NppiRect oSrcRectROI, Npp8u * pDst, int nDstStep, NppiSize oDstSize, NppiRect oDstRectROI, int eInterpolation);// Single channel 8-bit unsigned to 32-bit floating-point conversion.
NppStatus
nppiConvert_8u32f_C3R(const Npp8u * pSrc, int nSrcStep, Npp32f * pDst, int nDstStep, NppiSize oSizeROI);// Three-channel 32-bit float packed to planar image copy.
NppStatus
nppiCopy_32f_C3P3R(const Npp32f * pSrc, int nSrcStep, Npp32f * const aDst[3], int nDstStep, NppiSize oSizeROI);
使用npp进行图像resize
// 图像resize
// interMode 1:最近邻,2:线性插值
// 返回值参考 NppStatus
int gpu_resize_npp(unsigned char* pSrc, int wSrc, int hSrc, int channel, unsigned char* pDst, int wDst, int hDst, int interMode)
{NppiSize oSrcSize, oDstSize;oSrcSize.width = wSrc;oSrcSize.height = hSrc;oDstSize.width = wDst;oDstSize.height = hDst;NppiRect oSrcRectROI, oDstRectROI;oSrcRectROI.x = 0;oSrcRectROI.y = 0;oSrcRectROI.width = wSrc;oSrcRectROI.height = hSrc;oDstRectROI.x = 0;oDstRectROI.y = 0;oDstRectROI.width = wDst;oDstRectROI.height = hDst;NppStatus ns = NppStatus::NPP_NUMBER_OF_CHANNELS_ERROR;switch (channel){case 1:ns = nppiResize_8u_C1R(pSrc, wSrc, oSrcSize, oSrcRectROI, pDst, wDst, oDstSize, oDstRectROI, interMode);break;case 3:ns = nppiResize_8u_C3R(pSrc, wSrc * 3, oSrcSize, oSrcRectROI, pDst, wDst * 3, oDstSize, oDstRectROI, interMode);break;default:break;}return (int)ns;
}