GPU 上的图像调整大小比 cv::resize 慢

Posted

技术标签:

【中文标题】GPU 上的图像调整大小比 cv::resize 慢【英文标题】:Image resize on GPU is slower than cv::resize 【发布时间】:2020-03-05 20:45:12 【问题描述】:

我正在调整这张测试图片的大小:

Mat im = Mat::zeros(Size(832*3,832*3),CV_8UC3);
putText(im,"HI THERE",Point2i(10,90),1,7,Scalar(255,255,255),2);

按标准

cv::resize(im,out,Size(416,416),0,0,INTER_NEAREST);

并通过 CUDA 版本调整大小:

static void gpuResize(Mat in, Mat &out)
    double k = in.cols/416.;
    cuda::GpuMat gpuInImage;
    cuda::GpuMat gpuOutImage;
    gpuInImage.upload(in);
    const Size2i &newSize = Size(416, in.rows / k);
    //cout << "newSize " << newSize<< endl;
    cuda::resize(gpuInImage, gpuOutImage, newSize,INTER_NEAREST);
    gpuOutImage.download(out);

测量时间表明 cv::resize 快了约 25 倍。我究竟做错了什么?我在 GTX1080ti 显卡上,但也在 Jetson NANO 上观察到同样的情况。是否有任何替代方法可以比使用 nvidia 硬件加速的 cv::resize 更快地调整图像大小?

【问题讨论】:

你如何测量时间?上传和下载是相当昂贵的,所以在下载最终结果之前上传然后执行几个 gpu 操作更有意义。 最有可能将苹果与橙子进行比较,而忘记了 Micka 提到的将数据移入/移出 GPU 所涉及的大量开销。您让 GPU 做的工作太少,不足以超过所涉及的开销。 那我可以向 GPU 提供批量图像吗? 问题解决了吗? @AndrejFogelton 现在解决了(或至少解释了)。请参阅下面的答案。 【参考方案1】:

我今天也在做类似的事情,并且在我的 Jetson NX 上运行在 NVP 模型 2 模式(15W,6 核)下得到了相同的结果。

使用 CPU 将图像大小调整 10,000 倍比使用 GPU 将相同图像大小调整 10,000 倍要快。

这是我的 CPU 代码:

cv::Mat cpu_original_image = cv::imread("test.png"); // 1400x690 RGB image
for (size_t count = 0; count < number_of_times_to_iterate; count ++)

    cv::Mat cpu_resized_image;
    cv::resize(cpu_original_image, cpu_resized_image, desired_image_size);

这是我的 GPU 代码:

cv::cuda::GpuMat gpu_original_image;
gpu_original_image.upload(cpu_original_image);
for (size_t count = 0; count < number_of_times_to_iterate; count ++)

    cv::cuda::GpuMat gpu_resized_image;
    cv::cuda::resize(gpu_original_image, gpu_resized_image, desired_image_size);

我的计时码(上面未显示)仅用于for() 循环,它不包括imread()upload()

当循环调用 10K 次时,我的结果是:

CPU:5786.930 毫秒 GPU:9678.054 毫秒(加上upload() 的额外 170.587 毫秒)

然后我对每个循环进行了 1 处更改。我将“调整大小”的垫子移到循环之外,以防止它在每次迭代时被创建和销毁。然后我的代码如下所示:

cv::Mat cpu_original_image = cv::imread("test.png"); // 1400x690 RGB image
cv::Mat cpu_resized_image;
for (size_t count = 0; count < number_of_times_to_iterate; count ++)

    cv::resize(cpu_original_image, cpu_resized_image, desired_image_size);

...对于 GPU:

cv::cuda::GpuMat gpu_original_image;
gpu_original_image.upload(cpu_original_image);
cv::cuda::GpuMat gpu_resized_image;
for (size_t count = 0; count < number_of_times_to_iterate; count ++)

    cv::cuda::resize(gpu_original_image, gpu_resized_image, desired_image_size);

for() 循环计时结果现在是:

CPU:5768.181 毫秒(基本不变) GPU:2827.898 毫秒(从 9.7 秒到 2.8 秒)

这看起来好多了! GPU 调整大小现在比 CPU 调整大小要快...只要您使用 GPU 做大量工作而不是单次调整大小。并且只要您不不断地重新分配临时 GPU 垫,因为这似乎相当昂贵。


但在这一切之后,回到您最初的问题:如果您所做的只是调整单个图像的大小,或者每次调整多个图像的大小,那么 GPU 调整大小将无济于事,因为将每个图像上传到 GPU垫将比原来的调整需要更长的时间!以下是我在 Jetson NX 上尝试的结果:

在 CPU 上调整单个图像大小:3.565 毫秒 将 mat 上传到 GPU:186.966 毫秒 第二个 GPU 垫的分配和 gpu 调整大小:225.925 毫秒

因此,在 CPU 上,NX 可以在

【讨论】:

请注意,cv::resize 中的调整大小模式会显着影响性能。我还发现在 Jetson 上调整图像大小的最佳方法是将图像快速缩小到 2*dstWidth*2*dstHeight,然后平滑地缩小到 dstWidth*dstHeight——这是速度和质量之间的最佳折衷跨度>

以上是关于GPU 上的图像调整大小比 cv::resize 慢的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV 在大图像上调整大小失败,出现“错误:(-215) ssize.area() > 0 in function cv::resize”

(详解)opencv里的cv2.resize改变图片大小Python

调整在Python中使用Numpy和OpenCV绘制的多边形的大小

如何在opencv python中调整PNG图像的大小? [复制]

OpenCV-尺寸调整cv::resize

图像的缩放