opencv: Results of cv::resize and cv::gpu::resize do not match

Transferred from http://code.opencv.org/issues/3641

|| Lon Risinger on 2014-04-10 18:54
|| Priority: Normal
|| Affected: 2.4.0 - 2.4.8
|| Category: gpu (cuda)
|| Tracker: Bug
|| Difficulty: 
|| PR: 
|| Platform: x64 / Linux

Results of cv::resize and cv::gpu::resize do not match

When re-sizing an image patch using the GPU accelerated version of resize(), the results do not match the results of the equivalent unaccelerated resize().

The code snippet below shows that each channel is off by 1 or occasionally 2.

Possibly useful info:
Type is CV_8UC3 - have not tried other cv::Mat types.
OpenCV compiled with cuda 5.5 and gcc/g++ 4.6
Code snippet compiled with g++ 4.8.1
OS: Linux Ubuntu 13.10

=============================================================================

   std::cout << "OPENCV RESIZE GPU/CPU compare ..." << std::endl;

    // initialize image size 
    cv::Size imgSize(640, 480);



    // initialize image with its pixels going from (0,0,0) to (255,255,255)
    cv::Mat image = cv::Mat(imgSize, CV_8UC3, cv::Scalar(0,0,0));
    for (int row = 0; row < image.rows; ++row)
    {
        for (int col = 0; col < image.cols; ++col)
        {
            image.at<cv::Vec3b>(row, col)[0] = floor(float(row)/float(image.rows)*255.0f);
            image.at<cv::Vec3b>(row, col)[1] = floor(float(col)/float(image.cols)*255.0f);
            image.at<cv::Vec3b>(row, col)[2] = floor(((float(row)/float(image.rows) + float(col)/float(image.cols))/2.0f) * 255.0f);
        }
    }

    cv::gpu::GpuMat image_gpu;
    image_gpu.upload(image);
    cv::Size standardBoxSize(10, 10);
    cv::Rect rawBox(20, 20, 50, 50); // x, y, width, height
    cv::gpu::GpuMat patch_gpu;
    cv::Mat cpu_resized_patch;
    cv::Mat gpu_resized_patch;

    cv::gpu::Stream stream;
    // resize source image area within rawBox to standard size
    cv::gpu::resize(image_gpu(rawBox), patch_gpu, standardBoxSize);    
    patch_gpu.download(gpu_resized_patch);
    cv::resize(image(rawBox), cpu_resized_patch, standardBoxSize);

    int misMatchCnt = 0;
    for (int row = 0; row < cpu_resized_patch.rows; ++row)
    {
        for (int col = 0; col < cpu_resized_patch.cols; ++col)
        {
            cv::Vec3b pix_cpu = cpu_resized_patch.at<cv::Vec3b>(row, col);
            cv::Vec3b pix_gpu = gpu_resized_patch.at<cv::Vec3b>(row, col);
            if(pix_cpu[0] != pix_gpu[0] ||  pix_cpu[1] != pix_gpu[1] || pix_cpu[2] != pix_gpu[2])
            {
                std::cout  << " col: " << col << " row: " << row 
                           << " diff: " << pix_cpu[0]- pix_gpu[0] 
                           << " " << pix_cpu[1]- pix_gpu[1] 
                           << " " << pix_cpu[2]- pix_gpu[2] 
                           << std::endl;
                misMatchCnt++;
            }
        }
    }

    std::cout  << " mismatch " << misMatchCnt / (cpu_resized_patch.size().height*cpu_resized_patch.size().width) * 100 << " %" << std::endl;

===================================================================

Output:


OPENCV RESIZE GPU/CPU compare ...
 col: 0 row: 0 diff: 1 1 1
 col: 1 row: 0 diff: 1 1 1
 col: 2 row: 0 diff: 1 1 1
 col: 3 row: 0 diff: 1 1 1
 col: 4 row: 0 diff: 1 1 1
 col: 5 row: 0 diff: 1 1 1
 col: 6 row: 0 diff: 1 1 1
 col: 7 row: 0 diff: 1 1 1
 col: 8 row: 0 diff: 1 1 1
 col: 9 row: 0 diff: 1 1 1
...
 col: 4 row: 9 diff: 1 1 1
 col: 5 row: 9 diff: 1 1 1
 col: 6 row: 9 diff: 1 1 1
 col: 7 row: 9 diff: 1 1 1
 col: 8 row: 9 diff: 1 1 1
 col: 9 row: 9 diff: 1 1 1

 mismatch 100 %

History

Alexander Smorkalov on 2014-04-30 19:11
-   Assignee set to Vladislav Vinogradov
-   Category set to gpu (cuda)
Dmitry Retinskiy on 2014-05-29 06:36
Hi Vlad,

could you check this and say your opinion?
Thanks.
-   Affected version changed from 2.4.8 (latest release) to 2.4.0 -
    2.4.8
-   Status changed from New to Open

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 29 (3 by maintainers)

Most upvoted comments

any update?

Before I left NVIDIA I did escalate this to the NPPI team, doesn’t look like anything came of it!

Hackathon findings on the problem: The issue is reproducible with OpenCV 3.4.10 and 4.3.0 (contrib master) too. The implementation of cv::cuda::resize with linear interpolation does not use NPP and is aligned with GPU texture unit implementation to reuse it for some cases. The implementation is not the same as OpenCV uses for CPU kernels and it leads to different results. CUDA implementation has test ResizeSameAsHost.Accuracy, but it’s not instantiated for linear interpolation intentionally.