Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
505 views
in Technique[技术] by (71.8m points)

MATLAB vs C++ vs OpenCV - imresize

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

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

Gr = imresize(Gr, 1 / newScale);

in the MATLAB documentation:

B = imresize(A, scale) returns image B that is scale times the size of A. The input image A can be a grayscale, RGB, or binary image. If scale is between 0 and 1.0, B is smaller than A. If scale is greater than 1.0, B is larger than A.

So this means I will get a 2D matrix == matrix_width/2 and matrix_height/2
How do I calculate the values? The default according to the docs are coming from cubic interpolation for nearest 4X4.

I can't find a sample code for C++ that does the same. Can you please provide a link to such code?

I also found this OpenCV function, resize.

Does it do the same as the MATLAB one?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...