4、图像数据准备:标准测试图像获取与RAW格式解析
做3A算法仿真,第一步不是调参数,而是找对图。
我见过不少新人,上来就用手机随手拍的照片做测试。结果算法调得再好,换到标准数据集上就崩了。说白了,没有标准测试图像,你的算法就是闭着眼睛走路。
这一章,我们就把图像数据准备这件事聊透。从数据集选择,到RAW格式解析,再到Bayer阵列与去马赛克,每一步我都会把实际项目中的坑指给你看。
4.1 标准测试图像数据集
做3A算法仿真,有三套数据集是绕不开的:Kodak、MIT、RAISE。它们各有各的脾气,我分别说说。
4.1.1 Kodak数据集
Kodak数据集是图像处理领域的“老黄牛”。它包含24张真彩色图像,分辨率从768×512到2048×1536不等。这些图像的特点是色彩丰富、纹理细腻,非常适合做白平衡和色彩校正的测试。
我个人习惯用Kodak做算法初调。为什么?因为它图像质量高,噪声低,能让你先排除传感器噪声的干扰,专心调核心参数。
4.1.2 MIT数据集
MIT数据集由麻省理工学院提供,包含多组不同光照条件下的场景图像。它的特点是同一场景有多个色温版本,非常适合做自动白平衡(AWB)的评估。
我记得有一次做AWB算法对比,用Kodak跑出来的结果都差不多,换到MIT数据集上,差距一下子就拉开了。MIT的“多光照”特性,能逼出算法的真实水平。
| 数据集 | 图像数量 | 分辨率范围 | 主要用途 | 注意事项 |
|---|---|---|---|---|
| Kodak | 24 | 768×512 ~ 2048×1536 | 白平衡、色彩校正初调 | 数量少,仅适合验证 |
| MIT | 多组(每组多光照) | 约 1024×768 | AWB算法评估 | 光照标注精确,适合定量分析 |
| RAISE | 8156 | 4288×2848 ~ 7360×4912 | 噪声建模、去马赛克训练 | RAW格式,需配套解析工具 |
4.1.3 RAISE数据集
RAISE数据集是这三个里面我最常用的。它包含8156张高分辨率RAW图像,全部来自消费级相机。分辨率从1200万像素到3600万像素不等。
RAISE最大的价值在于:它提供了原始RAW文件。这意味着你可以完全控制从Bayer数据到最终图像的每一个环节。做去马赛克算法、噪声建模、HDR合成,RAISE都是首选。
4.2 RAW图像格式解析
RAW格式是什么?说白了,它就是传感器“看到”的原始数据,未经任何处理。JPEG是“做好的菜”,RAW是“刚买回来的菜”。
你想想看,做3A算法,你肯定要从原材料开始调,而不是从成品菜里反推配方。所以理解RAW格式是基本功。
4.2.1 RAW文件结构
一个典型的RAW文件包含以下几个部分:
- 文件头: 包含相机型号、ISO、快门速度、白平衡设置等元数据
- 图像数据: 传感器输出的原始像素值,通常是12位或14位
- 缩略图: 相机生成的预览JPEG图像
- 附加数据: 镜头校正参数、黑电平、增益映射等
我曾经在解析某品牌相机的RAW文件时,发现它的黑电平数据藏在文件头的第1024字节偏移处,而不是标准位置。这种“非标”设计,让我多花了三天时间调试。
4.2.2 常用RAW解析库
做仿真时,我不建议自己从头写RAW解析器。直接用现成的库,省时省力。
# 使用 rawpy 解析 RAW 文件
import rawpy
import numpy as np
# 读取 RAW 文件
raw = rawpy.imread('sample.NEF')
# 获取 Bayer 原始数据(未处理)
bayer_raw = raw.raw_image # 形状: (H, W),uint16
# 获取黑电平和白电平
black_level = raw.black_level_per_channel
white_level = raw.white_level
# 获取颜色校正矩阵(CCM)
ccm = raw.color_matrix
# 获取白平衡增益
wb_gains = raw.camera_whitebalance
print(f"图像尺寸: {bayer_raw.shape}")
print(f"黑电平: {black_level}")
print(f"白电平: {white_level}")
4.3 Bayer阵列与去马赛克基础
大多数相机传感器使用Bayer阵列。它用红、绿、蓝三种滤色片覆盖在像素上,每个像素只记录一种颜色。绿色像素数量是红色和蓝色的两倍,因为人眼对绿色更敏感。
4.3.1 Bayer阵列模式
最常见的Bayer模式是RGGB,也有BGGR、GRBG、GBRG等变体。不同相机厂商用的模式不一样。
# RGGB 模式的 4x4 像素块
# R G R G
# G B G B
# R G R G
# G B G B
# 用代码生成 Bayer 掩码
def get_bayer_mask(shape, pattern='RGGB'):
h, w = shape
mask_r = np.zeros((h, w), dtype=bool)
mask_g = np.zeros((h, w), dtype=bool)
mask_b = np.zeros((h, w), dtype=bool)
if pattern == 'RGGB':
mask_r[0::2, 0::2] = True
mask_g[0::2, 1::2] = True
mask_g[1::2, 0::2] = True
mask_b[1::2, 1::2] = True
elif pattern == 'BGGR':
mask_b[0::2, 0::2] = True
mask_g[0::2, 1::2] = True
mask_g[1::2, 0::2] = True
mask_r[1::2, 1::2] = True
# ... 其他模式类似
return mask_r, mask_g, mask_b
4.3.2 去马赛克算法
去马赛克(Demosaicing)就是从Bayer数据恢复出完整RGB图像的过程。最简单的算法是双线性插值,但效果一般。实际项目中常用的是自适应插值或基于边缘导向的算法。
我刚开始做去马赛克时,用双线性插值跑出来的图像边缘全是锯齿。后来换成基于梯度的插值,效果好了很多。但要注意,没有一种算法是万能的——纹理丰富的区域和平坦区域需要不同的处理策略。
4.4 本章知识体系
下面这张图,我把本章的核心知识点串了起来。你可以把它当作一个快速索引。
4.5 实践建议
说了这么多,最后给几条实操建议:
- 先下载RAISE数据集的一个子集(比如100张),验证你的解析流程没问题,再下载全集。不然硬盘空间浪费了,时间也浪费了。
- 写一个统一的RAW加载器,封装rawpy的调用,统一输出格式。这样后续换数据集时,只需要改配置文件,不用改代码。
- 去马赛克算法不要一上来就搞复杂的。先用双线性插值跑通整个流程,再逐步替换成更高级的算法。这样能快速定位问题出在哪个环节。