在第一篇文章里面,我提到计算摄影学是计算机图形学,计算机视觉,光学和传感器等领域的交叉学科,在这个领域我们可以用强大的图像算法,对传感器所获取的信息做任意的处理,得到丰富多彩的效果。
那么,可以对图像做哪些处理呢?基本的处理包括如下两大类,
- 改变图像的像素值, 我们称为滤波(Filtering)
- 改变图像的像素位置,我们称为扭曲(Warping)
在接下来的几篇文章里面,我们都会重点探讨滤波问题。
一. 点处理
在滤波时,根据目标像素信息的来源,可以分为点操作和邻域操作两类。点操作是指目标像素仅仅依赖于对应的源像素,跟其他的像素没有关系。邻域操作则相反,事实上我们可以认为点操作是邻域操作的一种特殊实例。
下图中列出了一些典型的点操作,当你使用Python或Matlab这样的语言时,可以轻松的实现这些操作,可以参见这一章的Jupyter Notebook
在第2篇文章提到的相机内基本处理中,White Blalance, Color Transforms等操作都是点操作。
二. 线性移不变滤波器
2.1 基本概念
在邻域操作中,比较基础且重要的是一类称为线性移不变的滤波器,英文里叫做Linear Shift-Invariant Image Filtering。
这里:
- 线性,是指最终生成的像素值是由邻域像素值线性混合而成
- 移不变,是指不管对于哪个坐标的像素,其线性混合的系数都是一致的,不会因为像素坐标的变化而变化
一个非常典型的线性移不变滤波器是Box Filter,下图展示了它的工作原理。(注,这里可以看到图像的边缘像素因为没有足够的信息输入,所以在boxFilter后没有值可以填充,因此后文会介绍如何处理图像的边缘)
Box Filter
我们可以用boxFilter来对图像进行模糊,当调整它的核窗口大小时,可以得到不同程度的模糊结果。下图是用boxFilter对爱因斯坦照片进行模糊的结果:
线性移不变滤波器通常用卷积(Convolution)来实现,当处理一维信号时,卷积可以表示成:
例如,对方波信号进行滤波时,相关的函数为:
而到了二维图像,卷积则表示为:
3x3的box filter可以表示为:
这里我们可以很容易看到,如果图像的尺寸为HxW, 滤波器尺寸为NxN, 则二维滤波器的时间复杂度为O(WHN2), 那么有没有方法可以降低此复杂度呢?
一种典型的方法是将二维的滤波转换成两个一维滤波,例如:
这时,滤波器的时间复杂度会变为 O(2WHN)
2.2 更多实例
box filter可以平滑图像,但是它也有一些缺点,例如它平滑的效果不够自然,特别是在原始图像有比较密集的细节纹理时,boxFilter会产生网格状的效应,如下图所示。它产生的原因是box filter的滤波核决定了不管离中心像素多远的像素的权重都是一样的,这使得远离中心像素的信息在滤波后会融入到中心像素中。
一种更光滑的滤波器是高斯滤波(Gaussian Image Filter),它的公式和示意图如下
可以看到,在一个滤波核中,离中心点越远的像素权重越小。对于离散的数字图像,我们一般取半径为2~3σ的窗口大小作为滤波核的尺寸, 例如下面是一个典型的3x3的高斯滤波核:
下面的图可以明显看出Gaussian Filter和Box Filter的区别:
三. 图像梯度和边缘
3.1 图像的导数
有着基本高数知识的读者肯定知道,函数的变化率可以用其导数来求得,在函数值突变处的导数比其他地方大。对于图像来说也是一样,我们可以通过对图像求导数来得到图像的不连续处,进而获取图像的边缘。那么如何对图像求导呢,一般来说是通过有限差分函数来完成。其公式和1维表现形式是一个1x3的卷积核(水平梯度),或3x1的卷积核(垂直梯度):
直接对图像求导会受到噪声的干扰,因此一般需要对图像先做一次平滑,减少噪声的干扰,再做求导。例如,典型Sobel核,它的水平和垂直形式形式表现如下:
比较有趣的是,水平Sobel滤波核最终会凸显出图像的垂直线条,而垂直Sobel滤波核最终会凸显出图像的水平线条,如下图:
除了Sobel滤波核之外,还有很多滤波核,下面是典型的几种滤波核
3.2 图像的梯度和边缘
当有了图像的导数后,就可以得到图像的梯度,它定义为:
通过水平和垂直方向的导数,我们可以求得梯度的幅值和方向
下图是分别展示了水平求导结果、垂直求导结果,及梯度的幅值。可以很容易通过梯度来得到图像的边缘,以及边缘的方向。
3.2 DoG滤波器以及LoG滤波器
我们前面讲过,对图像求导很容易受到噪声的干扰,尽管如Sobel一类的滤波核已经包含了对图像的平滑处理来减轻噪声的影响,但当噪声很多时,依然不够。但可以采用同样的原理得到新的对噪声更鲁棒的滤波方式:
这里,f代表信号,h代表blur核,用于平滑图像。当h是高斯核且是一阶梯度时,我们称上式右边的下图单元为Derivative of Gaussian (DoG)滤波器。
上式等号左边的物理意义是先平滑图像,去除噪声的干扰,然后再求导。我们可以看看在一维情况下的表现:
按照等号左边来求导,会使得要做两次对原信号的卷积,计算量较大,而等式右边的形式则可以大大减轻计算量,因为它只需要做一次卷积即可,如下图所示,可以看到最终的结果和上图中的一致,但是计算量少了很多。
DoG滤波器可以得到图像的边缘信息,而且对噪声比较鲁棒,在二维形式下它的示意图如下
DoG实际上是由一个高斯核和一个一阶梯度核组成,我们还可以使用高斯核和二阶梯度核来构成另外一种滤波器,即Laplacian of Gaussian (LoG)滤波器。
先来看看laplacian滤波器,它可以用二阶有限差分来获得,如下图展示了水平laplacian滤波器
这样,如果我们按照同样的原理组合上高斯核,就可以得到LoG滤波器,下面是一维情况下的示意:
可以很容易观察到,函数的跳变处恰好就是二阶导数过零点的地方。在图像中,这也就是边缘所在的位置。
来比较下几个滤波器吧:
下图展示了直接使用Laplacian滤波器和使用LoG滤波器来获取边缘的效果对比,由于Laplacian滤波器对噪声非常敏感,因此可以看到其结果中会出现大量的非边缘响应,这些都是噪声所在的位置。而LoG滤波器的结果则很干净:
当与DoG相比时,结果如下。可以看到DoG得到的图像边缘通常比较粗,由多个像素组成,而LoG则相对来说可以得到更加准确的边缘。
四. 总结
这篇帖子主要介绍了图像的线性移不变滤波器,它只是所有可能的图像变换中的一种基本形式。在后面的帖子中,我还会进一步介绍更多的图像变换的知识,感谢你的阅读。
我在如下的Jupyter Notebook中展示了本帖中的相关操作,你可以对着它获取更深入的理解,也能够进一步掌握用Python来进行图像处理的一些技巧。
nbviewer.jupyter.org/gi
跟这一系列专题文章相关的Notebook可以从github.com/yourwanghao/获取
参考资料:
这一篇文章的绝大部分素材来自于
[1] CMU 2017 Fall Computational Photography Course 15-463, Lecture 3
如果不做特别说明,素材均来自于[1]
我也会参考下面的重要资料中的内容
[2] Richard Szeliski, Computer Vision : Algorithms and Applications, Section 3.2