python - 高斯拉普拉斯算子是用于斑点检测还是边缘检测?
问题描述
以下代码来自(被要求删除链接)。但我想知道它究竟是如何工作的。如果这被认为是边缘检测或斑点检测,我感到困惑,因为维基百科将高斯拉普拉斯算子 (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
解决方案
hkchengrex 的回答相当完整,但我并不完全同意。也许我有点坚持正确的命名法。检测器是在要检测的东西的位置产生强烈响应的东西。
高斯拉普拉斯算子 (LoG) 不是边缘检测器,因为它在 (near * ) 边缘处有零交叉。但它可以用来构建边缘检测器。如此构造的边缘检测器是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 在图像的极值处产生强烈的响应(其中二阶导数最大)。这发生在“斑点”的顶部,以及沿着线条的脊部。
让我们来看看这个简单的测试图像:
并将日志应用到它:
在这里,中灰色是值为 0 的像素。可以看出,它在细线和小点上具有强(负)响应。它还在较宽对象的边缘周围具有中等响应(边缘内部为负,外部为正);零交叉点靠近边缘所在的位置。
我们可以对该图像进行阈值检测以检测细线和点:
(阈值幅度产生相同的结果)。我们可以降低阈值以查看中等响应发生在感兴趣的边缘周围:
获得边缘需要的不仅仅是一个简单的阈值。相反,可以对梯度幅度(边缘位置的一阶导数很强)进行阈值化以获得边缘:
梯度幅度对于检测线没有用,因为它检测的是沿线的两个边缘,而不是线本身。上面的梯度幅度是使用高斯导数计算的(索贝尔是另一种选择,但不那么精确)。
请注意,Canny 边缘检测器是基于梯度幅度的,它添加了非极大值抑制和滞后阈值处理,以使检测变得细而有意义。
*二阶导数在拐点处有一个零交叉点(可以作为边缘的真实位置)。然而,拉普拉斯算子是二阶导数之和。如果考虑梯度方向的二阶导数,它的零交叉点将很好地定位。但是现在在垂直方向(沿边缘)添加二阶导数。该二阶导数沿直边为零,沿凸弯曲边缘(例如圆的边缘)为负,沿凹弯曲边缘为正。因此,添加这两个值将导致零交叉在弯曲边缘上移动,曲率越强,零交叉就越偏离其真实位置。
推荐阅读
- sql - 在 WHERE 语句中使用的 SQL 索引
- python - Groupby 性别并计算高度列中的缺失值
- css - @keyframes 动画背景位置不起作用
- azure-functions - Azure Functions BlobTrigger 属性绑定问题
- python - 如何在 jupyterhub 页面中使用 python-selenium 查找现有的 HTML 元素?
- html - 我的响应式网站不适用于三星和 OPPO 手机。为什么?
- python - 如果实际数据嵌入了相同的分隔符,如何使用 Spark RDD 读取分隔文件
- xml - 如何使用 Xquery 用 XML 节点包装每个返回结果?
- file - 将文件夹中大于 5000 KB 的文件名列出到单独的文件中
- c - vim 是否在自动完成建议中提供函数参数