提供以下代码(被要求删除链接).但我想知道它是如何工作的.如果这被认为是边缘检测或斑点检测,我很困惑,因为维基百科将高斯拉普拉斯(LoG)列为斑点检测.
此外,有人可以解释并提供更深层次的解释,说明为什么计算绝对值以及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
Cris Luengo..
8
hkchengrex的答案相当完整,但我并不完全同意.也许我对正确的命名法有点敏感.检测器可以在要检测的物体的位置产生强烈的响应.
高斯拉普拉斯算子(LoG)不是边缘检测器,因为它在(近*)边缘处具有零交叉.但它可以用于构建边缘检测器.如此构造的边缘检测器是Marr-Hildreth边缘检测器.因此,它通常被归类为边缘检测器.对我来说,这是一个线路探测器.
拉普拉斯是二阶导数的总和(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在图像中的极值处产生强响应(其中二阶导数是最大的).这发生在"斑点"的峰值,沿着线的脊.
我们来看看这个简单的测试图像:
并将LoG应用于它:
这里,中灰色是具有值0的像素.可以看出,它沿着细线和小点具有强(负)响应.它还具有围绕较宽物体边缘的中等响应(边缘内部为负,外部为正); 过零点靠近边缘的位置.
我们可以对此图像进行阈值检测,以检测细线和点:
(阈值大小产生相同的结果).我们可以降低阈值以查看介质响应发生在感兴趣的边缘周围:
获取边缘需要的不仅仅是一个简单的阈值.相比之下,梯度幅度(边缘位置处的一阶导数很强)可以设置阈值以获得边缘:
梯度幅度对于检测线条没有用,因为它检测沿线的两条边,而不是线本身.上面的梯度幅度是使用高斯导数计算的(Sobel是另一种选择,但不是那么精确).
请注意,Canny边缘检测器基于梯度幅度,它增加了非最大抑制和滞后阈值处理,使检测变得薄且有意义.
*二阶导数在拐点处具有零交叉(可以将其视为边缘的真实位置).然而,拉普拉斯算子是二阶导数的总和.如果你想到梯度方向的二阶导数,它的零交叉将很好地定位.但现在在垂直方向(沿着边缘)添加二阶导数.该二阶导数沿直边为零,沿凸曲面边缘(例如圆的边缘)为负,沿凹曲面边为正.因此,添加这两个值将导致零交叉在弯曲边缘上移动,曲率越强,过零点将偏离其真实位置越多.
1> Cris Luengo..:
hkchengrex的答案相当完整,但我并不完全同意.也许我对正确的命名法有点敏感.检测器可以在要检测的物体的位置产生强烈的响应.
高斯拉普拉斯算子(LoG)不是边缘检测器,因为它在(近*)边缘处具有零交叉.但它可以用于构建边缘检测器.如此构造的边缘检测器是Marr-Hildreth边缘检测器.因此,它通常被归类为边缘检测器.对我来说,这是一个线路探测器.
拉普拉斯是二阶导数的总和(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在图像中的极值处产生强响应(其中二阶导数是最大的).这发生在"斑点"的峰值,沿着线的脊.
我们来看看这个简单的测试图像:
并将LoG应用于它:
这里,中灰色是具有值0的像素.可以看出,它沿着细线和小点具有强(负)响应.它还具有围绕较宽物体边缘的中等响应(边缘内部为负,外部为正); 过零点靠近边缘的位置.
我们可以对此图像进行阈值检测,以检测细线和点:
(阈值大小产生相同的结果).我们可以降低阈值以查看介质响应发生在感兴趣的边缘周围:
获取边缘需要的不仅仅是一个简单的阈值.相比之下,梯度幅度(边缘位置处的一阶导数很强)可以设置阈值以获得边缘:
梯度幅度对于检测线条没有用,因为它检测沿线的两条边,而不是线本身.上面的梯度幅度是使用高斯导数计算的(Sobel是另一种选择,但不是那么精确).
请注意,Canny边缘检测器基于梯度幅度,它增加了非最大抑制和滞后阈值处理,使检测变得薄且有意义.
*二阶导数在拐点处具有零交叉(可以将其视为边缘的真实位置).然而,拉普拉斯算子是二阶导数的总和.如果你想到梯度方向的二阶导数,它的零交叉将很好地定位.但现在在垂直方向(沿着边缘)添加二阶导数.该二阶导数沿直边为零,沿凸曲面边缘(例如圆的边缘)为负,沿凹曲面边为正.因此,添加这两个值将导致零交叉在弯曲边缘上移动,曲率越强,过零点将偏离其真实位置越多.