You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV与Matlab均值滤波输出存在差异的原因探究

为什么OpenCV和Matlab的2x2均值滤波结果不一样?

咱们先从你给出的测试代码和输出入手,一步步拆解差异的原因:

测试代码与输出对比

OpenCV实现及结果

Mat P(Size(5,5),CV_64FC1,Scalar(0));
for(int i = 0; i < 5; i++) {
    for (int j = 0; j < 5 ; j++)
        P.at<double>(i,j) = i;
}
cout<<"Original Matrix is :"<<endl;
cout<<P<<endl;
Mat averageFilter(2,2,CV_64FC1,Scalar(0)),U;
averageFilter = cv::Scalar::all(1.0/(2*2));
filter2D(P, U, -1 , averageFilter, Point( -1, -1 ), 0, BORDER_REPLICATE );
cout<<"Filtered Matrix is :"<<endl;
cout<<U<<endl;

输出:

Original Matrix is :
[0, 0, 0, 0, 0;
 1, 1, 1, 1, 1;
 2, 2, 2, 2, 2;
 3, 3, 3, 3, 3;
 4, 4, 4, 4, 4]
Filtered Matrix is :
[0, 0, 0, 0, 0;
 0.5, 0.5, 0.5, 0.5, 0.5;
 1.5, 1.5, 1.5, 1.5, 1.5;
 2.5, 2.5, 2.5, 2.5, 2.5;
 3.5, 3.5, 3.5, 3.5, 3.5]

Matlab实现及结果

ma = [0 0 0 0 0;1 1 1 1 1;2 2 2 2 2;3 3 3 3 3;4 4 4 4 4];
MEANF = fspecial('average',[2 2]);
U = imfilter(ma, MEANF, 'replicate');

输出:

U =
    0.5000    0.5000    0.5000    0.5000    0.5000
    1.5000    1.5000    1.5000    1.5000    1.5000
    2.5000    2.5000    2.5000    2.5000    2.5000
    3.5000    3.5000    3.5000    3.5000    3.5000
    4.0000    4.0000    4.0000    4.0000    4.0000

核心差异原因:卷积核的锚点位置不同

这俩工具输出不一样的根本原因,是默认的卷积核锚点(也就是核与输出像素对齐的基准点)位置不同,直接导致了滑动窗口的计算范围不一样:

1. OpenCV的默认锚点逻辑

当你给filter2D传Point(-1,-1)时,OpenCV会把锚点设为核的几何中心。但对于2x2这种偶数尺寸的核,几何中心是(0.5, 0.5)(0索引),而锚点必须是整数坐标,所以OpenCV会向下取整到(0,0)——也就是核的左上角像素位置。

这就意味着:

  • 计算输出第一行时,滑动窗口的核会对齐到原始图像的第一行,由于边界模式是BORDER_REPLICATE,核需要的下方像素会直接复制第一行的内容,所以计算的是(0+0+0+0)/4 = 0,输出第一行保持0;
  • 计算输出最后一行时,核需要的上方像素会复制第四行的内容,所以是(3+3+4+4)/4 = 3.5,对应输出的最后一行。

2. Matlab的默认锚点逻辑

Matlab的imfilter对偶数尺寸的核,默认锚点是核的右下角(0索引下是(1,1))。也就是说,锚点会对齐到输出像素的位置,对应的输入窗口会覆盖当前输出位置的上方和左侧区域。

这就导致:

  • 计算输出第一行时,滑动窗口会取原始图像的第一行和第二行的内容(边界模式replicate不需要额外复制,因为第二行存在),计算(0+0+1+1)/4 = 0.5,输出第一行是0.5;
  • 计算输出最后一行时,滑动窗口需要的下方像素会复制第五行的内容,所以是(4+4+4+4)/4 = 4.0,对应输出的最后一行。

如何让两者输出一致?

如果你想让OpenCV的结果和Matlab对齐,只需要手动把filter2D的锚点设为Point(1,1)(对应2x2核的右下角)就行,修改后的调用代码如下:

filter2D(P, U, -1 , averageFilter, Point(1, 1), 0, BORDER_REPLICATE );

此时OpenCV的输出就会和Matlab完全一样了。


内容的提问来源于stack exchange,提问作者Harjatin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:08:30