filter2D Question

I am trying to convert some OpenCV code I wrote to Matlab and ran into some problems with filter2D. I do not think I fully understand how filter2D works. I tried implementing the function using the equation given in the docs:

I think I must be missing something though because my Matlab code result does not match the filter2D result :( For input mat = [1 2 3; 4 5 6; 7 8 9] and kernel = [1 1 1; 1 1 1; 1 1 1], I get in Matlab result mat = [21, 27, 33; 39, 45, 51; 57, 63, 69] and in OpenCV result mat = [34, 37, 40; 43, 46, 49; 52, 55, 58]

For OpenCV I use filter2D(src, dst, -1, ker, Point(-1,-1), BORDER_REPLICATE)

Here is my Matlab code (I assume BORDER_REPLICATE (Matlab is missing a corresponding BORDER_REFLECT and (more importantly) BORDER_REFLECT_101 padding) and default anchor):

% X - input image
% kernel - convolution kernel (or rather a correlation kernel), a single-channel floating point matrix

function Y = filter_2D(X, kernel)

[k_rows, k_cols] = size(kernel);
[x_rows, x_cols] = size(X);

Y = zeros(x_rows, x_cols);

% Assume padding used in OpenCV is BORDER_REPLICATE aaaaaa|abcdefgh|hhhhhhh

for r = 1:x_rows
for c = 1:x_cols
Y(r,c) = sum(sum(kernel .* X_pad(r:r+k_rows-1, c:c+k_cols-1)));
end
end

end


Can someone point out what I am doing wrong/need to change? Thanks!

UPDATE: My code works correctly for the test case LBerger has given. So the error must be in my understand of filter2D padding?

Here is some OpenCV test results to illustrate what I am doing and where things go wrong:

My Matlab code matches up until the dst result. Does the padding shown match how filter2D will pad the matrix? Is it is the correct filter2D padding, how is the first 34 value being calculated by filter2D?

edit retag close merge delete

1

use a Mat(7,7) to test with :

[0 0 0 0 0 0 0; 0 0 0 0 0 0 0;0 0 1 2 3 0 0;0 0 4 5 6 0 0;0 0 7 8 9 0 0;0 0 0 0 0 0 0;0 0 0 0 0 0 0]

there is no border effect with a 3X3 kernel (all borders effect are 0)

( 2018-02-20 08:00:21 -0500 )edit

My code works for the test case. It still does not work for the example in the question though :( Please see updated question

( 2018-02-20 11:19:36 -0500 )edit

Sort by ยป oldest newest most voted

Here my code to understand BORDER_REPLICATE :

void main(void)
{
Mat x = (Mat_<float>(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
Mat x7 = (Mat_<float>(7, 7) << 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 0, 0, 1, 1, 2, 3, 3, 0, 0, 4, 4, 5, 6, 6, 0, 0, 7, 7, 8, 9, 9, 0, 0, 7, 7, 8, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0);
Mat kernel = (Mat_<float>(3, 3) << 1, 1, 1, 1, 1, 1, 1, 1, 1);
Mat dst;

filter2D(x, dst, -1, kernel, Point(-1, -1), 0, BORDER_REPLICATE);
cout << "*************BORDER_REPLICATE *******************\n"<<dst << "\n";
cout << "\n data for BORDER_REPLICATE are \n";
cout << x7<<"\n";
cout << "*************Filter2d for x7 *******************\n" << dst << "\n";
filter2D(x7, dst, -1, kernel, Point(-1, -1), 0, BORDER_ISOLATED);// Don't use BORDER_REPLICATE
cout << dst << "\n";

}


and results :

*************BORDER_REPLICATE *******************
[21, 27, 33;
39, 45, 51;
57, 63, 69]

data for BORDER_REPLICATE are
[0, 0, 0, 0, 0, 0, 0;
0, 1, 1, 2, 3, 3, 0;
0, 1, 1, 2, 3, 3, 0;
0, 4, 4, 5, 6, 6, 0;
0, 7, 7, 8, 9, 9, 0;
0, 7, 7, 8, 9, 9, 0;
0, 0, 0, 0, 0, 0, 0]
*************Filter2d for x7 *******************
[21, 27, 33;
39, 45, 51;
57, 63, 69]
[1, 2, 4, 6, 8, 6, 3;
2, 4, 8, 12, 16, 12, 6;
6, 12, 21, 27, 33, 24, 12;
12, 24, 39, 45, 51, 36, 18;
18, 36, 57, 63, 69, 48, 24;
14, 28, 44, 48, 52, 36, 18;
7, 14, 22, 24, 26, 18, 9]

more

2

I am soooo stupid. I did not enter an argument for the filter2D delta parameter!!! Thank you for your help!!

( 2018-02-20 11:52:23 -0500 )edit
1

@phillity mark it solved, then. (green hook)

( 2018-02-20 11:58:23 -0500 )edit