I am new to image processing, please forgive me if you find the question too simple.
I was trying to replace ndimage.convolve()
with cv2.filter2D()
function for convolution.
Here is the original code
ndimage.convolve(Gxx,f,origin=0)
Here is the replace function
cv2.filter2D(Gxx,-1,cv2.flip(f,-1),borderType=cv2.BORDER_REFLECT,anchor=(-1,-1))
Both of the code return different values, I try to play around with the parameter at ndimage.convolve
and set origin to -1 then it return the exact result as the cv2.filter2D
but this is not what I want, since I want ndimage.convolve to use the default origin which is zero.
After I study the opencv documentation again on filter2D
I realize that
The filtering function actually calculates correlation. If you have a symmetrical convolution kernel, the mathematical expressions for correlation and convolution are the same.
If the kernel is not symmetric, you must flip the kernel and set the anchor point to (kernel.cols - anchor.x - 1, kernel.rows - anchor.y - 1). This will calculate the actual convolution.
So I flip the kernel with cv2.flip(f,-1)
in both direction, but I don't know how to calculate the new anchor point after flip the kernel, according to the documentation, I need to set anchor point to (kernel.cols - anchor.x - 1, kernel.rows - anchor.y - 1)
. I guess kernel.col
s and kernel.rows
is the kernel size in both direction but what does anchor.x
and anchor.y
means here? Is it original anchor point of the kernel? Assume the kernel is 42 X 42, what will be the new anchor point? Thanks in advance.
The anchor of a filter is typically at its center. So, for a 3x3 filter it is (1, 1) when indexing from zero. For example, a simple edge filter:
1 0 -1
1 0 -1
1 0 -1
It makes sense that the anchor is at the center (1, 1) because when the convolution is applied for a specific point in the image, it computes the difference between the points to the left and to the right in its direct neighborhood.
Now let's look at your 42x42 kernel. For 41x41 the center would be (20, 20) and for 43x43 it would be (21, 21).
The kernel 42x42 has even side lengths which makes it asymmetrical. This is one of the reasons why kernels with odd side lengths are preferred.
For a filter kernel like this, the anchor is shifted from the center to the next valid coordinate. For example, a 4x4 kernel has it's center at (1.5, 1.5) and anchor at (2, 2), accordingly.
So in your case of a 42x42 kernel, the anchor would be shifted to (21, 21) from center (20.5, 20.5). If you flip the kernel, the anchor needs to be flipped as well: in a point-wise symmetry with the center at (20.5, 20.5), to (20, 20). This is also the result of the given formula kernel.cols - anchor.x - 1:
42 - 21 - 1 = 20