Category:Higher Mathematics & Computer Graphics Application
正文
9 信号处理
9.4 图像信号处理
到目前为止,我们已经抽象地讨论了采样、滤波和重建,主要使用 1D 信号作为示例。但正如我们在本章开头所观察到的,信号处理在图形中最重要和最常见的应用是采样图像。让我们仔细看看这一切是如何应用于图像的。
9.4.1 使用离散滤波器的图像滤波
也许卷积最简单的应用是使用离散卷积处理图像。图像处理程序的一些最广泛使用的特性是简单的卷积滤波器。图像模糊可以通过与许多常见的低通滤波器进行卷积来实现,范围从框到高斯(图 9.31)。
高斯过滤器会产生非常平滑的模糊效果,通常用于此目的。
与模糊相反的是锐化,一种方法是使用“反锐化蒙版”程序:从原始图像中减去一部分 α。通过重新调整以避免改变整体亮度,我们有
其中 fg,σ 是宽度为 σ 的高斯滤波器。使用离散的 impluse d 和卷积的分布特性,我们能够将整个过程写成一个依赖于模糊宽度和锐化程度的单个滤波器(图 9.32)。
组合两个离散过滤器的另一个示例是投影。通常采用模糊的、移动的对象轮廓副本来创建柔和的阴影(图 9.33)。我们可以将移位操作表示为带有偏离中心脉冲的卷积:
通过与两个过滤器进行卷积来实现移位,然后是模糊:
在这里,我们使用关联性将两个操作分组为具有三个参数的单个过滤器。
9.4.2 图像采样中的抗锯齿
在图像合成中,我们经常需要生成图像的采样表示,我们有一个连续的数学公式(或者至少一个我们可以用来计算任何点的颜色的过程,而不仅仅是整数像素位置)。光线追踪是一个常见的例子;更多关于光线追踪和抗锯齿的具体方法在第 4 章。在信号处理的语言中,我们有一个连续的 2D 信号(图像),我们需要在规则的 2D 点阵上对其进行采样。如果我们在没有任何特殊措施的情况下继续对图像进行采样,结果将显示出各种混叠伪影(图 9.34)。
在图像的锐利边缘,我们会看到被称为“锯齿”的阶梯状伪影。在有重复图案的区域,我们会看到被称为云纹图案的宽带。
这里的问题是图像包含太多小尺度特征;我们需要在采样前通过过滤来平滑它。回顾方程(9.3)中连续卷积的定义,我们需要在像素位置周围的区域上对图像进行平均,而不是仅仅取单个点的值。具体方法在第 4 章中讨论。像盒子这样的简单过滤器可以改善锐利边缘的外观,但它仍然会产生一些莫尔条纹(图 9.35)。非常平滑的高斯滤波器对莫尔条纹图案更有效,但总体上会更加模糊。这两个示例说明了锐度和混叠之间的权衡,这是选择抗混叠滤波器的基础。
9.4.3 重构和重采样
仔细过滤至关重要的最常见的图像操作之一是重采样——改变采样率,或改变图像大小。 假设我们使用 3000 x 2000 像素大小的数码相机拍摄了一张图像,并且我们希望将其显示在只有 1280 x 1024 像素的监视器上。为了使它适合,在保持 3:2 纵横比的同时,我们需要将其重新采样为 1278 x 852 像素。我们应该怎么做呢?
解决这个问题的一种方法是将这个过程视为丢弃像素:大小比率在 2 到 3 之间,因此我们必须在保留的像素之间丢弃一两个像素。用这种方法可以缩小图像,但结果质量很低——图 9.34 中的图像是使用像素删除制作的。然而,像素下降非常快,在交互式操作期间预览调整大小的图像是一个合理的选择。
考虑调整图像大小的方法是重新采样操作:我们想要一组图像在由新图像尺寸定义的特定网格上的样本,我们通过对从输入重建的连续函数进行采样来获得它们样本(图 9.36)。这样看,它只是一系列标准图像处理操作:首先,我们从输入样本中重建一个连续函数,然后我们对该函数进行采样,就像我们对任何其他连续图像进行采样一样。为了避免混叠伪影,需要在每个阶段使用适当的过滤器。
一个小例子如图 9.37 所示:如果原始图像是 12 × 9 像素,而新图像是 8 × 6 像素,则每个维度的输出像素是输入像素的 2/3,因此它们在图像上的间距是原始样本间距的 3/2。
为了得出每个输出样本的值,我们需要以某种方式计算样本之间图像的值。 pixeldropping 算法为我们提供了一种方法:只需取 t 的值他在输入图像中最接近的样本并将其作为输出值。这完全等同于使用 1 像素宽(半径为二分之一)的框滤波器重建图像,然后进行点采样。
当然,如果选择像素丢弃或其他非常简单的过滤的主要原因是性能,那么人们永远不会将该方法作为一般重建和重采样过程的特例来实现。事实上,由于不连续性,盒式过滤器很难在通用框架中工作。但是,对于高质量的重采样,重建/采样框架提供了宝贵的灵活性。
要计算出算法细节,最简单的方法是下拉到 1D 并讨论对序列重新采样。编写实现的最简单方法是根据我们在第 9.2.5 节中定义的重构函数。
参数 x0 给出了新序列的第一个样本相对于旧序列的样本的位置。也就是说,如果第一个输出样本落在输入序列中样本 3 和 4 的中间,则 x0 为 3.5。
此过程通过将输入序列与连续滤波器进行卷积来重建连续图像,然后对其进行点采样。这并不是说这两个操作是顺序发生的——连续函数仅在原则上存在,其值仅在样本点处计算。但在数学上,该函数计算函数 a * f 的一组点样本。
但是,这种点采样似乎是错误的,因为我们刚刚说完应该使用适当的平滑滤波器对信号进行采样以避免混叠。我们应该将重构函数与采样滤波器 g 和点采样 g * (f * a) 进行卷积。但由于这与 (g * f) * a 相同,我们可以将采样滤波器与重构滤波器一起滚动;我们只需要一个卷积操作(图 9.38)。
这种组合的重建和采样滤波器称为重采样滤波器。重新采样图像时,我们通常以旧图像为单位指定一个源矩形,该矩形指定我们要保留在新图像中的部分。例如,使用第 3 章中的像素样本定位约定,我们用来重新采样整个图像的矩形是
给定一个源矩形 (xl, xh) × (yl, yh),新图像的样本间距为
左下角的样本位于 (xl +Δx/2, yl +Δy/2)。
修改一维伪代码以使用此约定,并将对重构函数的调用扩展为隐含的双循环,我们得出:
此例程包含重新采样图像的所有基础知识。最后一个有待解决的问题是在图像边缘做什么,这里的简单版本将超出输入序列的范围。我们可能会做几件事: • 在序列的末尾停止循环。这相当于用零填充图像。
• 将所有数组访问剪辑到序列的末尾——也就是说,当我们想要访问a[-1] 时返回a[0]。这相当于通过扩展最后一行或最后一列来填充图像的边缘。
• 当我们接近边缘时修改过滤器,使其不会超出序列的边界。
当我们重新采样整个图像时,第一个选项会导致边缘暗淡,这并不令人满意。第二种选择很容易实现;第三个可能是表现最好的。修改图像边缘附近的过滤器的最简单方法是对其进行重新归一化:将过滤器除以落在图像内的过滤器部分的总和。这样,过滤器总是在实际图像样本上加 1,因此它保留了图像强度。出于性能考虑,最好将边缘过滤器半径内的像素带(需要重新归一化)与中心(包含更多像素并且不需要重新归一化)分开处理。
重采样滤波器的选择很重要。有两个独立的问题:过滤器的形状和大小(半径)。由于滤波器既作为重构滤波器又作为采样滤波器,这两种角色的要求都会影响滤波器的选择。对于重建,我们需要一个足够平滑的滤波器,以避免在放大图像时出现混叠伪影,并且滤波器应该是无波纹的。对于采样,滤波器应该足够大以避免欠采样,并且足够平滑以避免摩尔纹伪影。图 9.39 说明了这两种不同的需求。
一般我们会选择一个f根据输入和输出的相对分辨率过滤形状并对其进行缩放。两种分辨率中较低的一个决定了滤波器的大小:当输出比输入更粗采样时(下采样,或缩小图像),正确采样所需的平滑大于重建所需的平滑,因此我们调整大小根据输出样本间距(图 9.39 中的半径 3)进行过滤。另一方面,当输出被更精细地采样(上采样或放大图像)时,重建所需的平滑占主导地位(重建的函数已经足够平滑,可以以比开始时更高的速率进行采样),所以滤波器由输入样本间距(图 9.39 中的半径 1)确定。
选择过滤器本身就是速度和质量之间的权衡。常见的选择是箱式过滤器(当速度至关重要时)、帐篷式过滤器(中等质量)或分段立方(优质)。在分段三次的情况下,可以通过在 fB 和 fC 之间进行插值来调整平滑度; Mitchell-Netravali 过滤器是一个不错的选择。
就像图像过滤一样,可分离过滤器可以提供显着的加速。基本思想是首先对所有行重新采样,生成一个宽度改变但高度不变的图像,然后重新采样该图像的列以产生最终结果(图 9.40)。修改前面给出的伪代码以利用这种优化是相当简单的。