Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does filter2D in opencv really do its job?

I am doing something about convolving images in Python and for sake of speed I chose opencv 2.4.9.

Opencv offers a way called filter2D to do this and here's its docs: http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=filter2d#filter2d

In docs, it says:

Convolves an image with the kernel.

But I have doubts(caused by something else) so I make some experiments on it:

First, I make a normal 3x3 matrix a using numpy as:

  [[ 1.,  5.,  0.], 
   [ 7.,  2.,  9.], 
   [ 2.,  3.,  4.]]

Then, I make a 2x2 matrix b as the kernel as:

>>> b

  [[ 1.,  2.],
   [ 3.,  4.]]

Finally, in order to make it clear to see difference between convolve and correlate, rotate b by 180 degree and b will look like:

  [[ 4.,  3.],
   [ 2.,  1.]]

Now, All pre-work is done. We could begin the experiment.

Step 1. Use scipy.ndimage.convolve: ndconv = ndimage.convolve(a, b, mode = 'constant') and ndconv is:

  [[ 35.,  33.,  18.],
   [ 41.,  45.,  44.],
   [ 17.,  24.,  16.]]

Convolution op will rotate b by 180 degree and do correlation using b on a. So ndconv[0][0] = 4*1+3*5+2*7+1*2 = 35, and ndconv[2][2] = 4*4+3*0+2*0+1*0 = 16

This result is correct.

Step 2. Use scipy.ndimage.correlate: ndcorr = ndimage.correlate(a, b, mode = 'constant') and ndcorr is:

  [[  4.,  23.,  15.],
   [ 30.,  40.,  47.],
   [ 22.,  29.,  45.]]

According to correlation's definition, ndcorr[0][0] = 1*0+2*0+3*0+4*1 = 4 because the border will expand by 0.

(Someone may be confused by the expandation's difference between conv and corr. It seems convolve expand image in directions right and down while correlate in directions left and up.)

But this is not the point.

Step 3. Use cv2.filter2D: cvfilter = cv2.filter2D(a, -1, b) and cvfilter is:

  [[ 35.,  34.,  35.],
   [ 41.,  40.,  47.],
   [ 33.,  29.,  45.]]

If we ignore the border cases, we will find that what cv2.filter2D did is actually a correlation other than a convolution! How could I say that?

because cvfilter[1..2][1..2] == ndcorr[1..2][1..2].

WEIRD, isn't it?

Could anyone be able to tell the real thing that cv2.filter2D do? Thanks a lot.

like image 525
Lancelod Liu Avatar asked Nov 11 '14 05:11

Lancelod Liu


2 Answers

If you read a bit further down in the description in the OpenCV documentation:

The function does actually compute correlation, not the convolution:

OpenCV filter2d() formula

That is, the kernel is not mirrored around the anchor point. If you need a real convolution, flip the kernel using flip() and set the new anchor to (kernel.cols - anchor.x - 1, kernel.rows - anchor.y - 1).

like image 51
beaker Avatar answered Sep 30 '22 19:09

beaker


Well I think that's true for OpenCV. If you want real convolution according to Digital Image Processing theory, you should manually reverse the kernel prior to applying cv2.filter2D.

like image 31
Jake0x32 Avatar answered Sep 30 '22 17:09

Jake0x32