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 做的一样吗?
【问题讨论】:
根据 MATLAB 文档,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介绍及opencv3.0在 vs2010上的配置
OpenCV 图像处理——C++ vs C vs Python