ISP RGB 域之 CCM
Why?
我们肉眼的对光谱的 RGB 响应曲线和 sensor 的响应曲线是不同的;
CCM 一般是 3x3 矩阵形式,也有 3x4 形式的,3x4 形式主要是给 rgb 各自加一个 offset
\[ \begin{bmatrix} R_{out} \\ G_{out} \\ B_{out} \end{bmatrix} = \begin{bmatrix} CC_{00} & CC_{01} & CC_{02}\\ CC_{10} & CC_{11} & CC_{12}\\ CC_{20} & CC_{21} & CC_{22} \end{bmatrix} \ast \begin{bmatrix} R_{in} \\ G_{in} \\ B_{in} \end{bmatrix} \]
\[ \begin{bmatrix} R_{out} \\ G_{out} \\ B_{out} \end{bmatrix} = \begin{bmatrix} CC_{00} & CC_{01} & CC_{02} & OFFSET_r\\ CC_{10} & CC_{11} & CC_{12} & OFFSET_g\\ CC_{20} & CC_{21} & CC_{22} & OFFSET_b \end{bmatrix} \ast \begin{bmatrix} R_{in} \\ G_{in} \\ B_{in} \end{bmatrix} \]
上面的人眼 rgb 响应和 sensor rgb 响应曲线都是非线性的,所以指望通过一个 CCM 矩阵就得到匹配度很好的映射关系是不现实的。现实中,往往会标定很多个 CCM,ISP 在运行的时候根据照度,光源等等因素,选择两个最近的 CCM 插值得到最终的 CCM;
CCM 模块在 apply awb gain 后面,因此 3x3 个值存在约束条件:
\[ CC_{00} + CC_{01} + CC_{02} = 1 CC_{10} + CC_{11} + CC_{12} = 1 CC_{20} + CC_{21} + CC_{22} = 1 \]
保证灰点也就是 r=g=b 的点,经过 CCM 以后仍然 r=g=b;
标定 CCM 方法
用 camera 拍一张某个色温下的 24 色卡 raw 文件:注意 shading 影响,拍这个色卡占整个 sensor 中间一小部分就可以。
raw 文件预处理。主要包括减 blc,根据第 4 行的 patch,获取 awb gain 值,乘上去;这样就拿到了这个色温下 24 个 patch 的 rgb 值。
理想 rgb 值。
这是色卡厂家提供的 24 个 patch 的标准 rgb 空间下的理论值;拿到这个值以后,需要进行反 gamma 处理,因为厂家提供的是 srgb 的值,是带了 2.2gamma 的,ISP 的 CCM 模块一般是在 gamma 前面,因此要对理论值进行反 gamma 处理;
标定算法
已知 100 个 raw rgb 值,已知对应的理论 rgb 值;求一个 3x3 线性变换矩阵;这个矩阵要使得映射后的 rgb 值尽可能的接近理论值;
借鉴深度学习的梯度下降方法,可以快速得到 CCM;并且可以自定义 100 个 patch 的重要程度,使得某些 patch 的误差非常小。
定义损失和梯度函数,测量 rgb 值得差异,采用 L2 距离;
\[ L_i = {\textstyle \sum_{n=1}^{18}} (CCM \ast RGB_{origin} - RGB_{standard})^2 \]
完整代码如下:
1 | from mpl_toolkits.mplot3d import Axes3D |
可视化看一下映射后的点与理论点的距离:
参考文献
https://zhuanlan.zhihu.com/p/108626480