0

I am trying to write a class that uses the Laplacian of Gaussian for blob detection. Here is the class that I wrote:

import cv2 as cv
import numpy as np
from sklearn.preprocessing import normalize
from scipy import ndimage

class Blob:
        
    BlobStack = [[[[]]]]
    
    def _getLGKernel(self,sx,sy):
        kx = (int(sx - 0.8)*4+1)*2+1
        ky = (int(sy - 0.8)*4+1)*2+1    
        gaussKernelX = np.float32(cv.getGaussianKernel(kx,sx))
        gaussKernelY = np.float32(cv.getGaussianKernel(ky,sy))
        d2GaussKernelX = cv.Laplacian(gaussKernelX,cv.CV_32F)[1:kx-1]
        d2GaussKernelY = cv.Laplacian(gaussKernelY,cv.CV_32F)[1:ky-1]
        d2GaussKernelX = normalize(d2GaussKernelX,axis=0)
        d2GaussKernelY = normalize(d2GaussKernelY,axis=0)
        return d2GaussKernelX, d2GaussKernelY
    
    def __init__(self,img,mins,maxs,steps):
        step = int((maxs-mins)/steps)
        r = range(mins,maxs+step,step)
        self.BlobStack = np.zeros((np.size(r),np.size(r),np.shape(img)[0],np.shape(img)[1]),dtype= np.float32)
        for i,sx in enumerate(r):
            for j,sy in enumerate(r):
                kernx, kerny = self._getLGKernel(sx, sy)
                self.BlobStack[i,j] = np.abs(cv.filter2D(img,cv.CV_64F,kernx,borderType = cv.BORDER_REPLICATE) \
                                             +cv.filter2D(img,cv.CV_64F,np.transpose(kerny),borderType = cv.BORDER_REPLICATE))        
        return
    
    def findLocalBlobs(self,sz):
        LocalBlobs = np.where(ndimage.maximum_filter(self.BlobStack,size=sz) == self.BlobStack)
        LocalBlobs = np.asarray(LocalBlobs).transpose()
        return  LocalBlobs

Right now I am using a test case with two circles of various darkness on a white background. I am getting many extra blobs that shouldn't be there. Some are at the minimum or maximum kernel size but some are at other kernel sizes. There are kernel sizes, which are sometimes the max kernel size in one direction but not always, that have a constant value in a large region that it is detecting a local minimum at. It is lower than the value of the actual blobs I want to detect but still well above what could be a floating point error. A straight forward filtering by the value of the LoG doesn't work because some of the 'phantom' blobs have a higher value than the circle with the lower contrast to the background.

I am more interested in help from a theoretical image processing prospective as this is just a project that I am using to learn from, but any help would be appreciated.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • 3
    Please, provide your input images! – stateMachine Aug 17 '22 at 22:09
  • 1
    Yes, please show the input image as well as the output. It would be a lot easier to follow your description if we can also see the image. Right now, I do not understand what you describe is your output. – Cris Luengo Aug 17 '22 at 22:30
  • I do see a lot of issues in your code: `d2GaussKernelX` is cropped, it should go to zero at both ends (plot it!). Normalizing this kernel makes no sense, the Gaussian itself was normalized, here you have its second derivative. You convolve with two 1D LoG filters, which is imprecise at best, but possibly plain wrong. You compute the magnitude of the result, where the sign matters. See [here](https://stackoverflow.com/a/53665075/7328782) for two ways to implement the 2D LoG filter. – Cris Luengo Aug 17 '22 at 22:38

0 Answers0