一、线性滤波与卷积的基本概念

线性滤波可以说是图像处理最基本的方法,它可以允许我们对图像进行处理,产生很多不同的效果。做法很简单。首先,我们有一个二维的滤波器矩阵(有个高大上的名字叫卷积核)和一个要处理的二维图像。然后,对于图像的每一个像素点,计算它的邻域像素和滤波器矩阵的对应元素的乘积,然后加起来,作为该像素位置的值。这样就完成了滤波过程。

  

pytorch实现高斯滤波器_数字图像处理


  对图像和滤波矩阵进行逐个元素相乘再求和的操作就相当于将一个二维的函数移动到另一个二维函数的所有位置,这个操作就叫卷积或者协相关。卷积和协相关的差别是,卷积需要先对滤波矩阵进行180的翻转,但如果矩阵是对称的,那么两者就没有什么差别了。

  Correlation 和 Convolution可以说是图像处理最基本的操作,但却非常有用。这两个操作有两个非常关键的特点:它们是线性的,而且具有平移不变性shift-invariant。平移不变性指我们在图像的每个位置都执行相同的操作。线性指这个操作是线性的,也就是我们用每个像素的邻域的线性组合来代替这个像素。这两个属性使得这个操作非常简单,因为线性操作是最简单的,然后在所有地方都做同样的操作就更简单了。

  实际上,在信号处理领域,卷积有广泛的意义,而且有其严格的数学定义,但在这里不关注这个。

  2D卷积需要4个嵌套循环4-double loop,所以它并不快,除非我们使用很小的卷积核。这里一般使用3x3或者5x5。而且,对于滤波器,也有一定的规则要求:

   1)滤波器的大小应该是奇数,这样它才有一个中心,例如3x3,5x5或者7x7。有中心了,也有了半径的称呼,例如5x5大小的核的半径就是2。

   2)滤波器矩阵所有的元素之和应该要等于1,这是为了保证滤波前后图像的亮度保持不变。当然了,这不是硬性要求了。

   3)如果滤波器矩阵所有元素之和大于1,那么滤波后的图像就会比原图像更亮,反之,如果小于1,那么得到的图像就会变暗。如果和为0,图像不会变黑,但也会非常暗。

   4)对于滤波后的结构,可能会出现负数或者大于255的数值。对这种情况,我们将他们直接截断到0和255之间即可。对于负数,也可以取绝对值。

  


二、神奇的卷积核

上面说到,对图像的滤波处理就是对图像应用一个小小的卷积核,那这个小小的卷积核到底有哪些魔法,能让一个图像从惨不忍睹变得秀色可餐。下面我们一起来领略下一些简单但不简单的卷积核的魔法。
  

1、啥也不做

哈哈,大家可以看到啥了吗?这个滤波器啥也没有做,得到的图像和原图是一样的。因为只有中心点的值是1。邻域点的权值都是0,对滤波后的取值没有任何影响。

  

pytorch实现高斯滤波器_数字图像处理_02


  下面我们动点真格的。

  

2、图像锐化滤波器Sharpness Filter

图像的锐化和边缘检测很像,首先找到边缘,然后把边缘加到原来的图像上面,这样就强化了图像的边缘,使图像看起来更加锐利了。这两者操作统一起来就是锐化滤波器了,也就是在边缘检测滤波器的基础上,再在中心的位置加1,这样滤波后的图像就会和原始的图像具有同样的亮度了,但是会更加锐利。

pytorch实现高斯滤波器_pytorch实现高斯滤波器_03


  

  我们把核加大,就可以得到更加精细的锐化效果:

pytorch实现高斯滤波器_线性滤波_04


  

   另外,下面的滤波器会更强调边缘:

pytorch实现高斯滤波器_高斯滤波_05


  

  主要是强调图像的细节。最简单的3x3的锐化滤波器如下:

pytorch实现高斯滤波器_高斯滤波_06


   实际上是计算当前点和周围点的差别,然后将这个差别加到原来的位置上。另外,中间点的权值要比所有的权值和大于1,意味着这个像素要保持原来的值。

  

3、边缘检测Edge Detection

我们要找水平的边缘:需要注意的是,这里矩阵的元素和是0,所以滤波后的图像会很暗,只有边缘的地方是有亮度的。

pytorch实现高斯滤波器_高斯滤波_07


  

  为什么这个滤波器可以寻找到水平边缘呢?因为用这个滤波器卷积相当于求导的离散版本:你将当前的像素值减去前一个像素值,这样你就可以得到这个函数在这两个位置的差别或者斜率。下面的滤波器可以找到垂直方向的边缘,这里像素上和下的像素值都使用:

pytorch实现高斯滤波器_卷积_08


  

  再下面这个滤波器可以找到45度的边缘:取-2不为了什么,只是为了让矩阵的元素和为0而已。

pytorch实现高斯滤波器_pytorch实现高斯滤波器_09


  

  那下面这个滤波器就可以检测所有方向的边缘:

pytorch实现高斯滤波器_pytorch实现高斯滤波器_10


  

  为了检测边缘,我们需要在图像对应的方向计算梯度。用下面的卷积核来卷积图像,就可以了。但在实际中,这种简单的方法会把噪声也放大了。另外,需要注意的是,矩阵所有的值加起来要是0.

pytorch实现高斯滤波器_pytorch实现高斯滤波器_11


  

4、均值模糊Box Filter (Averaging)

我们可以将当前像素和它的四邻域的像素一起取平均,然后再除以5,或者直接在滤波器的5个地方取0.2的值即可,如下图:

pytorch实现高斯滤波器_高斯滤波_12


  

  可以看到,这个模糊还是比较温柔的,我们可以把滤波器变大,这样就会变得粗暴了:注意要将和再除以13.

pytorch实现高斯滤波器_卷积_13


  

  所以,如果你想要更模糊的效果,加大滤波器的大小即可。或者对图像应用多次模糊也可以。

  

pytorch实现高斯滤波器_卷积_14


  

pytorch实现高斯滤波器_pytorch实现高斯滤波器_15


  

  


三、高斯模糊

均值模糊很简单,但不是很平滑。高斯模糊就有这个优点,所以被广泛用在图像降噪上。特别是在边缘检测之前,都会用来移除细节。高斯滤波器是一个低通滤波器。它将正态分布(又名”高斯分布”)用于图像处理。本质上,它是一种数据平滑技术(data smoothing),适用于多个场合,图像处理恰好提供了一个直观的应用实例。
  

1、高斯模糊的原理

所谓”模糊”,可以理解成每一个像素都取周边像素的平均值。

  

pytorch实现高斯滤波器_卷积_16


  上图中,2是中间点,周边点都是1。

  

pytorch实现高斯滤波器_高斯滤波_17


  “中间点”取”周围点”的平均值,就会变成1。在数值上,这是一种”平滑化”。在图形上,就相当于产生”模糊”效果,”中间点”失去细节。

  

pytorch实现高斯滤波器_卷积_18


  

显然,计算平均值时,取值范围越大,”模糊效果”越强烈。

  

pytorch实现高斯滤波器_高斯滤波_19


  上面分别是原图、模糊半径3像素、模糊半径10像素的效果。模糊半径越大,图像就越模糊。从数值角度看,就是数值越平滑。

  

  接下来的问题就是,既然每个点都要取周边像素的平均值,那么应该如何分配权重呢?

  如果使用简单平均,显然不是很合理,因为图像都是连续的,越靠近的点关系越密切,越远离的点关系越疏远。因此,加权平均更合理,距离越近的点权重越大,距离越远的点权重越小。

  

2、正态分布的权重

正态分布显然是一种可取的权重分配模式。

  

pytorch实现高斯滤波器_卷积_20


  在图形上,正态分布是一种钟形曲线,越接近中心,取值越大,越远离中心,取值越小。

  计算平均值的时候,我们只需要将”中心点”作为原点,其他点按照其在正态曲线上的位置,分配权重,就可以得到一个加权平均值。

  

3、高斯函数

上面的正态分布是一维的,图像都是二维的,所以我们需要二维的正态分布。

  

pytorch实现高斯滤波器_卷积_21


  

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

pytorch实现高斯滤波器_高斯滤波_22


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

  

pytorch实现高斯滤波器_卷积_23


  

  

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

  

pytorch实现高斯滤波器_线性滤波_24


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

  

4、权重矩阵

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

  

pytorch实现高斯滤波器_卷积_25


  更远的点以此类推。

  

  为了计算权重矩阵,需要设定σ的值。假定σ=1.5,则模糊半径为1的权重矩阵如下:

  

pytorch实现高斯滤波器_卷积_26


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

  

pytorch实现高斯滤波器_线性滤波_27


  

5、计算高斯模糊

有了权重矩阵,就可以计算高斯模糊的值了。

假设现有9个像素点,灰度值(0-255)如下:

  

pytorch实现高斯滤波器_卷积_28


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

  

pytorch实现高斯滤波器_卷积_29


  得到

  

pytorch实现高斯滤波器_高斯滤波_30


  将这9个值加起来,就是中心点的高斯模糊的值。

  对所有点重复这个过程,就得到了高斯模糊后的图像。如果原图是彩色图片,可以对RGB三个通道分别做高斯模糊。