高斯的拉普拉斯算子是用于斑点检测还是用于边缘检测?

时间:2018-07-18 21:20:49

标签: python python-3.x opencv image-processing computer-vision

提供以下代码(要求删除链接)。但是我想知道它是如何工作的。如果将其视为边缘检测或斑点检测,我会感到困惑,例如Wikipedia list the Laplacian of Gaussian (LoG) as blob detection

还可以有人解释并提供更深入的解释,说明为什么计算绝对值以及focus_stack()函数中发生了什么吗?

#   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

2 个答案:

答案 0 :(得分:8)

hkchengrex's answer相当完整,但我并不完全同意。也许我对正确的命名有点不满意。检测器是一种在被检测物体的位置产生强烈响应的物体。

高斯拉普拉斯算子(LoG)不是边缘检测器,因为它在(near * )边缘处具有零交叉。但是它可以用来构造边缘检测器。这样构造的边缘检测器是Marr-Hildreth edge detector。因此,它经常在边缘检测器下分类。对我来说,它是行检测器

拉普拉斯(Laplace)是二阶导数的和(Hessian矩阵的迹线)。用LoG卷积的图像与使用高斯卷积的图像的拉普拉斯算子相同:

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) ]

因此,LoG在图像的极值处产生强烈的响应(其中二阶导数最大)。这种情况发生在“斑点”的顶峰和沿线的山脊上。

让我们来看看这个简单的测试图像:

image with blocks, lines and dots

并对其应用LoG:

LoG of image above

此处,中间灰色是值为0的像素。可以看出,它沿细线和小点具有较强的(负)响应。它还在较宽物体的边缘周围具有中等响应(边缘内侧为负,外侧外侧为正);零交叉点靠近边缘。

我们可以对此图像进行阈值检测以检测细线和点:

LoG < 65

(将幅度阈值产生相同的结果)。我们可以降低阈值,以查看在感兴趣的边缘周围发生中等响应:

abs(LoG) < 20

要获得边缘,不仅需要简单的阈值。相比之下,可以对梯度幅度(一阶导数在边缘位置处较强)进行阈值化以获得边缘:

gradmag < 50

梯度量级对检测线无用,因为它检测沿线的两个边缘,而不是线本身。上面的梯度幅度是使用高斯导数计算的(Sobel是另一种选择,但不够精确)。

请注意,Canny edge detector是基于梯度幅度的,它添加了非最大抑制和磁滞阈值,从而使检测变得稀薄而有意义。


* 二阶导数在拐点处具有零交叉(可以视为边缘的真实位置)。但是,拉普拉斯算子是二阶导数的和。如果考虑梯度方向上的二阶导数,则其零交叉点将很好地定位。但是现在在垂直方向(沿边)上添加二阶导数。该二阶导数沿直线边缘为零,沿凸曲线边缘(例如,圆的边缘)为负,而沿凹曲线边缘为正。因此,将这两个值相加会导致零交叉点在弯曲边缘上移动,曲率越强,零交叉点偏离其真实位置的可能性就越大。

答案 1 :(得分:4)

编辑:Cris Luengo是正确的。忽略有关边缘检测器的部分。


高斯的拉普拉斯算子(LoG)可用作 边缘检测器和 blob检测器。我将跳过详细的数学和原理,我想您可以在书或某些网站hereherehere上阅读它们。

要了解为什么可以同时使用它,我们来看看它的图和内核。

enter image description here enter image description here

如果您有一个半径为3且中心位于内核的值为1的斑点,而背景的值为0,则将产生非常强的(负)响应。很明显,如果半径设置正确,为什么可以进行斑点检测。

边缘检测如何?嗯,它不像Sobel运算符那样为您提供渐变和对边缘的强烈响应。 Sobel运算符不能为您提供准确的边缘,因为渐变通常会在几个像素上上下波动。这样,您的边缘将为几个像素宽。为了使其定位更加准确,我们可以在本地找到具有最大(或最小)梯度的像素。这意味着其二阶导数(拉普拉斯算子)应等于零,或在该点具有零交叉。

Before After

您可以看到处理后的图像同时具有亮带和暗带。过零是边缘。要在内核上看到此效果,请尝试在内核上手动滑动完美的台阶边缘,以查看响应如何变化。

对于您的第二个问题,我想绝对是要同时找到浅色和深色斑点(浅色斑点,深色背景;深色斑点,浅色背景),因为它们分别给出了强烈的负面和强烈的正面回应。然后,它在每个像素位置的所有图像上找到最大值。对于每个输出像素,它将使用图像上响应最大的像素作为输出。我认为他的理由是,具有强脉冲(小斑点)的像素可以对焦。

他正在使用bitwise_not作为复制机制。它将一些由遮罩指定的像素设置为不是源图像的按位显示。最后,您将拥有output由来自不同来源的像素组成,不同之处在于所有像素均未按位进行处理。要恢复真实图像,只需再次“不”为NOT(NOT(x)) = x255-x does exactly that。我认为copyTo也可以使用,不确定他为什么选择其他方式。

http://fourier.eng.hmc.edu/e161/lectures/gradient/node8.html拍摄的图像。