图像处理:高斯滤波算法

目录


前言

在此之前,我曾在此篇中推导过图像处理:推导五种滤波算法(均值、中值、高斯、双边、引导)。这在此基础上,我想更深入地研究和推导这些算法,以便为将来处理图像的项目打下基础。

概念介绍

高斯滤波是一种常用的图像处理技术,常用于去噪、平滑和边缘检测等应用中。它是基于高斯函数的概念,由于高斯函数的性质,距离中心像素越远的像素对新值的贡献越小,对图像中的像素进行加权平均处理,使得周围像素的影响比较大,而远离中心像素的影响则较小。因此,高斯滤波可以平滑图像并去除一部分噪声,同时保留图像中的边缘和细节。

具体来说,高斯滤波是通过一个矩阵(卷积核)来实现的。这个矩阵的值是由高斯函数计算出来的,高斯函数在中心点处取得最大值,随着距离的增加而逐渐减小。矩阵的大小和参数的选择取决于需要处理的图像和要达到的效果。

基本原理

这里以一个3×3的卷积核为例,卷积核的值是由高斯函数计算出来的,高斯函数在中心点处取得最大值,随着距离的增加而逐渐减小。通过对每个像素应用卷积核,高斯滤波可以对图像进行平滑处理并去除噪声,同时保留图像的细节和边缘。

如上图所示,高斯函数在中心点处的值最大,离中心点越远的值越小。这意味着对于每个像素,距离中心像素越远的像素对新值的影响越小。这种影响方式使得高斯滤波可以去除图像噪声,同时保留图像细节和边缘。

通过高斯滤波的计算过程,可以得出中心点像素值226被新值164所替代的结果。具体来说,通过一个简单的矩阵点乘计算,将卷积核与图像中的像素矩阵相乘,得出每个像素的新值。

它的计算过程如下所示:

a=40*1+107*2+5*1+198*2+226*8+223*2+37*1+68*2+193*1
b=a*(1/(1*4+2*4+8))
print(b)

卷积核的大小

前面举的例子是以3×3大小的卷积核为例,这里就详细补充一些有关于卷积核的知识。

卷积核的形状和权重比

卷积核的形状通常是一个矩阵,长和宽可以有所不同,但必须是奇数。在高斯滤波中,卷积核的大小通常是3×3、5×5、7×7等。其中,3×3的卷积核是最常用的,它的中心点权重最大,周围点权重逐渐减小。

\frac{1}{256}\begin{bmatrix} 1 & 4 & 6 & 4 &1 \\ 4 & 16 & 24 & 16 & 4\\ 6 & 24& 36 & 24 &6 \\ 4 & 16 & 24 &16 &4 \\ 1& 4 & 6 &4 &1 \end{bmatrix} \frac{1}{159}\begin{bmatrix} 2& 9& 5& 9 &2 \\ 4& 4& 12& 4 &4 \\ 5& 12& 15& 12 &5 \\ 4& 9& 12& 9& 4\\ 2& 4 & 5 & 4 &2 \end{bmatrix}

同一尺寸的卷积核可以有不同的形式的权重比例,这些权重比例会决定卷积核对图像不同区域的关注程度。在高斯滤波中,卷积核的权重比是根据高斯函数计算得出的。高斯函数是一个钟形曲线,它的中心点权重最大,两侧的权重逐渐减小。

卷积核的归一化

在实际使用过程中,往往需要对卷积核进行归一化,以保证滤波效果的正确性。在高斯滤波中,卷积核的所有权重值都需要缩放到相同的范围内,并且总和为1,以保证卷积操作对图像的影响是平衡的,避免某些权重过大或过小导致滤波结果出现偏差。

结论

卷积核是图像处理中非常重要的概念,它可以通过卷积操作实现滤波、边缘检测等功能。在高斯滤波中,卷积核的大小、权重比例和归一化等因素都会影响滤波效果。因此,需要根据实际情况选择合适的卷积核,并对卷积核进行适当的调整,以满足不同的图像处理需求。

Opencv实现高斯滤波

def GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None):

在Opencv中,我们可以使用cv2.GaussianBlur()函数来实现高斯滤波。使用该函数时,需要输入原始图像、卷积核的大小、沿着x轴、y轴方向的高斯核标准差以及边界样式等参数。其中sigmaY和borderType是可选参数,sigmaX是必选参数,但是可以将该参数设置为 0,让函数自己去计算 sigmaX 的具体值。

import cv2
import numpy as np
import pyps.pyzjr.utility as zjr
path = 'Images/Colnoiselena.jpg'

img = cv2.imread(path)
imgGaussianBlur_1=cv2.GaussianBlur(img,(1,1),0,0)
imgGaussianBlur_3=cv2.GaussianBlur(img,(3,3),0,0)
imgGaussianBlur_5=cv2.GaussianBlur(img,(5,5),0,0)
imgGaussianBlur_7=cv2.GaussianBlur(img,(7,7),0,0)

imgStack = zjr.stackImages(0.6, ([imgGaussianBlur_1, imgGaussianBlur_3], [imgGaussianBlur_5, imgGaussianBlur_7]))
cv2.imshow("imges",imgStack)
cv2.waitKey(0)
cv2.destroyAllWindows()

实现效果: 

一般情况下,卷积核大小和高斯核标准差是需要根据实际场景进行调整的。如果需要对图像进行更强的模糊处理,可以增加sigma值和卷积核的大小;如果需要对图像进行较弱的模糊处理,可以减小sigma值和卷积核的大小。

Python手写实现高斯滤波

import cv2
import numpy as np
import pyps.pyzjr.utility as zjr
path = 'Images/Colnoiselena.jpg'
img = cv2.imread(path)

def gaussian_kernel(size, sigma):
    kernel = np.zeros((size, size), dtype=np.float32)
    center = size // 2

    for i in range(size):
        for j in range(size):
            x, y = i - center, j - center
            kernel[i, j] = np.exp(-(x**2 + y**2)/(2*sigma**2))
    kernel /= 2 * np.pi * sigma**2
    kernel /= np.sum(kernel)
    return kernel

def Gaussian_Filtering(img, kernel_size, sigma):
    kernel = gaussian_kernel(kernel_size, sigma)
    height, width, channels = img.shape
    result = np.zeros_like(img, dtype=np.float32)

    pad_size = kernel_size // 2
    img_pad = np.pad(img, [(pad_size, pad_size), (pad_size, pad_size), (0, 0)], mode='constant')
    for c in range(channels):
        for i in range(pad_size, height + pad_size):
            for j in range(pad_size, width + pad_size):
                result[i - pad_size, j - pad_size, c] = np.sum(kernel * img_pad[i - pad_size:i + pad_size + 1, j - pad_size:j + pad_size + 1, c])
    return np.uint8(result)

imgGaussianBlur_1 = Gaussian_Filtering(img, 1, 1.5)
imgGaussianBlur_3 = Gaussian_Filtering(img, 3, 1.5)
imgGaussianBlur_5 = Gaussian_Filtering(img, 5, 1.5)
imgGaussianBlur_7 = Gaussian_Filtering(img, 7, 1.5)
imgStack = zjr.stackImages(0.6, ([imgGaussianBlur_1, imgGaussianBlur_3], [imgGaussianBlur_5, imgGaussianBlur_7]))
cv2.imshow("imges",imgStack)
cv2.waitKey(0)
cv2.destroyAllWindows()

与手写实现均值滤波的情况大致相同,还是计算速度比较慢的情况,不过这里从效果来看,又是相差不大。

下面是这个函数的具体实现过程: 

  • 定义一个高斯核:首先通过 gaussian_kernel() 函数生成一个高斯核,该函数根据输入的 sizesigma 参数生成一个高斯核,其中 size 表示高斯核的大小, sigma 表示高斯核的标准差。

G(x,y)=\frac{1}{2\pi \sigma^{2}}e^{-\frac{x^{2}+y^{2}}{2\sigma ^{2}}}

  • 对图像进行补零:由于高斯滤波是在图像的像素周围应用高斯核,因此需要对图像进行补零处理,以便在图像的边缘区域进行高斯卷积时不会出现越界的情况。这里使用 np.pad() 函数来实现对图像的补零操作,其中只对高和宽两个维度进行填充,通道维度不进行填充。

  • 实现高斯卷积:对于每一个像素,将以它为中心的区域和高斯核进行卷积,这里使用嵌套的三重循环对图像进行遍历,其中 c 表示图像的通道数, ij 表示当前像素的位置。

  • 将卷积结果存储在结果矩阵中:将卷积的结果保存在一个结果矩阵中,该矩阵与原始图像具有相同的大小。最后将该结果矩阵转换为uint8格式并返回。

需要注意的是,在对图像进行高斯滤波时,应该对每一个通道分别进行处理,因此在高斯卷积的循环中需要增加一个针对通道的循环。

参考文章

(13条消息) 图像处理:推导五种滤波算法(均值、中值、高斯、双边、引导)_高斯滤波,均值滤波,中值滤波_夏天是冰红茶的博客-CSDN博客

(19条消息) 高斯滤波(Gauss filtering)_半濠春水的博客-CSDN博客

(6条消息) 高斯滤波及其原理_声希Censh的博客-CSDN博客

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
扎眼的阳光的头像扎眼的阳光普通用户
上一篇 2023年12月27日
下一篇 2023年12月27日

相关推荐