文章目录
什么是AAF
我们知道RAW图中记录的是每个点其实记录的是一种颜色, 但是平时我们看到图像上每个点基本都是RGB三色通道的图,那么我们就需要通过"去马赛克"算法把RAW中每个点的其它通道的值补回来, 比如针对R通道的数据,它需要通过周围像素的G和B通道的值,来推算出它的G和B通道的值.
-
产生了问题:
如果拍的图像有非常细密的纹理(如细密的格子衫,百叶窗). 这些纹理的细节比传感器的排列阵列还密集的话,那么传感器采集到信息有缺失,导致去马赛克后颜色失真. 再举个例子,比如夜晚透过细密的防蚊窗纱看远处的灯,我们可以再窗纱上看到弯曲亮带.
如下图1 ,因为细纹间距超过了像素间距,无法准确采样的亮暗变换的纹理,
图2 中,间距较大没问题,像素能采集到对应准确的颜色.

-
什么是"奈奎斯特频率"?(相机的视力极限)
我们可以把它理解为相机传感器能分辨的"最高清晰度极限"。
如果场景里的细节超过了这个极限(比如极其细密的条纹),相机就无能为力了,强行记录只会变成一团乱码(也就是前面说的伪彩色)。
-
什么是"AAF 抗混叠滤波"?(提前打马赛克)
既然相机有"视力极限",为了防止它在极限边缘"猜错颜色"产生难看的伪彩,工程师想出了一个聪明的办法:在算法去猜颜色之前,先主动把那些超出相机极限的、极其细密的纹理给模糊掉 。
这个"提前模糊"的动作,就是 AAF(抗混叠滤波)。
它就像一个筛子(低通滤波器),把那些会导致算法出错的、过于细密的纹理(高于奈奎斯特频率的分量)直接过滤掉。虽然牺牲了一点点极限锐度,但保证了算法在"猜"颜色时不会出错,从而避免了画面出现奇怪的伪彩色。
AAF算法原理
在 Bayer RAW 图像去马赛克之前,高频信号(纹理细节)与 Bayer 阵列的空间采样频率可能发生混叠,产生伪彩色。AAF 在 Bayer 域对图像进行低通滤波,抑制高于奈奎斯特频率的分量。
滤波器核
[[1, 0, 1, 0, 1],
[0, 0, 0, 0, 0],
[1, 0, 8, 0, 1], / 16
[0, 0, 0, 0, 0],
[1, 0, 1, 0, 1]]
中心权重为 8,四角权重为 1,总权重 = 8 + 8×1 = 16(归一化)。
设计要点: 偶数位置系数为 0,使得滤波仅在同色像素间进行(步长 2)。R 位置的滤波只使用周围 R 像素,G/B 同理。这避免了不同颜色通道的混叠。
AAF算法python代码
实现细节
使用 scipy.ndimage.correlate 实现卷积,效率较高
实际卷积操作跨越整个 5×5 邻域,但相邻颜色位置系数为 0,等效于只对同色像素低通. 这里其实就一个加权求平均的操作,当前像素的权重最大.
python
class AAF:
'Anti-aliasing Filter'
def __init__(self, img):
self.img = img
def padding(self):
img_pad = np.pad(self.img, (2, 2), 'reflect')
return img_pad
def execute(self):
img_pad = self.padding()
raw_h = self.img.shape[0]
raw_w = self.img.shape[1]
aaf_img = correlate(self.img, np.array([[1, 0, 1, 0, 1],
[0, 0, 0, 0, 0],
[1, 0, 8, 0, 1],
[0, 0, 0, 0, 0],
[1, 0, 1, 0, 1]])/16)
self.img = aaf_img
return self.img
AAF测试代码
测试代码生成一个32x32的的图像,因为AAF其实就是一个低通滤波的效果.它对每个像素周围5x5邻域内的像素,做加权平均的运算,平滑图像.
python
def test_lowpass_reduces_variance(self):
"""含噪图像经 AAF 后方差应减小(低通效果)。"""
rng = np.random.default_rng(42)
img = 150 + rng.integers(-100, 100, size=(32, 32), dtype=np.int16)
img = img.astype(float)
aaf = AAF(img.copy())
out = aaf.execute()
show_bayer_images(img, out, "left", "right-AAF")
self.assertLess(float(out.std()), float(img.std()),
"AAF 未减小图像方差,低通效果不明显")
- 测试效果
AAF 之后图像变的平滑了许多.
