编写以下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
两个输出之间出现差异的原因是什么?
答案 0 :(得分:2)
您看到的差异是由于偶数尺寸滤镜中原点的选择不同。对于奇数大小的内核,软件往往是一致的,并选择中间像素作为原点。但对于偶数大小的内核,有两种选择具有同等意义。
我可以通过更改过滤器的原点来复制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
的输出。