Is Laplacian of Gaussian for blob detection or for

2020-02-05 09:23发布

问题:

The following code is provided from (was asked to remove the link). But I was wondering how it exactly works. I was confused if this was considered edge detection or blob detection, as Wikipedia list the Laplacian of Gaussian (LoG) as blob detection.

Also, could somebody explain and provide a deeper explanation for why the absolute value is calculated and what is going on in the focus_stack() function?

#   Compute the gradient map of the image
def doLap(image):

    # YOU SHOULD TUNE THESE VALUES TO SUIT YOUR NEEDS
    kernel_size = 5         # Size of the laplacian window
    blur_size = 5           # How big of a kernal to use for the gaussian blur
                            # Generally, keeping these two values the same or very close works well
                            # Also, odd numbers, please...

    blurred = cv2.GaussianBlur(image, (blur_size,blur_size), 0)
    return cv2.Laplacian(blurred, cv2.CV_64F, ksize=kernel_size)

#
#   This routine finds the points of best focus in all images and produces a merged result...
#
def focus_stack(unimages):
    images = align_images(unimages)

    print "Computing the laplacian of the blurred images"
    laps = []
    for i in range(len(images)):
        print "Lap {}".format(i)
        laps.append(doLap(cv2.cvtColor(images[i],cv2.COLOR_BGR2GRAY)))

    laps = np.asarray(laps)
    print "Shape of array of laplacians = {}".format(laps.shape)

    output = np.zeros(shape=images[0].shape, dtype=images[0].dtype)

    abs_laps = np.absolute(laps)
    maxima = abs_laps.max(axis=0)
    bool_mask = abs_laps == maxima
    mask = bool_mask.astype(np.uint8)
    for i in range(0,len(images)):
        output = cv2.bitwise_not(images[i],output, mask=mask[i])

    return 255-output

回答1:

EDIT: Cris Luengo is right. Ignore the part about edge detector.


Laplacian of Gaussian(LoG) can be used as both edge detector and blob detector. I will skip the detailed mathematics and rationale, I think you can read them on a book or some websites here, here and here.

To see why it can be used as both, let's look at its plot and kernel.

If you have a blob with radius of 3 and value 1 centered at the kernel, and the background has value 0, you will have a very strong (negative) response. It is clear why it can do blob detection if the radius is set properly.

How about edge detection? Well it is not like Sobel operator which gives you gradient and strong response for edges. Sobel operator does not give you accurate edges as the gradient usually rise and fall across a few pixels. Your edge would then be several pixels wide. To make it localize more accurate, we can find the pixel with maximum (or minimum) gradient locally. This implies its second derivative (Laplacian) should equal zero, or has a zero-crossing at that point.

You can see the processed image has both a light and dark band. The zero-crossing is the edge. To see this with a kernel, try sliding a perfect step edge across the kernel manually to see how the respond changes.

For you second question, I guess the absolute is trying to find both light and dark blob (light blob, dark background; dark blob, light background) as they gives strong negative and strong positive response respectively. It then find the max across all images at each pixel location. For each output pixel, it uses the pixel at the image with the maximum response as output. I think his rationale is that pixels with strong impulse (small blob) are in-focus.

He is using bitwise_not as a copy mechanism. It sets some pixels, specified by the mask, to the bitwise not of the source image. At the end, you would have output consisting of pixels from different sources, except that all of them have undergone bitwise not. To recover the true image, simply 'NOT' them again, as NOT(NOT(x)) = x. 255-x does exactly that. I think a copyTo would work too, not sure why he chose otherwise.

Images taken from http://fourier.eng.hmc.edu/e161/lectures/gradient/node8.html.



回答2:

hkchengrex's answer is fairly complete, but I don't completely agree. Maybe I'm a bit of a stickler for correct nomenclature. A detector is something that yields a strong response at the location of the thing to be detected.

The Laplacian of Gaussian (LoG) is not an edge detector, since it has zero crossings at (near*) edges. But it can be used to construct an edge detector. The edge detector so constructed is the Marr-Hildreth edge detector. Because of this, it often gets classified under edge detectors. To me, it's a line detector.

The Laplace is the sum of second derivatives (the trace of the Hessian matrix). An image convolved with the LoG is the same as the Laplacian of an image convolved with a Gaussian:

img * [ d^2/dx^2 G(x,y) + d^2/dy^2 G(x,y) ] = d^2/dx^2 [ img * G(x,y) ] + d^2/dy^2 [ img * G(x,y) ]

Thus, the LoG yields a strong response at extrema in the image (where the second derivative is maximal). This happens at the peaks of "blobs", and along the ridges of lines.

Let's take this simple test image:

and apply the LoG to it:

Here, mid-gray are pixels with a value of 0. As can be seen, it has strong (negative) response along the thin line and on the small dots. It also has medium responses around the edges of the wider objects (negative inside the edge, positive outside); the zero crossings are close to where the edges are.

We can threshold this image to detect the thin line and the dots:

(thresholding the magnitude yields the same result). We can lower the threshold to see that medium responses happen around edges of interest:

It takes more than a simple threshold to obtain edges. In contrast, the gradient magnitude (first derivatives are strong at the location of edges) can be thresholded to obtain edges:

The gradient magnitude is not useful to detect lines, as it detects the two edges along the lines, rather than the line itself. The gradient magnitude above is computed using Gaussian derivatives (Sobel is another option, but not as precise).

Note that the Canny edge detector is based on the gradient magnitude, it adds non-maximum suppression and hysteresis thresholding to make the detections thin and meaningful.


* The second derivative has a zero crossing at the inflection points (which can be taken as the true location of edges). However, the Laplacian is the sum of second derivatives. If you think of the second derivative in the direction of the gradient, its zero crossing will be well localized. But now add the second derivative in the perpendicular direction (along the edge). This second derivative will be zero along a straight edge, negative along a convex curved edge (e.g. the edge of a circle), and positive along a concave curved edge. Adding these two values will therefore cause the zero crossings to shift on curved edges, the stronger the curvature, the more the zero crossing will deviate from its true location.