[23] cuda应用之 nppi 实现图像缩放
-
NPP(NVIDIA Performance Primitives)是一个由 NVIDIA 提供的库,专门用于加速图像和信号处理任务。NPP 提供了许多高效的图像处理函数,包括图像缩放。使用 NPP 实现图像缩放可以充分利用 GPU 的并行计算能力,从而加速处理过程。
-
以下是一个使用 NPP 实现图像缩放的简单示例,主要流程如下:
- 加载图像拷贝到设备内存
- nppi实现图像缩放
- 设备内存拷贝到主机内存
1. nppi实现图像缩放
/*
* 测试nppi实现图像缩放
*/#include <opencv2/opencv.hpp> // OpenCV 用于加载和保存图像
#include <nppi.h> // NPP 库
#include <nppi_geometry_transforms.h> // NPP 图像几何变换
#include <cuda_runtime.h> // CUDA 运行时
#include <iostream>int main()
{//0. 主机分配内存示例// 假设输入图像是 8 位灰度图像/* unsigned char* h_inputImage = new unsigned char[INPUT_IMAGE_WIDTH * INPUT_IMAGE_HEIGHT];unsigned char* h_outputImage = new unsigned char[OUTPUT_IMAGE_WIDTH * OUTPUT_IMAGE_HEIGHT];*/// 1. 使用 OpenCV 加载图像std::string inputImagePath = "images/autumn.tif"; // 输入图像路径//cv::Mat h_srcImage = cv::imread(inputImagePath, cv::IMREAD_GRAYSCALE); // 以灰度模式加载图像cv::Mat h_srcImage = cv::imread(inputImagePath);if (h_srcImage.empty()) {std::cerr << "Error: Could not load image!" << std::endl;return -1;}int srcWidth = h_srcImage.cols; // 输入图像宽度int srcHeight = h_srcImage.rows; // 输入图像高度int srcChannel = h_srcImage.channels(); //输入图像通道数// 2. 定义输出图像尺寸//int dstWidth = srcWidth / 2; // 输出图像宽度(缩放为一半)//int dstHeight = srcHeight / 2; // 输出图像高度int dstWidth = srcWidth * 2; // 输出图像宽度(缩放为2倍)int dstHeight = srcHeight * 2; // 输出图像高度int dstChannel = srcChannel;cv::Mat h_dstImage;if (srcChannel == 1){h_dstImage = cv::Mat(dstHeight, dstWidth, CV_8UC1); // 输出图像(灰度)}else if (srcChannel == 3){h_dstImage = cv::Mat(dstHeight, dstWidth, CV_8UC3); // 输出图像(彩色)}// 3. 分配设备内存unsigned char* d_srcImage;unsigned char* d_dstImage;cudaMalloc((void**)&d_srcImage, srcWidth * srcHeight * srcChannel * sizeof(unsigned char)); // 输入图像设备内存cudaMalloc((void**)&d_dstImage, dstWidth * dstHeight * dstChannel * sizeof(unsigned char)); // 输出图像设备内存// 4. 将输入图像数据从主机复制到设备cudaMemcpy(d_srcImage, h_srcImage.data, srcWidth * srcHeight * srcChannel * sizeof(unsigned char), cudaMemcpyHostToDevice);// 5. 使用 NPP 进行图像缩放NppiSize srcSize = { srcWidth, srcHeight }; // 输入图像尺寸NppiRect srcROI = { 0, 0, srcWidth, srcHeight }; // 输入图像 ROINppiSize dstSize = { dstWidth, dstHeight }; // 输出图像尺寸NppiRect dstROI = { 0, 0, dstWidth, dstHeight }; // 输出图像 ROIint interpolationMode = NPPI_INTER_LINEAR; // 使用线性插值// 调用 NPP 图像缩放函数NppStatus status;if (srcChannel == 1){status = nppiResize_8u_C1R(d_srcImage, srcWidth, srcSize, srcROI,d_dstImage, dstWidth, dstSize, dstROI,interpolationMode);}else if (srcChannel == 3){status = nppiResize_8u_C3R(d_srcImage, srcWidth * srcChannel, srcSize, srcROI,d_dstImage, dstWidth * dstChannel, dstSize, dstROI,interpolationMode);}if (status != NPP_SUCCESS) {std::cerr << "NPP Image Resize failed with error code: " << status << std::endl;return -1;}// 6. 将缩放后的图像数据从设备复制回主机cudaMemcpy(h_dstImage.data, d_dstImage, dstWidth * dstHeight * dstChannel * sizeof(unsigned char), cudaMemcpyDeviceToHost);// 7. 保存或显示结果std::string outputImagePath = "output.jpg"; // 输出图像路径cv::namedWindow("dst", 0);cv::imshow("dst", h_dstImage);cv::waitKey(0);cv::imwrite(outputImagePath, h_dstImage); // 保存缩放后的图像std::cout << "Resized image saved to: " << outputImagePath << std::endl;// 8. 释放设备内存cudaFree(d_srcImage);cudaFree(d_dstImage);return 0;
}
2.相关函数介绍
- nppiResize 系列函数用于缩放图像,支持不同的图像格式和插值方式,以决定在缩放过程中如何计算像素值。常见的插值方法包括:
NPPI_INTER_NEAREST:最近邻插值,最快,但质量较差。
NPPI_INTER_LINEAR:线性插值,速度较快,质量适中。
NPPI_INTER_CUBIC:立方插值,计算量较大,但质量较高。
NPPI_INTER_LANCZOS:Lanczos 插值,计算量较大,图像质量非常好。
nppiResize_8u_C1R
用于缩放单通道(灰度图像)8位无符号整数图像。
NppStatus nppiResize_8u_C1R(const Npp8u* pSrc, NppiSize oSrcSize, int nSrcStep,NppiSize oDstSize, Npp8u* pDst, int nDstStep,NppiInterpolationMode eInterpolation);
- 参数
pSrc:输入图像数据的指针。
oSrcSize:输入图像的宽度和高度。
nSrcStep:输入图像的步长(通常为宽度 * 通道数)。
oDstSize:目标图像的宽度和高度。
pDst:输出图像数据的指针。
nDstStep:输出图像的步长。
eInterpolation:插值方法(如 NPPI_INTER_LINEAR)。
nppiResize_8u_C3R
用于缩放三通道(如 RGB 彩色图像)8位无符号整数图像。
NppStatus nppiResize_8u_C3R(const Npp8u* pSrc, NppiSize oSrcSize, int nSrcStep,NppiSize oDstSize, Npp8u* pDst, int nDstStep,NppiInterpolationMode eInterpolation);- 参数:
pSrc:输入图像数据的指针。
oSrcSize:输入图像的宽度和高度。
nSrcStep:输入图像的步长。
oDstSize:目标图像的宽度和高度。
pDst:输出图像数据的指针。
nDstStep:输出图像的步长。
eInterpolation:插值方法。
nppiResize_16u_C1R
用于缩放单通道16位无符号整数图像。
NppStatus nppiResize_16u_C1R(const Npp16u* pSrc, NppiSize oSrcSize, int nSrcStep,NppiSize oDstSize, Npp16u* pDst, int nDstStep,NppiInterpolationMode eInterpolation);- 与 nppiResize_8u_C1R 类似,只是支持 16 位图像数据。
nppiResize_32f_C1R / nppiResize_32f_C3R
用于处理单通道或三通道32位浮点图像的缩放。
NppStatus nppiResize_32f_C1R(const Npp32f* pSrc, NppiSize oSrcSize, int nSrcStep,NppiSize oDstSize, Npp32f* pDst, int nDstStep,NppiInterpolationMode eInterpolation);
- 参数:与 nppiResize_8u_C1R 类似,只是数据类型变为 32 位浮点
nppiResize_8u_P2C3R
适用于处理图像中的区域进行缩放的函数,处理的是图片的矩形区域。
NppStatus nppiResize_8u_P2C3R(const Npp8u* pSrc, NppiSize oSrcSize, int nSrcStep,NppiSize oDstSize, Npp8u* pDst, int nDstStep,NppiInterpolationMode eInterpolation, NppiSize oROI);- 参数:
oSrcSize:输入图像的尺寸。
oDstSize:目标图像的尺寸。
eInterpolation:插值方法。
pDstBufferSize:返回所需的缓冲区大小。