4. 增益表生成方法:基于灰卡/均匀光源的采集

好,咱们进入正题。LSC 校正的核心,说白了就是一张增益表。这张表怎么来的?不是拍脑袋算出来的,得靠实际采集数据。我个人习惯用灰卡或者均匀光源来做这件事。你想想看,如果连参考图都不均匀,那校正出来的结果肯定也是歪的。

4.1 采集前的准备工作

先别急着架相机。有几个坑,我替你们踩过了,得先说清楚。

⚠️ 采集环境要求
  • 光源均匀性:用积分球或均匀面光源,中心到边缘亮度差异 < 2%
  • 灰卡选择:18% 中性灰卡,避免偏色;不要用白纸,白纸的荧光增白剂会干扰
  • 镜头光圈:建议用 F5.6~F8,避开镜头最佳光圈?不,恰恰要用实际使用光圈
  • 色温固定:D65 或 D50,全程不要变

我曾经在一个项目里,用普通 LED 面板当均匀光源,结果校正完发现画面左上角总是偏暗。折腾了两天,最后拿照度计一测——那个 LED 面板本身就不均匀。嗯,从那以后我再也不敢省这个步骤了。

4.2 标准流程:四步走

整个流程我拆成四个步骤,每一步都有讲究。来,先看这张图,心里有个框架。

LSC 增益表生成标准流程 Raw 图采集 灰卡/均匀光源 分块统计 网格划分 + 均值 计算增益 中心归一化 平滑处理 滤波 + 拟合 关键说明 • Raw 图必须保存为 12bit/14bit 无损格式,不能有 ISP 自动处理 • 分块大小建议 32x32 或 64x64,太细会引入噪声,太粗会丢失细节 • 增益表最终要插值到图像分辨率,平滑处理直接影响校正质量

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 第三步:计算增益

有了每个块的均值,接下来就是算增益。原理很简单:以中心块为基准,其他块除以中心块的值。

但这里有个细节——中心块不一定在正中心。因为镜头的光学中心可能和传感器中心有偏移。我建议的做法是:

  1. 先找出所有块中亮度最高的块(通常就是中心附近)
  2. 以这个块为基准,计算其他块的增益
  3. 增益值 = 基准块均值 / 当前块均值
⚠️ 增益裁剪

增益值不要无限大。边缘区域如果太暗,增益会很大,同时也会放大噪声。我一般把增益上限设为 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 验证与调试

增益表生成完了,怎么知道对不对?我的验证流程是这样的:

  1. 肉眼检查:把增益表可视化,看看是不是从中心到边缘平滑过渡
  2. 校正测试:用同一张 Raw 图做 LSC 校正,看校正后的均匀性
  3. 量化指标:计算校正后图像四个角和中心的亮度差,要求 < 3%
  4. 偏色检查:R/G/B 三个通道的增益比例要一致,否则会出现色偏
验收标准(参考)
  • 四角与中心亮度差:< 3%
  • 最大增益值:< 4.0
  • 增益表平滑度:相邻网格增益变化 < 0.1
  • 校正后无可见块状效应

嗯,到这里增益表生成的核心流程就讲完了。这套方法我在好几个项目里验证过,从手机摄像头到安防监控,基本都能用。关键就是每一步都要做扎实,尤其是采集这一步,源头数据不行,后面再怎么算都是白搭。