MATLAB vs C++ vs OpenCV - imresize

前端 未结 2 1516
余生分开走
余生分开走 2020-11-29 09:49

I have the following MATLAB code which I want to transport into C++

Assume Gr is 2d matrix and 1/newscale == 0.5

Gr = imres         


        
相关标签:
2条回答
  • 2020-11-29 10:13

    Yes, just be aware that MATLAB's imresize has anti-aliasing enabled by default:

    imresize(A,scale,'bilinear')
    

    vs. what you would get with cv::resize(), which does not have anti-aliasing:

    imresize(A,scale,'bilinear','AntiAliasing',false)
    

    And as Amro mentioned, the default in MATLAB is bicubic, so be sure to specify.

    Bilinear

    No code modifications are necessary to get matching results with bilinear interpolation.

    Example OpenCV snippet:

    cv::Mat src(4, 4, CV_32F);
    for (int i = 0; i < 16; ++i)
        src.at<float>(i) = i;
    
    std::cout << src << std::endl;
    
    cv::Mat dst;
    cv::resize(src, dst, Size(0, 0), 0.5, 0.5, INTER_LINEAR);
    
    std::cout << dst << std::endl;
    

    Output (OpenCV)

    [0, 1, 2, 3;
      4, 5, 6, 7;
      8, 9, 10, 11;
      12, 13, 14, 15]
    
    [2.5, 4.5;
      10.5, 12.5]
    

    MATLAB

    >> M = reshape(0:15,4,4).';
    >> imresize(M,0.5,'bilinear','AntiAliasing',true)
    ans =
                         3.125                     4.875
                        10.125                    11.875
    >> imresize(M,0.5,'bilinear','AntiAliasing',false)
    ans =
                           2.5                       4.5
                          10.5                      12.5
    

    Note that the results are the same with anti-aliasing turned off.

    Bicubic Difference

    However, between 'bicubic' and INTER_CUBIC, the results are different on account of the weighting scheme! See here for details on the mathematical difference. The issue is in the interpolateCubic() function that computes the cubic interpolant's coefficients, where a constant of a = -0.75 is used rather than a = -0.5 like in MATLAB. However, if you edit imgwarp.cpp and change the code :

    static inline void interpolateCubic( float x, float* coeffs )
    {
        const float A = -0.75f;
        ...
    

    to:

    static inline void interpolateCubic( float x, float* coeffs )
    {
        const float A = -0.50f;
        ...
    

    and rebuild OpenCV (tip: disable CUDA and the gpu module for short compile time), then you get the same results:

    MATLAB

    >> imresize(M,0.5,'bicubic','AntiAliasing',false)
    ans =
                        2.1875                    4.3125
                       10.6875                   12.8125
    

    OpenCV

    [0, 1, 2, 3;
      4, 5, 6, 7;
      8, 9, 10, 11;
      12, 13, 14, 15]
    [2.1875, 4.3125;
      10.6875, 12.8125]
    

    More about cubic HERE.

    0 讨论(0)
  • 2020-11-29 10:17

    In OpenCV, the call would be:

    cv::Mat dst;
    cv::resize(src, dst, Size(0,0), 0.5, 0.5, INTER_CUBIC);
    

    You might then have to do some smoothing/blurring to emulate the anti-aliasing which MATLAB also performs by default (see @chappjc's answer)

    0 讨论(0)
提交回复
热议问题