跳转至

Image Processing⚓︎

1450 个字 预计阅读时间 7 分钟

Basics⚓︎

常见的一些图像处理操作有:

  • 增加对比度(contrast)

    • 通过 S 曲线,对每个像素做这样的转换:output(x, y) = f(input(x, y))

  • 图像(颜色)反转(invert)

    • 对每个像素的处理位:out(x, y) = 1 - in(x, y)
  • 模糊(blur)

    • 利用边缘检测(edge detection) 技术,我们可以实现更“聪明”的模糊(即不会模糊整张图,仍然保留物体边缘特征)

      例子

  • 锐化(sharpen)

下面主要介绍模糊这一操作。在此之前,我们得先理解它的数学基础——卷积(convolution)。

Convolution⚓︎

卷积公式如下:

考虑最简单的情况——单位面积的盒状函数 \(f(x)\)——有助于我们理解卷积操作:

\(g(x)\) 是输入图像,得到的输出图像上的每个像素是 \([x - 0.5, x + 0.5]\) 范围内像素的均值,从而起到模糊效果。

下面从一维角度看这个求均值的过程,可能更好理解些:

前面给出的卷积公式是连续的。不过对于图像处理,我们只要考虑离散(discrete) 的二维卷积公式就行了,所以公式中的积分可以用累加替换,即:

其实等号左侧的 g 应该写成 I,特指图像。

为方便操作,我们将滤波器(filter) \(f(i, j)\) 限制在 \(-1 \le i, j \le 1\) 的范围内,于是: $$ (f*I)(x,y)=\sum_{i,j=-1}^1f(i,j)I(x-i,y-j) $$

此时 \(f(i, j)\) 可以用一个 \(3 \times 3\) 的矩阵表示,每一个元素的值记作 \(f(i, j) = \mathbf{F}_{i, j}\)(通常称为滤波权重(filter weight) / 滤波核(filter kernel)

下图更加形象地展示离散 2D 卷积的过程:

我们需要考虑滤波器扫描到图像边界上的特殊情况,因为此时滤波器的一部分不在图像内。一般有以下几种填充手段 (padding)

  • 零值
  • 边值
  • 对称
  • ...

Blur⚓︎

最简单的盒模糊(box blur)(滤波器大小:7x7)

Gaussian Blur⚓︎

通过 2D 高斯函数获取滤波器的系数: $$ f(i,j)=\frac{1}{2\pi\sigma2}e{-\frac{i2+j2}{2\sigma^2}} $$

输出图像的每个像素就是滤波器范围内像素值的加权和,这些邻近像素的贡献随距离增加而衰减(想想正态曲线。虽然理论上正态曲线会无限接近但不等于 0,但是实际操作时出于效率,超出一定距离外的像素就不给予考虑。

滤波器大小为 7x7 高斯模糊效果如下,可以看到模糊后的图像不会真的糊成一团,图像的原特征还是得到一定保留的(比如砖头间的缝隙等


(3x3)锐化的滤波器大致长这样:

\[ \begin{bmatrix} 0 & -1 & 0 \\ -1 & 5 & -1 \\ 0 & -1 & 0 \end{bmatrix} \]

效果:

锐化操作的本质是向图像增加高频信号

  • I 为原图像
  • 图像中的高频信号:I' = I - Blur(I)
  • 锐化后的图像:I = I + I'
例子


以下两个矩阵分别对应检测垂直水平边的滤波器:

\[ \begin{bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{bmatrix} \quad \begin{bmatrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1 \end{bmatrix} \]

这些滤波器统称为梯度检测滤波器(gradient detection filter)。以下是这些滤波器的使用效果:

我们可以将滤波器视为一种模式的“探测器”(detector),输出图像中的像素值 = 滤波器对输入图像中每个像素周围区域的“响应”(这也是 CV 中的常见解释


一种更强大但复杂的滤波(模糊)手段叫做双边滤波(bilateral filter),它的作用是在去除图像噪声的同时保留图像原有的边缘特征。

例子

双边滤波的原理图:

滤波核的内容取决于图像内容。

Image Sampling⚓︎

一种对图像的常用操作是缩放(resize)。

缩放操作涉及到对图像的采样(sampling),比如缩小图像就是一个降采样(down-sampling) 的过程:

后续内容参见我的 CG 笔记中关于反走样的介绍。

Image Maginification⚓︎

另一种对图像的缩放就是图像放大(image maganification)。

而图像放大的过程本质上是升采样(up-sampling)。

这显然会遇到一个问题:如何插入这些原本不存在的像素呢?解决方案就是插值(interpolation)。

Interpolation⚓︎

下面列举一些插值方式:

  • 最近邻居插值(nearest-neighbor interpolation):不够连续和平滑

  • 线性插值(linear interpolation):连续但不平滑

  • 三次插值(cubic interpolation):连续且平滑

  • 双线性插值(bilinear interpolation)

例子:超分辨率 (super-resolution)

Changing Aspect Ratio⚓︎

如果处理不当,仅通过缩放图像(不是剪切 (cropping))来改变图像宽高比会导致图像内容的变形 (distortion)

这篇论文给出了解决方案:

下面就来阐述其中的思想。

  • 问题陈述:我们需要移除图像每行的 n 个像素
  • 基本思路:移除“不重要”的像素

那么如何衡量一个像素的重要性呢?一种简单的思路是:构成边缘的像素就是重要像素。

接缝裁剪(seam carving):自顶向下寻找像素的连接路径,其边缘能量为最小。

$\mathbf{M}(i, j) = $ 经过像素 \((i, j)\) 的缝 (seam) 的最小边缘能量,那么 $$ \mathbf{M}(i,j){=}E(i,j)+\min(\mathbf{M}(i-1,j-1),\mathbf{M}(i-1,j),\mathbf{M}(i-1,j+1)) $$

该计算可通过动态规划完成。

结果

还可通过接缝插入来放大图像:

思路:寻找需要插入的 k 条缝,然后插值像素。

评论区

如果大家有什么问题或想法,欢迎在下方留言~