CUDA小白 - NPP(6) 图像处理 Geometry Transforms (2)

cuda小白
原始API链接 NPP

GPU架构近些年也有不少的变化,具体的可以参考别的博主的介绍,都比较详细。还有一些cuda中的专有名词的含义,可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》

常见的NppStatus,可以看这里。

Affine Transform

仿射变换
在这里插入图片描述

// 仿射变换
NppStatus nppiWarpAffine_8u_C3R(const Npp8u *pSrc,
								NppiSize oSrcSize,
								int nSrcStep,
								NppiRect oSrcROI,
								Npp8u *pDst,
								int nDstStep,
								NppiRect oDstROI,
								const double aCoeffs[2][3],
								int eInterpolation);
// 同样的2x3的矩阵的逆仿射变换
NppStatus nppiWarpAffineBack_8u_C3R(const Npp8u *pSrc,
									NppiSize oSrcSize,
									int nSrcStep,
									NppiRect oSrcROI,
									Npp8u *pDst,
									int nDstStep,
									NppiRect oDstROI,
									const double aCoeffs[2][3],
									int eInterpolation);
// 源图像的四边形 仿射变换到 目标的四边形,平时使用较少,后续不进行测试
NppStatus nppiWarpAffineQuad_8u_C3R(const Npp8u *pSrc,
									NppiSize oSrcSize,
									int nSrcStep,
									NppiRect oSrcROI,
									const double aSrcQuad[4][2],
									Npp8u *pDst,
									int nDstStep,
									NppiRect oDstROI,
									const double aDstQuad[4][2],
									int eInterpolation);
code
#include 
#include 
#include 
#include 

#define CUDA_FREE(ptr) { if (ptr != nullptr) { cudaFree(ptr); ptr = nullptr; } }

int main() {
  std::string directory = "../";
  cv::Mat image_dog = cv::imread(directory + "dog.png");
  int image_width = image_dog.cols;
  int image_height = image_dog.rows;
  int image_size = image_width * image_height;

  // =============== device memory ===============
  // input
  uint8_t *in_image;
  cudaMalloc((void**)&in_image, image_size * 3 * sizeof(uint8_t));
  cudaMemcpy(in_image, image_dog.data, image_size * 3 * sizeof(uint8_t), cudaMemcpyHostToDevice);

  // output
  uint8_t *out_ptr1, *out_ptr2;
  cudaMalloc((void**)&out_ptr1, image_size * 3 * sizeof(uint8_t));  // 三通道
  cudaMalloc((void**)&out_ptr2, image_size * 3 * sizeof(uint8_t));  // 三通道

  double angle = 30.0;
  double scale = 0.6;
  cv::Point center = cv::Point(image_width / 2, image_height / 2);
  cv::Mat rot_mat = cv::getRotationMatrix2D(center, angle, scale);
  double coeffs[2][3] = { rot_mat.at<double>(0, 0),
                          rot_mat.at<double>(0, 1),
                          rot_mat.at<double>(0, 2),
                          rot_mat.at<double>(1, 0),
                          rot_mat.at<double>(1, 1),
                          rot_mat.at<double>(1, 2)};

  NppiSize in_size;
  in_size.width = image_width;
  in_size.height = image_height;
  NppiRect rc;
  rc.x = 0;
  rc.y = 0;
  rc.width = image_width;
  rc.height = image_height;

  cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);
  NppStatus status;
  // =============== nppiWarpAffine_8u_C3R ===============
  status = nppiWarpAffine_8u_C3R(in_image, in_size, image_width * 3, rc, out_ptr1, image_width * 3, 
                                 rc, coeffs, NPPI_INTER_LINEAR);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiWarpAffine_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr1, image_size * 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "affine.jpg", out_image);

   // =============== nppiWarpAffineBack_8u_C3R ===============
  status = nppiWarpAffineBack_8u_C3R(out_ptr1, in_size, image_width * 3, rc, out_ptr2, image_width * 3, 
                                     rc, coeffs, NPPI_INTER_LINEAR);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiWarpAffineBack_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr2, image_size * 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "affine_back.jpg", out_image);

  // free
  CUDA_FREE(in_image)
  CUDA_FREE(out_ptr1)
  CUDA_FREE(out_ptr2)
}
make
cmake_minimum_required(VERSION 3.20)
project(test)

find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})
file(GLOB CUDA_LIBS "/usr/local/cuda/lib64/*.so")

add_executable(test test.cpp)
target_link_libraries(test
                      ${OpenCV_LIBS}
                      ${CUDA_LIBS}
)
result

CUDA小白 - NPP(6) 图像处理 Geometry Transforms (2)_第1张图片

Perspective Transform

透视变换

NppStatus nppiWarpPerspective_8u_C3R(const Npp8u *pSrc,
									 NppiSize oSrcSize,
									 int nSrcStep,
									 NppiRect oSrcROI,
									 Npp8u *pDst,
									 int nDstStep,
									 NppiRect oDstROI,
									 const double aCoeffs[3][3],
									 int eInterpolation);

NppStatus nppiWarpPerspectiveBack_8u_C3R(const Npp8u *pSrc,
									     NppiSize oSrcSize,
								         int nSrcStep,
										 NppiRect oSrcROI,
										 Npp8u *pDst,
										 int nDstStep,
										 NppiRect oDstROI,
										 const double aCoeffs[3][3],
										 int eInterpolation);
code
#include 
#include 
#include 
#include 

#define CUDA_FREE(ptr) { if (ptr != nullptr) { cudaFree(ptr); ptr = nullptr; } }

int main() {
  std::string directory = "../";
  cv::Mat image_dog = cv::imread(directory + "dog.png");
  int image_width = image_dog.cols;
  int image_height = image_dog.rows;
  int image_size = image_width * image_height;

  // =============== device memory ===============
  // input
  uint8_t *in_image;
  cudaMalloc((void**)&in_image, image_size * 3 * sizeof(uint8_t));
  cudaMemcpy(in_image, image_dog.data, image_size * 3 * sizeof(uint8_t), cudaMemcpyHostToDevice);

  // output
  uint8_t *out_ptr1, *out_ptr2;
  cudaMalloc((void**)&out_ptr1, image_size * 3 * sizeof(uint8_t));  // 三通道
  cudaMalloc((void**)&out_ptr2, image_size * 3 * sizeof(uint8_t));  // 三通道

  cv::Point2f src_pts[4], dst_pts[4];
  src_pts[0].x = 0.0;
  src_pts[0].y = 0.0;
  src_pts[1].x = image_width - 1.0;
  src_pts[1].y = 0.0;
  src_pts[2].x = 0.0;
  src_pts[2].y = image_height - 1.0;
  src_pts[3].x = image_width - 1.0;
  src_pts[3].y = image_height - 1.0;

  dst_pts[0].x = image_width * 0.05;
  dst_pts[0].y = image_height * 0.05;
  dst_pts[1].x = image_width * 0.9;
  dst_pts[1].y = image_height * 0.1;
  dst_pts[2].x = image_width * 0.2;
  dst_pts[2].y = image_height * 0.8;
  dst_pts[3].x = image_width * 0.85;
  dst_pts[3].y = image_height * 0.85;

  cv::Mat warp_mat = cv::getPerspectiveTransform(src_pts, dst_pts);
  double coeffs[3][3] = { warp_mat.at<double>(0, 0),
                          warp_mat.at<double>(0, 1),
                          warp_mat.at<double>(0, 2),
                          warp_mat.at<double>(1, 0),
                          warp_mat.at<double>(1, 1),
                          warp_mat.at<double>(1, 2),
                          warp_mat.at<double>(2, 0),
                          warp_mat.at<double>(2, 1),
                          warp_mat.at<double>(2, 2) };
  
  NppiSize in_size;
  in_size.width = image_width;
  in_size.height = image_height;
  NppiRect rc;
  rc.x = 0;
  rc.y = 0;
  rc.width = image_width;
  rc.height = image_height;

  cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);
  NppStatus status;
  // =============== nppiWarpPerspective_8u_C3R ===============
  status = nppiWarpPerspective_8u_C3R(in_image, in_size, image_width * 3, rc, out_ptr1, image_width * 3, 
                                      rc, coeffs, NPPI_INTER_LINEAR);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiWarpPerspective_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr1, image_size * 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "perspective.jpg", out_image);

  // =============== nppiWarpPerspectiveBack_8u_C3R ===============
  status = nppiWarpPerspectiveBack_8u_C3R(out_ptr1, in_size, image_width * 3, rc, out_ptr2, image_width * 3, 
                                          rc, coeffs, NPPI_INTER_LINEAR);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiWarpPerspectiveBack_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr2, image_size * 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "perspective_back.jpg", out_image);

  // free
  CUDA_FREE(in_image)
  CUDA_FREE(out_ptr1)
  CUDA_FREE(out_ptr2)
}
make
cmake_minimum_required(VERSION 3.20)
project(test)

find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})
file(GLOB CUDA_LIBS "/usr/local/cuda/lib64/*.so")

add_executable(test test.cpp)
target_link_libraries(test
                      ${OpenCV_LIBS}
                      ${CUDA_LIBS}
)
result

CUDA小白 - NPP(6) 图像处理 Geometry Transforms (2)_第2张图片

你可能感兴趣的:(c++,CUDA,NPP)