MATLAB vs C++ vs OpenCV - imresize

我有以下 MATLAB 代码,我想将其传输到 C++

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

假设 Gr 是二维矩阵并且 1/newscale == 0.5

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

Gr = imresize(Gr, 1 / newScale);

在 MATLAB 文档中:

B = imresize(A, scale) 返回图像 B 的缩放倍数A. 输入图像 A 可以是灰度、RGB 或二值图像.如果scale 在 0 到 1.0 之间,B 小于 A.如果 scale 更大小于 1.0,B 大于 A.

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.

所以这意味着我将得到一个二维矩阵 == matrix_width/2 和 matrix_height/2
我如何计算这些值?根据文档的默认值来自最近 4X4 的三次插值.

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.

我找不到执行相同操作的 C++ 示例代码.能否提供此类代码的链接?

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

我还发现 这个 OpenCV 函数,resize.

它和 MATLAB 的功能一样吗?

Does it do the same as the MATLAB one?

推荐答案

是的,请注意 MATLAB 的 imresize 有 默认启用抗锯齿:

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

imresize(A,scale,'bilinear')

对比你会用 cv::resize() 得到什么,它没有抗锯齿:

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

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

正如 Amro 提到的,MATLAB 中的默认值是 bicubic,所以一定要指定.

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

无需修改代码即可通过双线性插值获得匹配结果.

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

示例 OpenCV 代码段:

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;

输出 (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'INTER_CUBIC 之间,由于权重方案的原因,结果是不同的!参见此处,了解数学差异的详细信息.问题出在计算三次插值系数的 interpolateCubic() 函数中,其中使用常数 a = -0.75 而不是 a = -0.5 就像在 MATLAB 中一样.但是,如果您编辑 imgwarp.cpp 并更改代码:

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;
    ...

到:

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

并重建 OpenCV(提示:禁用 CUDA 和 gpu 模块以缩短编译时间),然后您会得到相同的结果:

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]

更多关于立方这里.

相关文章