初入SLAM(5)——SIFT中的高斯模糊

1. Go 高斯模糊

高斯模糊是一种图像滤波器,它使用正态分布(高斯函数)计算模板值,并使用该模板与原图像做卷积运算,达到模糊图像的目的。

N维空间的正态分布如公式1-1所示 G ( r ) = 1 2 π σ 2 e − r 2 ( 2 σ 2 ) ( 1 − 1 ) G(r)=\frac{1}{\sqrt{2 \pi \sigma^{2}} e^{-r^{2}\left(2 \sigma^{2}\right)}}(1-1) G(r)=2πσ2 er2(2σ2)111
其中, σ \sigma σ是正态分布的标准差, σ \sigma σ值越大,进行高斯模糊后的图像越模糊(平滑)。r为模糊半径,模糊半径是指模板元素到模板中心的距离。

以下用二维模板举例,假设二维模板大小为 m ∗ n m*n mn,则模板元素上的元素 ( x , y ) (x,y) (x,y)对应的高斯计算公式为:
G ( x , y ) = 1 2 π σ 2 e − ( x − m / 2 ) 2 + ( y − n / 2 ) 2 2 σ 2 ( 1 − 2 ) G(x, y)=\frac{1}{2 \pi \sigma^{2}} e^{-\frac{(x-m / 2)^{2}+(y-n / 2)^{2}}{2 \sigma^{2}}}(1-2) G(x,y)=2πσ21e2σ2(xm/2)2+(yn/2)212
在二维空间中,这个公式生成的曲面的等高线是从中心开始呈正态分布的同心圆。分布不为零的像素组成的卷积矩阵与原始图像做变换。每个像素的值都是周围相邻像素值的加权平均。原始像素的值有最大的高斯分布值,所以有最大的权重,相邻像素随着距离原始像素越来越远,其权重也越来越小。这样进行模糊处理比其它的均衡模糊滤波器更高地保留了边缘效果。

理论上来讲,图像中每点的分布都不为零,这也就是说每个像素的计算都需要包含整幅图像。在实际应用中,在计算高斯函数的离散近似时,在大概3σ距离之外的像素都可以看作不起作用,这些像素的计算也就可以忽略。通常,图像处理程序只需要计算(6σ+1)*(6σ+1)的矩阵就可以保证相关像素影响。

2. Python学习代码

import cv2
import numpy as np


def GaussianSmooth2D(image: np.ndarray, sigma: float):
	'''
	此程序用于高斯平滑灰度图像,图像不能是3维灰度图,只能是2维的。此外,本程序实现自动全零填充,输出维度跟输入维度一样。
	image:二维图像,cv2的灰度读入
	sigma:高斯核的标准差
	'''
    # 确保sigma为正数
    sigma = sigma if sigma>0 else 0
    # 高斯核矩阵大小为(6*sigma+1)*(6*sigma+1)
    ksize = round(sigma * 3) * 2 + 1

    if (ksize == 1):
        return image

    kernel = np.zeros((ksize, ksize))

    scale = -0.5/(sigma * sigma)
    cons = -scale / np.pi
    sum = 0
    for i in range(ksize):
        for j in range(ksize):
            x = i - (ksize - 1) / 2
            y = j - (ksize - 1) / 2
            temp = cons * np.exp(scale * (x*x + y*y))
            kernel[i, j] = temp
            sum += temp

    # 归一化
    kernel = kernel / sum


    p = [ksize//2, ksize//2]


    dst = np.pad(image, p, 'constant')

    guassian_img = np.empty((image.shape))

    for i in range(p[0], image.shape[0] + p[0]):
        for j in range(p[1], image.shape[1] + p[1]):
            guassian_img[i-p[0], j-p[1]] = np.sum(kernel * dst[i-p[0]:i+p[0]+1,j-p[1]:j+p[1]+1])

    return guassian_img.astype(np.uint8)

3.总结

自己手写的代码肯定比调官方库慢,但是有些时候还是需要理解其中的原理,重复造轮子也不是不行。

猜你喜欢

转载自blog.csdn.net/REstrat/article/details/127047803