问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

图像处理:均值滤波算法详解

创作时间:
作者:
@小白创作中心

图像处理:均值滤波算法详解

引用
CSDN
1.
https://blog.csdn.net/m0_62919535/article/details/130316849

均值滤波是一种常用的图像处理技术,主要用于去除图像噪声、平滑图像。其基本原理是用像素点周围的邻域像素的平均值来代替该像素的值。本文将从概念、基本原理到具体实现(包括使用OpenCV库和纯Python实现)详细讲解均值滤波算法,并通过代码示例和图像处理效果展示不同滤波核大小对图像的影响。

概念介绍

均值滤波是一种简单的图像平滑处理方法,其基本思想是用像素点周围的邻域像素的平均值来代替该像素的值。在图像处理中,均值滤波可以用于去除图像中的噪声,使图像变得更加平滑。它的计算简单易懂,但在滤波过程中可能会导致图像细节的损失。因此,在实际应用中,需要根据具体的情况选择适合的滤波算法。

基本原理

我们以5x5大小为例,均值滤波的原理只需要理解到,它其实是将这个范围内的25个值进行求和的平均值,以这个新值来代替这个区域的中心值。

配合这里的图进行理解:

运行之后,获得新值126,覆盖掉中心值得像素226。

对于边缘像素,只仅仅计算在这个范围内得数值。假如,左上角为中心值,而其左边和上边都没有值,我们只需要计算在这5x5区域内有的值就可以了。

计算如下:

print((23+0+25+158+140+238+67+199+197)/9)

得出新值为116,替换中心点23的值。

Opencv实现均值滤波

在OpenCV中,我们可以使用cv2.blur()函数来实现均值滤波。在使用该函数时,我们需要输入原始图像、滤波核的大小以及边界样式等参数。一般情况下,我们可以直接采用函数默认值即可。

下面是使用OpenCV实现均值滤波的代码示例:

import cv2

path = 'Images/Colnoiselena.jpg'
img = cv2.imread(path)

imgAverage_1 = cv2.blur(img, (1, 1))
imgAverage_3 = cv2.blur(img, (3, 3))
imgAverage_5 = cv2.blur(img, (5, 5))
imgAverage_7 = cv2.blur(img, (7, 7))

imgStack = cv2.hconcat([cv2.vconcat([imgAverage_1, imgAverage_3]), cv2.vconcat([imgAverage_5, imgAverage_7])])
cv2.imshow("images", imgStack)
cv2.waitKey(0)

实现效果:

经典的lena的图片,可以看到,随着滤波核的大小逐渐增加,去噪效果越好,但相应的图片会变的模糊,计算时间会增长。所以,还是应了我开头就说过的话,在实际处理中,选择合适的滤波核大小,让模糊与去噪效果之间取得平衡。

Python手写实现均值滤波

下面是使用纯Python实现均值滤波的代码示例:

import cv2
import numpy as np

path = 'Images/Colnoiselena.jpg'
img = cv2.imread(path)

def Arerage_Filtering(img, k_size=3):
    if k_size % 2 == 0:
        k_size += 1
    rows, cols = img.shape[:2]
    pad_width = (k_size - 1) // 2
    img_pad = cv2.copyMakeBorder(img, pad_width, pad_width, pad_width, pad_width, cv2.BORDER_REPLICATE)
    img_filter = np.zeros_like(img)
    for i in range(rows):
        for j in range(cols):
            pixel_values = img_pad[i:i+k_size, j:j+k_size].flatten()
            img_filter[i, j] = np.mean(pixel_values)
    return img_filter

imgAverage_1 = Arerage_Filtering(img, k_size=1)
imgAverage_3 = Arerage_Filtering(img, k_size=3)
imgAverage_5 = Arerage_Filtering(img, k_size=5)
imgAverage_7 = Arerage_Filtering(img, k_size=7)

imgStack = cv2.hconcat([cv2.vconcat([imgAverage_1, imgAverage_3]), cv2.vconcat([imgAverage_5, imgAverage_7])])
cv2.imshow("images", imgStack)
cv2.waitKey(0)
cv2.destroyAllWindows()

这个算法相对来说比较容易实现,但是相比调用OpenCV的函数,它的计算时间要长很多,而且我这里还只考虑了图像的两个通道,最终输出的结果是灰度图的情况下。

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

  1. 首先,判断卷积核的大小是否为奇数,如果为偶数,则将其加1,确保其大小为奇数。
  2. 获取图像的行数和列数。
  3. 计算填充的宽度,即卷积核宽度的一半,用于处理图像边缘。

  1. 使用cv2.copyMakeBorder函数进行边缘填充,将图像的边缘复制并填充到周围,以防止边缘像素点无法进行卷积。
  2. 初始化一个和原始图像大小一样的零矩阵。
  3. 遍历图像中的每一个像素点,计算该像素点周围邻域内的像素值,并求取其平均值,然后将其赋值给零矩阵中的对应像素点。
  4. 返回处理后的图像。

最后,函数通过stackImages函数将处理后的四张图像以2x2的网格形式拼接成一张图像,并展示结果。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号