高斯拉普拉斯算子(Laplacian of Gaussian, LoG)
一、简要描述:
拉普拉斯算子是图像二阶空间导数的二维各向同性测度。拉普拉斯算子可以突出图像中强度发生快速变化的区域,因此常用在边缘检测任务当中。在进行Laplacian操作之前通常需要先用高斯平滑滤波器对图像进行平滑处理,以降低Laplacian操作对于噪声的敏感性。该操作通常是输入一张灰度图,经过处理之后输出一张灰度图。
二、工作原理
记图片像素的强度值为 ,其所对应的拉普拉斯算子 如下所示:
这个过程可以采用卷积核进行计算。由于图片是采用离散的像素值集合进行表示的,因此我们可以寻找一个近似于拉普拉斯算子的二阶导数离散卷积核。比如如下所示的两个卷积核:
以上的两个卷积核均可以近似为拉普拉斯算子。因为这两个卷积核都是对图片二阶导数的近似估计,它们对于图片中的噪声均很敏感。因此,为了解决这一问题,我们一般会在进行拉普拉斯操作之前先对图像进行高斯平滑滤波处理,二维的高斯平滑卷积核可以采用以下公式进行表示, ,先利用高斯平滑滤波进行处理,可以降低图片中的高频噪声,方便后续的拉普拉斯操作。事实上由于卷积操作具有结合律,因此我们先将高斯平滑滤波器与拉普拉斯滤波器进行卷积,然后利用得到的混合滤波器去对图片进行卷积以得到所需的结果。采用这个做法主要有以下两个优点:
- 由于高斯和拉普拉斯核通常都比图像小得多,所以这种方法通常只需要很少的算术运算。
- LoG (' Laplacian of Gaussian')内核的参数可以预先计算,因此在运行时只需要对图像执行一遍的卷积即可。
以0为中心,高斯标准差为 的二维的 函数的表达式如下所示:
具体的推导过程如下所示:
函数的图像如下图所示:
以下图3所示的离散卷积核可以近似上面的表达式(当 时):
值得注意的是,随着高斯函数变得越来越窄,LoG卷积核将会近似于图1中所示的简单Laplacian内核,主要原因是因为采用十分窄的高斯函数( )时,其在于离散的网格上面是不起作用的。因此,在离散的网格上,简单的拉普拉斯算子可以看成是一种高斯函数很窄的 函数。
三、使用指南
运算计算图片在空间上的二阶导数。这意味着图片中某个区域的强度是固定值的时候,其 变换的响应值为0。而在图片的强度发生变化的区域,在较暗的一侧 的响应值是正数,而在较亮的一侧, 的响应值则为负数,这意味着在两个强度均匀但不同的区域中间会有一条相对锐利的边,而 函数对于这一部分区域的响应为:
- 在连续强度不变的区域响应值为0
- 在边的一侧响应为正
- 在边的另一侧响应为负
- 在边中间的某一点响应值为0
以下的图4展示了 对于图像中边缘的响应。
因此可以看出 过滤器本身的作用就是突出图像中的边缘。
例如下图5的 变换的响应为图6
其中 卷积核的高斯标准差 ,卷积核的大小为 。需要注意的是,由于 卷积核的输出包含负数值,因此需要将最后输出的结果归一化到0~255之间。如果将经过过滤的部分图像或梯度图像添加到原始图像中,那么结果将使原始图像中的任何边缘更清晰和具有更高的对比度,这常常在遥感应用中作为图像增强的技巧。以图7为例:
值得一提的是增强之后图像的边缘变得更加的锋利但也带来了一定的噪声,以下图8展示了噪声对于 变换的影响。
从图8中可以使用右图这种锐化的图像进行边缘增强,得到的是有噪声的结果。相反,扩大算子的高斯平滑分量可以减少部分噪声,但同时会使得增强效果不那么明显。注意,由于 是一个各向同性的过滤器,所以不可能直接从 输出中提取边缘的方向信息,这与其他边缘检测器(如Roberts Cross和Sobel算子)的方法类似。
四、常见变种
通常我们可以用两个大小不同的高斯函数的差值来近似 滤波器。这种过滤器被称为 过滤器(Difference of Gaussians)。另外在1982年,Marr已经提出 过滤器(实际上是 )在生物视觉处理具有重要的作用。 (Difference og Boxes)滤波器是一种对于 更为粗糙的近似,但其计算速度更快,它只是两个大小不同的均值滤波器之间的差值,其可以产生 滤波器的一种平方近似。
五、代码实现
以下为采用图3所示的近似矩阵来作为 变换的近似卷积核:
import torch
import torch.nn.functional as F
import numpy as np
from torch.autograd import Variable
from math import exp
from PIL import Image
from torchvision.utils import save_image, make_grid
#将最后的矩阵中的元素归一化到0~1之间
def minmaxscaler(data):
min = torch.min(data)
max = torch.max(data)
return (data - min)/(max-min)
#LoG变换
def LoG(img,window,window_size,mode=“RGB”):
img1_array = np.array(img,dtype=np.float32)#Image -> array
img1_tensor = torch.from_numpy(img1_array)# array -> tensor
# 处理不同通道数的数据
if mode ‘L’:
img1_tensor = img1_tensor.unsqueeze(0).unsqueeze(0)#h,w -> n,c,h,w
else:#RGB or RGBA
img1_tensor = img1_tensor.permute(2,0,1)# h,w,c -> c,h,w
img1_tensor = img1_tensor.unsqueeze(0)#c,h,w -> n,c,h,w
channel = img1_tensor.size()[1]
window = Variable(window.expand(channel, 1, window_size, window_size).contiguous())
output = F.conv2d(img1_tensor, window, padding = window_size//2, groups = channel)
output = minmaxscaler(output)# 归一化到0~1之间
if (channel4):
save_image(output, “output.png”, normalize=False)
else:
save_image(output, “output.jpg”, normalize=False)
return output
#近似卷积核
window = torch.Tensor([[[0,1,1,2,2,2,1,1,0],
[1,2,4,5,5,5,4,2,1],
[1,4,5,3,0,3,5,4,1],
[2,5,3,-12,-24,-12,3,5,2],
[2,5,0,-24,-40,-24,0,5,2],
[2,5,3,-12,-24,-12,3,5,2],
[1,4,5,3,0,3,4,4,1],
[1,2,4,5,5,5,4,2,1],
[0,1,1,2,2,2,1,1,0]]])
window_size = 9
img = Image.open("./input.png")
img = img.convert(‘L’)
LoG(img,window,window_size,img.mode)
以下为运行的效果:
参考文献:
R. Haralick and L. Shapiro Computer and Robot Vision, Vol. 1, Addison-Wesley Publishing Company, 1992, pp 346 - 351.
B. Horn Robot Vision, MIT Press, 1986, Chap. 8.
D. Marr Vision, Freeman, 1982, Chap. 2, pp 54 - 78.
D. Vernon Machine Vision, Prentice-Hall, 1991, pp 98 - 99, 214.
参考链接:
Laplacian/Laplacian of Gaussian
http://fourier.eng.hmc.edu/e161/lectures/gradient/node9.html
https://blog.csdn.net/kezunhai/article/details/11579785
8 条评论
二维的高斯平滑卷积核公式是不是写错了,系数底下应该是没有根号的?
是的呢,多谢指正~
您好,请问三维LoG近似卷积核应该是什么
答主LoG表达式写错了,括号里面不是1是2