4. 增益表生成方法:基于灰卡/均匀光源的采集
好,咱们进入正题。LSC 校正的核心,说白了就是一张增益表。这张表怎么来的?不是拍脑袋算出来的,得靠实际采集数据。我个人习惯用灰卡或者均匀光源来做这件事。你想想看,如果连参考图都不均匀,那校正出来的结果肯定也是歪的。
4.1 采集前的准备工作
先别急着架相机。有几个坑,我替你们踩过了,得先说清楚。
- 光源均匀性:用积分球或均匀面光源,中心到边缘亮度差异 < 2%
- 灰卡选择:18% 中性灰卡,避免偏色;不要用白纸,白纸的荧光增白剂会干扰
- 镜头光圈:建议用 F5.6~F8,避开镜头最佳光圈?不,恰恰要用实际使用光圈
- 色温固定:D65 或 D50,全程不要变
我曾经在一个项目里,用普通 LED 面板当均匀光源,结果校正完发现画面左上角总是偏暗。折腾了两天,最后拿照度计一测——那个 LED 面板本身就不均匀。嗯,从那以后我再也不敢省这个步骤了。
4.2 标准流程:四步走
整个流程我拆成四个步骤,每一步都有讲究。来,先看这张图,心里有个框架。
4.3 第一步:Raw 图采集
这一步看着简单,其实最容易出问题。我见过有人直接拿 JPEG 来算增益,结果全是马赛克——因为 JPEG 已经做过 gamma 和去马赛克了,数据早就不是线性的了。
- 格式:Raw 格式(DNG、RAW10、RAW12),不要用 JPEG/TIFF
- 曝光:让中心区域亮度达到满幅的 60%~80%,不要过曝
- 张数:同一场景拍 5~10 张,后期做平均降噪
- 检查:用 Raw 查看工具确认没有坏点、没有灰尘阴影
我会在采集前先拍一张暗场(盖上镜头盖),用来做黑电平校正。这个很多人会忘,但黑电平不准的话,增益表在暗部会严重偏大。
4.4 第二步:分块统计
拿到 Raw 图之后,我们要把它切成网格。为什么?因为增益表不可能每个像素单独算,那样数据量太大,而且噪声会跟着进去。
瑞芯微平台一般支持 16x16 或 32x32 的网格。我个人建议用 32x32,精度和计算量的平衡点比较好。
// 伪代码:分块统计均值
#define BLOCK_SIZE 32
#define IMG_W 1920
#define IMG_H 1080
int blocks_x = IMG_W / BLOCK_SIZE; // 60
int blocks_y = IMG_H / BLOCK_SIZE; // 33
float block_mean[blocks_y][blocks_x];
for (int by = 0; by < blocks_y; by++) {
for (int bx = 0; bx < blocks_x; bx++) {
uint64_t sum = 0;
for (int y = by*BLOCK_SIZE; y < (by+1)*BLOCK_SIZE; y++) {
for (int x = bx*BLOCK_SIZE; x < (bx+1)*BLOCK_SIZE; x++) {
sum += raw_image[y][x];
}
}
block_mean[by][bx] = (float)sum / (BLOCK_SIZE * BLOCK_SIZE);
}
}
这里要注意:如果你用的是 Bayer 格式,记得把 R、Gr、Gb、B 分开统计。四个通道的衰减特性不一样,混在一起算会出偏色。
4.5 第三步:计算增益
有了每个块的均值,接下来就是算增益。原理很简单:以中心块为基准,其他块除以中心块的值。
但这里有个细节——中心块不一定在正中心。因为镜头的光学中心可能和传感器中心有偏移。我建议的做法是:
- 先找出所有块中亮度最高的块(通常就是中心附近)
- 以这个块为基准,计算其他块的增益
- 增益值 = 基准块均值 / 当前块均值
增益值不要无限大。边缘区域如果太暗,增益会很大,同时也会放大噪声。我一般把增益上限设为 4.0(对应 12dB),超过的部分直接裁剪。你想想看,增益拉到 8 倍,暗部噪声也放大 8 倍,画面就没法看了。
4.6 第四步:平滑处理
算出来的增益表是离散的,直接拿去用会有块状效应。所以必须做平滑。常用的方法有两种:
| 方法 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 高斯滤波 | 对增益矩阵做 3x3 或 5x5 高斯卷积 | 实现简单,速度快 | 会轻微模糊边缘细节 |
| 多项式拟合 | 用 2阶/3阶多项式拟合增益曲面 | 平滑度高,抗噪声好 | 对镜头特性有假设 |
| 双边滤波 | 保留边缘的同时平滑 | 不会模糊真实的光学渐变 | 计算量大 |
我在瑞芯微平台上常用的是高斯滤波 + 多项式拟合的组合。先用高斯滤波去掉高频噪声,再用多项式拟合生成连续的增益曲面。这样既保证了平滑度,又不会丢失镜头的真实衰减特性。
曾经有个项目,镜头边缘衰减特别厉害,增益值从中心到边缘从 1.0 跳到了 3.5。直接用高斯滤波,边缘的增益被拉低了很多,校正完反而中间亮、边缘暗。后来我改成先做对数变换,再滤波,最后指数恢复——效果好了很多。这个技巧你可以记一下。
4.7 增益表格式与导出
瑞芯微平台通常要求增益表以特定格式存储。以 RKISP1 为例:
// 增益表结构(RKISP1 驱动格式)
struct rkisp_lsc_gain_table {
uint16_t r_gain[17][17]; // R 通道 17x17 网格
uint16_t gr_gain[17][17]; // Gr 通道
uint16_t gb_gain[17][17]; // Gb 通道
uint16_t b_gain[17][17]; // B 通道
uint16_t center_x; // 光学中心 X 坐标
uint16_t center_y; // 光学中心 Y 坐标
};
注意这里的 17x17 网格,是瑞芯微硬件插值引擎的固定规格。你算出来的 32x32 增益表,需要重采样到 17x17。重采样时建议用双线性插值,不要用最近邻,否则会有锯齿。
4.8 验证与调试
增益表生成完了,怎么知道对不对?我的验证流程是这样的:
- 肉眼检查:把增益表可视化,看看是不是从中心到边缘平滑过渡
- 校正测试:用同一张 Raw 图做 LSC 校正,看校正后的均匀性
- 量化指标:计算校正后图像四个角和中心的亮度差,要求 < 3%
- 偏色检查:R/G/B 三个通道的增益比例要一致,否则会出现色偏
- 四角与中心亮度差:< 3%
- 最大增益值:< 4.0
- 增益表平滑度:相邻网格增益变化 < 0.1
- 校正后无可见块状效应
嗯,到这里增益表生成的核心流程就讲完了。这套方法我在好几个项目里验证过,从手机摄像头到安防监控,基本都能用。关键就是每一步都要做扎实,尤其是采集这一步,源头数据不行,后面再怎么算都是白搭。