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

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

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

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

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


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

cv2.blur

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

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

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

假设我们传入的kszie=(ksize_h, ksize_w),那么均值模糊的卷积核就是:

                                            \large \frac{1}{(ksize_h*ksize_w)}*\begin{bmatrix} 1 &1 &... &1 \\ 1& 1& ...&1 \\ ...& ...& ... &1 \\ 1& 1& ... &1 \end{bmatrix}_{(ksize_h*ksize_w)}

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

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]]

四、双边模糊

bilateral filter双边滤波器的通俗理解:公式推导

双边滤波(Bilateral Filter)详解:参数说明、参数选择

猜你喜欢

转载自blog.csdn.net/Vici__/article/details/102476784