MATLAB vs C++ vs OpenCV - imresize

Posted

技术标签:

【中文标题】MATLAB vs C++ vs OpenCV - imresize【英文标题】: 【发布时间】:2014-11-08 00:25:43 【问题描述】:

我有以下要传输到 C++ 中的 MATLAB 代码

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

Gr = imresize(Gr, 1 / newScale);

在the MATLAB documentation:

B = imresize(A, scale) 返回图像 B 的大小乘以 A. 输入图像 A 可以是灰度、RGB 或二值图像。如果 scale 介于 0 和 1.0 之间,B 小于 A。如果 scale 更大 大于 1.0,B 大于 A。

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

我找不到相同的 C++ 示例代码。您能否提供此类代码的链接?

我还找到了this OpenCV function, resize

它和 MATLAB 做的一样吗?

【问题讨论】:

根据 MA​​TLAB 文档,bicubic 是默认的插值方法。如果您想在 OpenCV 中获得相同的效果,请在 resize 函数中指定 INTER_CUBIC @Amro 您还必须关闭抗锯齿以匹配 OpenCV 啊,好观察 类似问题:***.com/q/22092744/97160 【参考方案1】:

是的,请注意 MATLAB 的 imresize 有 anti-aliasing enabled by default:

imresize(A,scale,'bilinear')

对比没有抗锯齿功能的cv::resize() 会得到什么:

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

正如 Amro 所说,MATLAB 中的默认值是bicubic,所以一定要指定。

双线性

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

OpenCV sn-p 示例:

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

请注意,关闭抗锯齿的结果是一样的。

双三次差

但是,在'bicubic'INTER_CUBIC 之间,由于加权方案的原因,结果是不同的! See here 了解数学差异的详细信息。问题出在计算三次插值系数的interpolateCubic() 函数中,其中使用了常数a = -0.75,而不是像MATLAB 中的a = -0.5。但是,如果您编辑 imgwarp.cpp 并更改代码:

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 模块以缩短编译时间),然后您会得到相同的结果:

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]

更多关于立方HERE.

【讨论】:

我需要一些精确的东西,所以我应该尝试自己实现它吗? @Gilad 对于双线性,只需使用 OpenCV。对于双三次,我想你必须自己滚动。 这是我在 OpenCV 和 MATLAB 之间切换时遇到的最大问题之一。该死的抗锯齿!大约一个月前,你以前的帖子救了我。谢谢顺便说一句! @rayryeng 使用cubic,需要修改OpenCV中的imgwarp.cpp以获得匹配的结果。 Amro and I have been hammering away 在我们自己的娱乐问题上。 :) @Gilad 是的,在 BSD 许可证下打开,这是非常宽松的。您还可以从其他地方获取三次插值代码,并验证它是否使用相同的常数并且方程式的计算方式相同。例如,您可以更改 cubicInterpolate 的 paulinternet.nl 实现中的等式,您发现对应的系数正确。 (该函数结合了系数和求和)。【参考方案2】:

在 OpenCV 中,调用是:

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

然后您可能需要进行一些平滑/模糊来模拟 MATLAB 默认执行的抗锯齿(请参阅@chappjc 的回答)

【讨论】:

有关 MATLAB 的 imresize 的相关帖子:***.com/a/7759981/97160(也可以查看链接帖子) 我用bilinear 的示例更新了我的帖子,但无论抗锯齿设置如何,我都无法使用bicubic 获得相同的结果。你知道这是怎么回事吗?等等...刚刚看到your link。这就解释了! @Amro 你能看看这里吗***.com/questions/27851389/…

以上是关于MATLAB vs C++ vs OpenCV - imresize的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV vs MATLAB(图像处理的形状测量功能)

Opencv介绍及opencv3.0在 vs2010上的配置

OpenCV 图像处理——C++ vs C vs Python

如何将 vs2008 c++ OpenCV dll 构建到 vs2008 C#?

OpenCV VS 2010 C++ CMake

C++ opencv配置 Vs2019和Clion