I am currently trying to filter an image with a Laplacian kernel that I have constructed myself. However, when filtering an input image with this kernel it gives an unexpected result compared to the implementation in SciPy.
The Laplacian kernel I have constructed should be verified by the following images

The code for filtering the image:
im = cv2.imread("test.png",0)
im = im.astype(np.float32)
def lkern(t=1.):
ax = np.arange(np.round(-5*np.sqrt(t),0),np.round(5*np.sqrt(t),0)+1)
xx, yy = np.meshgrid(ax, ax)
kernel = -1/(np.sqrt(2*np.pi*t)*t)*np.exp(-(xx**2+yy**2)/(2*t))+
(xx**2+yy**2)/(np.sqrt(2*np.pi*t)*t**2)*np.exp(-(xx**2+yy**2)/(2*t))
return kernel.astype(np.float)
t = 25**2/2
l = lkern(t)
L = cv2.filter2D(im/255,-1,l)
plt.figure()
plt.imshow(L,cmap="gray")
plt.show()
which results in

Comparing to SciPy's ndimage.gaussian_laplace, the result should have been

which is very different, and I cannot figure out how to do this properly.
The code in the OP seems to take the equation for a 1D Laplace of Gaussian and use that to construct a 2D radially symmetric function. That is, along any of the diameters of the kernel the function looks like a 1D Laplace of Gaussian. This is not the correct way to create a 2D Laplace of Gaussian.
The Laplace of Gaussian is defined as the sum of the second order derivative of the Gaussian kernel along each of the axes. That is,
With
Gthe Gaussian kernel.With Numpy, you can construct this kernel as follows. I'm using the separability of the Gaussian to reduce the computational complexity.
Tricks here:
gandd2gare 1D functions.g[:,None]turns the 1D function on its side, so that the multiplication causes broadcasting, leading to a 2D output.I have written the kernel this way, rather than expressing the full 2D equation in one go, because this leads to large efficiencies in your code: The convolution of an image
fwith the kernellogcan be written as:That is, instead of one convolution with a large 2D kernel, we compute 4 convolutions with relatively small 1D kernels. Note that the actual order here does not matter:
gand on the result a 1D kerneld2galong the other axis. These two operations can be reversed.(It is OK to use
cv2.filter2Dwhere I wroteconv.convjust indicates any convolution function, but a correlation function likefilter2Dis fine because the kernels are all symmetric.)