c++ - 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. The OpenCV code is
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 :
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 ?
解决方案
您看到的差异是由于对均匀大小过滤器中原点位置的不同选择。对于奇数大小的内核,软件倾向于一致并选择中间像素作为原点。但对于偶数大小的内核,有两种选择同样有意义。
我可以通过更改滤波器的原点来复制 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
。
推荐阅读
- xpath - How to skip paragraphs with comments in XPath expression?
- java - 未读取外部 Spring 引导属性
- c# - 如何使用变量值来引用另一个变量或对象(即其他语言中的 EVAL)
- tensorflow - 在 raspberry pi3 上安装 TensorFlow 期间出现 HadoopFileSystem 加载错误
- highcharts - Display Date and time on highcharts
- javascript - XY 图表使用数据源动态排列系列
- php - 如何获取我刚刚添加到商店功能中的用户 ID() Larevel 6.0
- java - 即使我的课程是公开的,Intellij 也无法解析符号
- python - 我该如何解决这个错误:没有足够的值来解包(预期 4,得到 1)
- ffmpeg - avcodec_find_encoder_by_name() 返回 NULL