1

I need to convert the following matlab code into OpenCV and obtain exactly the same result.

In matlab:

A = [1 2 3];
f = [4 5 6];
result = filter2(f, A);

This gives out as:

result = [17    32    23]

In OpenCV, I tried these lines:

cv::Mat A = (cv::Mat_<float>(1, 3) << 1, 2, 3);
cv::Mat f = (cv::Mat_<float>(1, 3) << 4, 5, 6);
cv::Mat result;
cv::filter2D(A, result, -1, f, cv::Point(-1, -1), 0, cv::BORDER_REPLICATE);

This gives me:

result = [21 32 41]

How can I obtain the same result as of Matlab?? I doubt the anchor point in OpenCV causes this difference, but I cannot figure out how to change it. Thanks in advance.

E_learner
  • 3,512
  • 14
  • 57
  • 88
  • The `ddepth` parameter you have kept as -1 i.e. same as src, have you tried changing to `CV_64F`? – ha9u63a7 Mar 23 '15 at 14:44
  • I tried, but it gives me error saying 'unsupported combination of source format (=5) and destination format (=6) ... '. – E_learner Mar 23 '15 at 14:56

1 Answers1

8

Use cv::BORDER_CONSTANT, which pads the array with zero rather than duplicating the neighboring element:

cv::filter2D(A, result, -1, f, cv::Point(-1, -1), 0, cv::BORDER_CONSTANT);

Result is:

result = [17, 32, 23]
beaker
  • 16,331
  • 3
  • 32
  • 49
  • That's exactly what I was going to post. +1. – rayryeng Mar 23 '15 at 15:46
  • @rayryeng Thanks, I wish I could come up with some documentation to back up this observation, but it is seriously lacking on both the Matlab and OpenCV side. :( – beaker Mar 23 '15 at 15:47
  • 1
    For MATLAB, it *kind of* implies that the borders are zero-filled: http://www.mathworks.com/help/matlab/ref/filter2.html. If you look at the `valid` flag, it tells you that it does zero-pad the borders, but it doesn't actually tell you that it's doing it outside of the `valid` flag. My guess is it actually is regardless of what flag you use, and depending on the flag, some elements are discarded. Zero-padding is still done though. For OpenCV: http://docs.opencv.org/modules/imgproc/doc/filtering.html#filter2d - It tells you that the default is `BORDER_DEFAULT`, which does do zero-padding. – rayryeng Mar 23 '15 at 15:54
  • @rayryeng I see what you mean about the `valid` flag for Matlab, but if I use `BORDER_DEFAULT` I get `[25, 32, 35]` which would mean it's getting padded with `2` for some reason? The only place that I could find that states `BORDER_CONSTANT` pads with zero was in the tutorial here: http://docs.opencv.org/doc/tutorials/imgproc/imgtrans/copyMakeBorder/copyMakeBorder.html – beaker Mar 23 '15 at 16:19
  • Oops... I thought `BORDER_DEFAULT` does zero-padding. yikes. I hate OpenCV documentation because it's inconsistent, and it makes you jump over hoops just to figure out what one flag means!... and even then it's not reliable! – rayryeng Mar 23 '15 at 16:26
  • btw, after trying 'cv::BORDER_CONSTANT', the result is in reverse order, as [23 32 17]. – E_learner Mar 24 '15 at 07:07
  • @E_learner Interesting. I used the exact code from your question and only changed to `cv::BORDER_CONSTANT` and just confirmed that I get the answer in the proper order, `[17 32 23]`. One thing that might cause the reverse order is if you reverse the array and filter. Can you double-check your code? – beaker Mar 24 '15 at 15:11
  • Just realized my comment might be a bit unclear. When I say reverse, I mean reverse the order of `A` and `f` in the argument list like `cv::filter2d(f, ..., A, ...)` rather than what I've used which is `cv::filter2d(A, ..., f, ...)`. – beaker Mar 24 '15 at 19:50
  • @beaker: yes, you're right. Now it gives me exactly the same result :) Thank you. – E_learner Mar 25 '15 at 07:07