c++ - Opencv 平均滤波器给出与 Matlab 平均滤波器不同的输出

标签 c++ matlab opencv image-processing

编写以下 OpenCV 代码用作诊断,以比较 Matlab 和 OpenCV 中的平均滤波器实现。 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

两个输出之间存在差异的原因是什么?

最佳答案

您看到的差异是由于对均匀大小过滤器中原点位置的不同选择。对于奇数大小的内核,软件倾向于保持一致并选择中间像素作为原点。但对于大小均匀的内核,有两种选择具有同等意义。

我可以通过更改过滤器的原点在 MATLAB 中复制 OpenCV 输出:

ma = repmat((0:4).',1,5);
filt = zeros(3);
filt(2:3,2:3) = 1/4;
U = imfilter(ma,filt,'replicate')
filt = rot90(filt,2);
V = imfilter(ma,filt,'replicate')

这给了我和你一样的U:

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

V 就是您在 OpenCV 中看到的:

V =
         0         0         0         0         0
    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

更有启发性的是创建一个全为零的输入,除了中间的一个值:

ma = zeros(5);
ma(3,3) = 1;
filt = zeros(3);
filt(2:3,2:3) = 1/4;
U = imfilter(ma,filt,'replicate')
filt = rot90(filt,2);
V = imfilter(ma,filt,'replicate')

现在我明白了:

U =
         0         0         0         0         0
         0    0.2500    0.2500         0         0
         0    0.2500    0.2500         0         0
         0         0         0         0         0
         0         0         0         0         0

V =
         0         0         0         0         0
         0         0         0         0         0
         0         0    0.2500    0.2500         0
         0         0    0.2500    0.2500         0
         0         0         0         0         0

这里很明显内核移动了一个像素。 同样,使用 fspecial('average',[2 2]) 你会得到 U 的结果,如果你在 OpenCV 中复制它,你会看到一个输出像 V

关于c++ - Opencv 平均滤波器给出与 Matlab 平均滤波器不同的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50501491/

相关文章:

c++ - 在c++中使用RGBtoHSV转换函数后如何显示HSV图像?

matlab - Matlab/Python 中的人脸识别

class - Matlab 函数/类历史

c++ - 是否可以通过模板指定抽象类变量类型?

c++ - boolean 值的排序

c++ - Windows 上的 GNU GSL 和 MATLAB

python - cv2 Python 图像混合 "Fade"过渡

c++ - C++ 中的 Grassfire 算法

C++ 实现从抽象模板派生的模板

c++ - 您如何使用任何 Boost 多精度库类型找到两个非常大的数字的模逆? (cpp_int、gmp_int 等)