简体   繁体   English

Opencv平均滤波器提供的输出与Matlab平均滤波器不同

[英]Opencv average filter gives different output than Matlab average filter

The following OpenCV code is written to serve as a diagnostic to compare average filter implementation in Matlab and OpenCV. 编写以下OpenCV代码作为诊断来比较Matlab和OpenCV中的平均滤波器实现。 The OpenCV code is 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;  

The output is 输出是

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 code to replicate the same operation is : 用于复制相同操作​​的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');

The output is 输出是

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

What is the reason for discrepancy between the two outputs ? 两个产出之间出现差异的原因是什么?

The difference you are seeing is due to the different choice of where the origin within the even-sized filter is. 您所看到的差异是由于在偶数尺寸滤波器中的原点的不同选择。 For odd-sized kernels, software tends to be consistent and pick the middle pixel as the origin. 对于奇数大小的内核,软件往往是一致的,并选择中间像素作为原点。 But for even-sized kernels there are two choices that make equal sense. 但对于偶数大小的内核,有两种选择具有同等意义。

I can replicate the OpenCV output in MATLAB by changing the origin of the filter: 我可以通过更改过滤器的原点来复制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')

This gives me the same U as you had: 这给了我和你一样的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

And the V is what you saw in OpenCV: 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

More instructive is creating an input that is all zeros except for one value in the middle: 更有启发性的是创建一个全零的输入,除了中间的一个值:

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')

Now I see: 现在我明白了:

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

Here it is clear that the kernel was shifted by one pixel. 很明显,内核移动了一个像素。 Again, with fspecial('average',[2 2]) you'd get the result of U , and if you replicate this in OpenCV you'll see an output like V . 同样,使用fspecial('average',[2 2])你会得到U的结果,如果你在OpenCV中复制它,你会看到像V这样的输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM