2

I use cv::cuda::remap instead of cv::remap to take advantage of CUDA acceleration to speed up video undistortion. Both versions of the program can run normally, but, while the camera matrix, distortion coefficients, map1 and map2 which come from cv::initUndistortRectifyMap() are all the same, the undistorted result image of the CPU version cv::remap is correct as follow:

enter image description here

but the CUDA version cv::cuda::remap results in a problem:

enter image description here

The code snippet for the CPU version is as follows:

cv::cuda::GpuMat gpuMat(m_height, m_width, CV_8UC4, (void *)dpFrame);
cv::Mat mat;
gpuMat.download(mat);
cv::remap(mat, mat, m_map1, m_map2, cv::INTER_LINEAR);
gpuMat.upload(mat);

GPU version:

cv::cuda::GpuMat gpuMat(m_height, m_width, CV_8UC4, (void *)dpFrame);
cv::cuda::remap(gpuMat, gpuMat, m_gpuMap1, m_gpuMap2, cv::INTER_LINEAR);

Among them, dpFrame is of type CUdeviceptr, m_map1 and m_map2 are calculated by cv::initUndistortRectifyMap, m_gpuMap1 and m_gpuMap2 are of type cv::cuda::GpuMat obtained by uploading m_map1 and m_map2 to GPU.

cv::remap and cv::cuda::remap are the same algorithm, why are their results different? I tried both versions of OpenCV 455 and 460, and neither works.

I'm stuck here and don't know how to go forward. Any suggestions are really appreciated. Thanks.

talonmies
  • 70,661
  • 34
  • 192
  • 269
Sang
  • 141
  • 11
  • 2
    you... expected that to work in-place? I wouldn't even expect that to work in-place on the CPU. this operation can't be performed in-place *in principle*. it has to be an operation from one piece of memory to the other. if anything here made "in-place" "work", it did an implicit copy/allocation. – Christoph Rackwitz Jul 01 '22 at 18:21
  • 1
    NB: remapping _can_ sometimes be done in-place, after examining the map and figuring out which pixels to map in what order, which directly depends on the values in the map and means you can't just iterate over it in arbitrary ways. in some cases interpolation would become tricky too. -- none of that happens in `cv::remap()`. – Christoph Rackwitz Jul 02 '22 at 10:07
  • Thanks for your explanation on the in-place issue. It does matter whether an algorithm can operate in-place. @ChristophRackwitz – Sang Jul 04 '22 at 02:45

1 Answers1

2

Okey, I also tried your code and got the similar results. I ended up with getting a correct result after a few tests.

My code simply flips an image with remap. Here is your code result to my input:

Code

cv::cuda::GpuMat gpuMat(m_height, m_width, CV_8UC4, (void *)dpFrame);
cv::cuda::remap(gpuMat, gpuMat, m_gpuMap1, m_gpuMap2, cv::INTER_LINEAR);

Input

enter image description here

Output

enter image description here

Then I just add a new declaration of cv::cuda::GpuMat and put it to output of resize function. Here is the code.

    cv::cuda::GpuMat gpuMat(m_height, m_width, CV_8UC4, (void *)dpFrame);
    cv::cuda::GpuMat gpuMat2;
    cv::cuda::remap(gpuMat, gpuMat2, m_gpuMap1, m_gpuMap2, cv::INTER_LINEAR);

    gpuMat2.download(mat);

New Output

enter image description here

I dont have a clear answer to the question why. Since we deal with gpu, it seems better to define different types for input and output of resize

Yunus Temurlenk
  • 4,085
  • 4
  • 18
  • 39
  • It is right. Thank you very much. I separate the two parameters, it results correctly. `cv::cuda::GpuMat` has a member method `copyTo`, I use it to make a GpuMat as the source. – Sang Jul 04 '22 at 02:29