如果没有编译GPU版本的OpenCV,也可以利用Nvidia提供的基于cuda的图像处理高层api。
NPP是一个用于执行CUDA加速2D图像和信号处理的函数库。库中的主要功能集中于图像处理,广泛适用于这些领域的开发人员。随着时间的推移,NPP将在各种问题领域中包含更多计算繁重的任务。NPP库的编写是为了最大限度地提高灵活性,同时保持高性能。
void cudaResize(cv::Mat &image, cv::Mat &rsz_img)
{
int outsize = rsz_img.cols * rsz_img.rows * sizeof(uchar3);
int inwidth = image.cols;
int inheight = image.rows;
int memSize = inwidth * inheight * sizeof(uchar3);
NppiSize srcsize = {inwidth, inheight};
NppiRect srcroi = {0, 0, inwidth, inheight};
NppiSize dstsize = {rsz_img.cols, rsz_img.rows};
NppiRect dstroi = {0, 0, rsz_img.cols, rsz_img.rows};
uchar3* d_src = NULL;
uchar3* d_dst = NULL;
cudaMalloc((void**)&d_src, memSize);
cudaMalloc((void**)&d_dst, outsize);
cudaMemcpy(d_src, image.data, memSize, cudaMemcpyHostToDevice);
// nvidia npp 图像处理,注意:函数参数step是图像宽的三倍(三通道)
nppiResize_8u_C3R( (Npp8u*)d_src, inwidth * 3, srcsize, srcroi,
(Npp8u*)d_dst, rsz_img.cols * 3, dstsize, dstroi,
NPPI_INTER_NN);
cudaMemcpy(rsz_img.data, d_dst, outsize, cudaMemcpyDeviceToHost);
cudaFree(d_src);
cudaFree(d_dst);
}
对于旋转操作,需注意旋转中心是左上角,旋转180°后需要shift图片才行,具体见代码
void cudaRemap(cv::Mat &image, cv::Mat &rsz_img, Npp32f* d_mapx, Npp32f* d_mapy, bool rotate_flag)
{
int outsize = rsz_img.cols * rsz_img.rows * sizeof(uchar3);
int inwidth = image.cols;
int inheight = image.rows;
int memSize = inwidth * inheight * sizeof(uchar3);
NppiSize srcsize = {inwidth, inheight};
NppiRect srcroi = {0, inheight/2, inwidth, inheight};
NppiSize dstsize = {rsz_img.cols, rsz_img.rows};
NppiRect dstroi = {0, 0, rsz_img.cols, rsz_img.rows};
Npp8u* d_src = NULL;
Npp8u* r_tmp = NULL;
Npp8u* d_dst = NULL;
cudaMalloc((void**)&d_src, memSize);
cudaMalloc((void**)&r_tmp, memSize);
cudaMalloc((void**)&d_dst, outsize);
cudaMemcpy(d_src, image.data, memSize, cudaMemcpyHostToDevice);
NppiRect rotate_roi = {0, 0, inwidth, inheight};
if (rotate_flag){
// *** nppiRotate_8u_C3R: Rotates an image around the origin (0,0) and then shifts it. Origin -> left bottom corner ***
NppStatus res = nppiRotate_8u_C3R(d_src, srcsize, inwidth * 3, rotate_roi,
r_tmp, inwidth * 3, rotate_roi, 180.0, srcsize.width-1, srcsize.height-1, NPPI_INTER_NN);
nppiRemap_8u_C3R(r_tmp,
srcsize,
inwidth * 3,
srcroi,
d_mapx,
(rsz_img.cols * sizeof(float)),
d_mapy,
(rsz_img.cols * sizeof(float)),
d_dst,
rsz_img.cols * 3,
dstsize,
NPPI_INTER_LINEAR);
}
else{
nppiRemap_8u_C3R(d_src,
srcsize,
inwidth * 3,
srcroi,
d_mapx,
(rsz_img.cols * sizeof(float)),
d_mapy,
(rsz_img.cols * sizeof(float)),
d_dst,
rsz_img.cols * 3,
dstsize,
NPPI_INTER_LINEAR);
}
cudaMemcpy(rsz_img.data, d_dst, outsize, cudaMemcpyDeviceToHost);
cudaFree(d_src);
cudaFree(r_tmp);
cudaFree(d_dst);
}
https://docs.nvidia.com/cuda/npp/index.html