欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊

程序员文章站 2022-07-14 11:35:32
...

对于卷积概念和计算不熟悉的建议先看下这篇博客:直观理解深度学习卷积部分

 滤波器有高通滤波器(HPF)和低通滤波器(LPF)两种。

  • 高通滤波器:根据像素与周围的像素的亮度差值来提升改像素的亮度
    主要作用是锐化
  • 低通滤波器:在像素与周围像素的亮度差值小于一个特定值时,平滑改像素的亮度
    主要作用是去噪和模糊化

下面要说的均值模糊、中值模糊、高斯模糊都属于低通滤波器。


 

一、均值模糊(归一化滤波)

cv2.blur

  • 原型:blur(src, ksize, dst=None, anchor=None, borderType=None)

  • 作用:对图像进行算术平均值模糊

  • 参数:ksize:卷积核的大小。dst,若填入dst,则将图像写入到dst矩阵。borderType:填充方式

假设我们传入的真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊,那么均值模糊的卷积核就是:

                                            真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊

 如果不理解,看看下面这段代码:

def blur_test():
    img = np.array([[1, 1, 1, 1, 1], 
                    [2, 2, 2, 2, 2], 
                    [3, 3, 3, 3, 3], 
                    [4, 4, 4, 4, 4], 
                    [5, 5, 5, 5, 5]], dtype=np.float32)
    print(img)
    dst = cv2.blur(img, (3, 3), borderType=cv2.BORDER_CONSTANT)
    print(dst)

blur_test()


output:
[[1. 1. 1. 1. 1.]
 [2. 2. 2. 2. 2.]
 [3. 3. 3. 3. 3.]
 [4. 4. 4. 4. 4.]
 [5. 5. 5. 5. 5.]]

[[0.6666667 1.        1.        1.        0.6666667]
 [1.3333334 2.        2.        2.        1.3333334]
 [2.        3.        3.        3.        2.       ]
 [2.6666667 4.        4.        4.        2.6666667]
 [2.        3.        3.        3.        2.       ]]

一个5*5的矩阵,经过blur的3*3卷积之后,真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊
我们可以看出输出矩阵和原矩阵的shape是相同的(都是5*5);

但卷积操作应该会使矩阵变小的啊,那么blur()之后矩阵却没有变小,
那么一定是对原矩阵进行了填充。(如右图,虚线话的框框就是填充)

 

这里的填充方式为 borderType=cv2.BORDER_CONSTANT,默认把虚线框里填充上0。

其它的填充方式如下:

BORDER_CONSTANT 

Python: cv.BORDER_CONSTANT

iiiiii|abcdefgh|iiiiiii with some specified i

BORDER_REPLICATE 

Python: cv.BORDER_REPLICATE

aaaaaa|abcdefgh|hhhhhhh

BORDER_REFLECT 

Python: cv.BORDER_REFLECT

fedcba|abcdefgh|hgfedcb

BORDER_WRAP 

Python: cv.BORDER_WRAP

cdefgh|abcdefgh|abcdefg

BORDER_REFLECT_101 

Python: cv.BORDER_REFLECT_101

gfedcb|abcdefgh|gfedcba

BORDER_TRANSPARENT 

Python: cv.BORDER_TRANSPARENT

uvwxyz|abcdefgh|ijklmno

BORDER_REFLECT101 

Python: cv.BORDER_REFLECT101

same as BORDER_REFLECT_101

BORDER_DEFAULT 

Python: cv.BORDER_DEFAULT

same as BORDER_REFLECT_101

BORDER_ISOLATED 

Python: cv.BORDER_ISOLATED

do not look outside of ROI

填充之后,然后按照卷积核滑动计算的方式得出结果。

二、中值模糊

cv2.medianBlur

  • 原型:mediaBlur(src, ksize, dst=None)

  • 作用:对图像进行中值模糊

  • 参数:ksize:卷积核的大小。dst,若填入dst,则将图像写入到dst矩阵。

翻遍了网上的博客,也没找到有关中值模糊的具体计算。

(其实只是用了类似卷积核的这个矩阵,计算方式就是取中间位置的数)

medianBlur函数,输入的ksize是一个int型整数,不同于blur中的size。它的卷积核是个ksize*ksize的矩阵。

medianBlur中值模糊就是以滑动的方式从原矩阵取出ksize*ksize个数,然后进行排序,结果就是中间位置的数。

它没有填充方式的参数,它的默认填充方式为:(这个很重要)

BORDER_REPLICATE 

Python: cv.BORDER_REPLICATE

aaaaaa|abcdefgh|hhhhhhh

首先我们看下面这段代码:

def blur_test():
    img = np.array([[1, 1, 3], 
                    [3, 2, 1], 
                    [1, 1, 3]], dtype=np.uint8)
    print(img)

    dst = cv2.medianBlur(img, 3)
    print(dst)

blur_test()

代码的输出结果是

[[1 1 3]
 [3 2 1]
 [1 1 3]]

[[1 1 2]
 [1 1 2]
 [1 1 2]]

其实它对原数组进行了下面的填充,然后按照3*3的卷积核把周围的9个数进行排序,取出中间的数作为结果。 

[[1 1 3]
 [3 2 1]
 [1 1 3]]

(1) (1) (1) (3) (3)
(1)  1   1   3  (3)
(3)  3   2   1  (1)
(1)  1   1   3  (3)
(1) (1) (1) (3) (3)

三、高斯模糊

转自https://www.cnblogs.com/invisible2/p/9177018.html

有了前面的知识,我们知道如果要想实现高斯模糊的特点,则需要通过构建对应的权重矩阵来进行滤波。

1、正态分布

真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊

 

正态分布中,越接近中心点,取值越大,越远离中心,取值越小
计算平均值的时候,我们只需要将"中心点"作为原点,其他点按照其在正态曲线上的位置,分配权重,就可以得到一个加权平均值。正态分布显然是一种可取的权重分配模式。

2、高斯函数

如何反映出正态分布?则需要使用高函数来实现。
上面的正态分布是一维的,而对于图像都是二维的,所以我们需要二维的正态分布。

 

真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊

 

正态分布的密度函数叫做"高斯函数"(Gaussian function)。它的一维形式是:

真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊

 

其中,μ是x的均值,σ是x的方差。因为计算平均值的时候,中心点就是原点,所以μ等于0。

真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊

 

根据一维高斯函数,可以推导得到二维高斯函数:

真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊

 

有了这个函数 ,就可以计算每个点的权重了。

3、获取权重矩阵

假定中心点的坐标是(0,0),那么距离它最近的8个点的坐标如下:

真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊


更远的点以此类推。
为了计算权重矩阵,需要设定σ的值。假定σ=1.5,则模糊半径为1的权重矩阵如下:(把坐标值带入高斯公式)

真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊


这9个点的权重总和等于0.4787147,如果只计算这9个点的加权平均,还必须让它们的权重之和等于1,因此上面9个值还要分别除以0.4787147,得到最终的权重矩阵。

真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊


除以总值这个过程也叫做“归一问题”。
目的是让滤镜的权重总值等于1。否则的话,使用总值大于1的滤镜会让图像偏亮,小于1的滤镜会让图像偏暗。

这里有个知识点:

  • 滤波器的权重总值等于1时不会改变图像的亮度
  • 权重总值大于1的滤镜会让图像偏亮小于1的滤镜会让图像偏暗
  • 权重总值等于0时:该滤波器属于边缘检测核,可以把边缘转化为白色非边缘转化为黑色

4、计算模糊值

有了权重矩阵,就可以计算高斯模糊的值了。
假设现有9个像素点,灰度值(0-255)如下:

真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊


每个点乘以自己的权重值:

真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊


得到

真正搞懂均值模糊、中值模糊、高斯模糊、双边模糊


将这9个值加起来,就是中心点的高斯模糊的值。
对所有点重复这个过程,就得到了高斯模糊后的图像。对于彩色图片来说,则需要对RGB三个通道分别做高斯模糊。

def Gauss_blur():
    img = np.array([[14, 15, 16], [24, 25, 26], [34, 35, 36]], dtype=np.float32)
    blur = cv2.GaussianBlur(img, (3, 3), 1.5)
    print(blur)


Gauss_blur()

# output:
[[20.771631 21.156027 21.540426]
 [24.615604 25.       25.3844  ]
 [28.45958  28.843975 29.228374]]