![]() |
OpenCV 4.12.0
开源计算机视觉
|
色彩校正的目的是将输入和输出设备的色彩响应调整到已知状态。被校准的设备有时被称为校准源;用作标准的色彩空间有时被称为校准目标。色彩校准已广泛应用于许多行业,如电视制作、游戏、摄影、工程、化学、医学等。由于输入和输出设备的制造过程,通道响应存在非线性失真。为了校正设备的图像输出,有必要校准捕获的颜色和实际颜色。
类 | |
| 类 | cv::ccm::ColorCorrectionModel |
| ccm 模型的核心类。 更多... | |
| enum cv::ccm::CCM_TYPE |
#include <opencv2/mcc/ccm.hpp>
ccm 可能类型的枚举。
| 枚举器 | |
|---|---|
| CCM_3x3 Python: cv.ccm.CCM_3x3 | 形状为 \(3\times3\) 的 CCM 对颜色值执行线性变换。 |
| CCM_4x3 Python: cv.ccm.CCM_4x3 | 形状为 \(4\times3\) 的 CCM 执行仿射变换。 |
| enum cv::ccm::COLOR_SPACE |
#include <opencv2/mcc/ccm.hpp>
| 枚举器 | |
|---|---|
| COLOR_SPACE_sRGB Python: cv.ccm.COLOR_SPACE_sRGB | https://en.wikipedia.org/wiki/SRGB , RGB 色彩空间 |
| COLOR_SPACE_sRGBL Python: cv.ccm.COLOR_SPACE_sRGBL | https://en.wikipedia.org/wiki/SRGB , 线性 RGB 色彩空间 |
| COLOR_SPACE_AdobeRGB Python: cv.ccm.COLOR_SPACE_AdobeRGB | https://en.wikipedia.org/wiki/Adobe_RGB_color_space , RGB 色彩空间 |
| COLOR_SPACE_AdobeRGBL Python: cv.ccm.COLOR_SPACE_AdobeRGBL | https://en.wikipedia.org/wiki/Adobe_RGB_color_space , 线性 RGB 色彩空间 |
| COLOR_SPACE_WideGamutRGB Python: cv.ccm.COLOR_SPACE_WideGamutRGB | https://en.wikipedia.org/wiki/Wide-gamut_RGB_color_space , RGB 色彩空间 |
| COLOR_SPACE_WideGamutRGBL Python: cv.ccm.COLOR_SPACE_WideGamutRGBL | https://en.wikipedia.org/wiki/Wide-gamut_RGB_color_space , 线性 RGB 色彩空间 |
| COLOR_SPACE_ProPhotoRGB Python: cv.ccm.COLOR_SPACE_ProPhotoRGB | https://en.wikipedia.org/wiki/ProPhoto_RGB_color_space , RGB 色彩空间 |
| COLOR_SPACE_ProPhotoRGBL Python: cv.ccm.COLOR_SPACE_ProPhotoRGBL | https://en.wikipedia.org/wiki/ProPhoto_RGB_color_space , 线性 RGB 色彩空间 |
| COLOR_SPACE_DCI_P3_RGB Python: cv.ccm.COLOR_SPACE_DCI_P3_RGB | https://en.wikipedia.org/wiki/DCI-P3 , RGB 色彩空间 |
| COLOR_SPACE_DCI_P3_RGBL Python: cv.ccm.COLOR_SPACE_DCI_P3_RGBL | https://en.wikipedia.org/wiki/DCI-P3 , 线性 RGB 色彩空间 |
| COLOR_SPACE_AppleRGB Python: cv.ccm.COLOR_SPACE_AppleRGB | |
| COLOR_SPACE_AppleRGBL Python: cv.ccm.COLOR_SPACE_AppleRGBL | https://en.wikipedia.org/wiki/RGB_color_space , 线性 RGB 色彩空间 |
| COLOR_SPACE_REC_709_RGB Python: cv.ccm.COLOR_SPACE_REC_709_RGB | https://en.wikipedia.org/wiki/Rec._709 , RGB 色彩空间 |
| COLOR_SPACE_REC_709_RGBL Python: cv.ccm.COLOR_SPACE_REC_709_RGBL | https://en.wikipedia.org/wiki/Rec._709 , 线性 RGB 色彩空间 |
| COLOR_SPACE_REC_2020_RGB Python: cv.ccm.COLOR_SPACE_REC_2020_RGB | https://en.wikipedia.org/wiki/Rec._2020 , RGB 色彩空间 |
| COLOR_SPACE_REC_2020_RGBL Python: cv.ccm.COLOR_SPACE_REC_2020_RGBL | https://en.wikipedia.org/wiki/Rec._2020 , 线性 RGB 色彩空间 |
| COLOR_SPACE_XYZ_D65_2 Python: cv.ccm.COLOR_SPACE_XYZ_D65_2 | https://en.wikipedia.org/wiki/CIE_1931_color_space , 非 RGB 色彩空间 |
| COLOR_SPACE_XYZ_D65_10 Python: cv.ccm.COLOR_SPACE_XYZ_D65_10 | 非 RGB 色彩空间 |
| COLOR_SPACE_XYZ_D50_2 Python: cv.ccm.COLOR_SPACE_XYZ_D50_2 | 非 RGB 色彩空间 |
| COLOR_SPACE_XYZ_D50_10 Python: cv.ccm.COLOR_SPACE_XYZ_D50_10 | 非 RGB 色彩空间 |
| COLOR_SPACE_XYZ_A_2 Python: cv.ccm.COLOR_SPACE_XYZ_A_2 | 非 RGB 色彩空间 |
| COLOR_SPACE_XYZ_A_10 Python: cv.ccm.COLOR_SPACE_XYZ_A_10 | 非 RGB 色彩空间 |
| COLOR_SPACE_XYZ_D55_2 Python: cv.ccm.COLOR_SPACE_XYZ_D55_2 | 非 RGB 色彩空间 |
| COLOR_SPACE_XYZ_D55_10 Python: cv.ccm.COLOR_SPACE_XYZ_D55_10 | 非 RGB 色彩空间 |
| COLOR_SPACE_XYZ_D75_2 Python: cv.ccm.COLOR_SPACE_XYZ_D75_2 | 非 RGB 色彩空间 |
| COLOR_SPACE_XYZ_D75_10 Python: cv.ccm.COLOR_SPACE_XYZ_D75_10 | 非 RGB 色彩空间 |
| COLOR_SPACE_XYZ_E_2 Python: cv.ccm.COLOR_SPACE_XYZ_E_2 | 非 RGB 色彩空间 |
| COLOR_SPACE_XYZ_E_10 Python: cv.ccm.COLOR_SPACE_XYZ_E_10 | 非 RGB 色彩空间 |
| COLOR_SPACE_Lab_D65_2 Python: cv.ccm.COLOR_SPACE_Lab_D65_2 | https://en.wikipedia.org/wiki/CIELAB_color_space , 非 RGB 色彩空间 |
| COLOR_SPACE_Lab_D65_10 Python: cv.ccm.COLOR_SPACE_Lab_D65_10 | 非 RGB 色彩空间 |
| COLOR_SPACE_Lab_D50_2 Python: cv.ccm.COLOR_SPACE_Lab_D50_2 | 非 RGB 色彩空间 |
| COLOR_SPACE_Lab_D50_10 Python: cv.ccm.COLOR_SPACE_Lab_D50_10 | 非 RGB 色彩空间 |
| COLOR_SPACE_Lab_A_2 Python: cv.ccm.COLOR_SPACE_Lab_A_2 | 非 RGB 色彩空间 |
| COLOR_SPACE_Lab_A_10 Python: cv.ccm.COLOR_SPACE_Lab_A_10 | 非 RGB 色彩空间 |
| COLOR_SPACE_Lab_D55_2 Python: cv.ccm.COLOR_SPACE_Lab_D55_2 | 非 RGB 色彩空间 |
| COLOR_SPACE_Lab_D55_10 Python: cv.ccm.COLOR_SPACE_Lab_D55_10 | 非 RGB 色彩空间 |
| COLOR_SPACE_Lab_D75_2 Python: cv.ccm.COLOR_SPACE_Lab_D75_2 | 非 RGB 色彩空间 |
| COLOR_SPACE_Lab_D75_10 Python: cv.ccm.COLOR_SPACE_Lab_D75_10 | 非 RGB 色彩空间 |
| COLOR_SPACE_Lab_E_2 Python: cv.ccm.COLOR_SPACE_Lab_E_2 | 非 RGB 色彩空间 |
| COLOR_SPACE_Lab_E_10 Python: cv.ccm.COLOR_SPACE_Lab_E_10 | 非 RGB 色彩空间 |
| enum cv::ccm::CONST_COLOR |
#include <opencv2/mcc/ccm.hpp>
带有 2 度 D50 的 Macbeth 和 Vinyl 色卡。
#include <opencv2/mcc/ccm.hpp>
用于计算颜色之间距离的可能函数的枚举。
请参阅 https://en.wikipedia.org/wiki/Color_difference 了解详情
#include <opencv2/mcc/ccm.hpp>
初始方法的可能类型的枚举。
| enum cv::ccm::LINEAR_TYPE |
#include <opencv2/mcc/ccm.hpp>
线性化变换类型。
色彩校正的第一步是对检测到的颜色进行线性化。由于输入色彩空间尚未校准,我们通常采用一些经验方法进行线性化。有几种常见的线性化方法。第一种是恒等变换,第二种是伽马校正,第三种是多项式拟合。
线性化通常是逐元素函数。数学符号如下
\(C\): 颜色的任意通道,可以是 \(R, G\) 或 \(B\)。
\(R, G, B\): 分别为 \(R, G, B\) 通道。
\(G\): 灰度;
\(s,sl\): 下标,表示检测到的数据及其线性化值,前者是输入,后者是输出;
\(d,dl\): 下标,表示参考数据及其线性化值
在恒等变换线性化过程中不进行任何更改,通常是因为输入 RGB 图像的三刺激值已经与亮度成比例。例如,如果输入测量数据是 RAW 格式,则测量数据已经线性,因此无需线性化。
恒等变换公式如下
\[ C_{sl}=C_s \]
伽马校正是在 RGB 空间中执行非线性的方法,详见色彩空间文档。在线性化部分,\(\gamma\) 的值通常设置为 2.2。您也可以自定义该值。
伽马校正线性化公式如下
\[ C_{sl}=C_s^{\gamma},\qquad C_s\ge0\\ C_{sl}=-(-C_s)^{\gamma},\qquad C_s<0\\\\ \]
多项式拟合使用多项式进行线性化。如果多项式为
\[ f(x)=a_nx^n+a_{n-1}x^{n-1}+... +a_0 \]
则
\[ C_{sl}=f(C_s) \]
实际中,使用 \(n\le3\) 来防止过拟合。
多项式拟合有多种变体,区别在于生成 \(f(x)\) 的方式。通常需要使用线性化的参考颜色和相应的检测颜色来计算多项式参数。然而,并非所有颜色都可以参与计算。需要去除检测到的饱和颜色。详见算法介绍文档。
使用三个多项式 \(r(x), g(x), b(x)\) 分别对 RGB 色彩空间的每个通道进行线性化[1-3]
\[ R_{sl}=r(R_s)\\ G_{sl}=g(G_s)\\ B_{sl}=b(B_s)\\ \]
通过最小化检测数据与线性化参考数据之间的残差平方和来生成多项式。以 R 通道为例
\[ R=\arg min_{f}(\Sigma(R_{dl}-f(R_S)^2) \]
这等价于对以下方程寻找最小二乘回归
\[ f(R_{s1})=R_{dl1}\\ f(R_{s2})=R_{dl2}\\ ... \]
使用多项式,上述方程变为
\[ \begin{bmatrix} R_{s1}^{n} & R_{s1}^{n-1} & ... & 1\\ R_{s2}^{n} & R_{s2}^{n-1} & ... & 1\\ ... & ... & ... & ... \end{bmatrix} \begin{bmatrix} a_{n}\\ a_{n-1}\\ ... \\ a_0 \end{bmatrix} = \begin{bmatrix} R_{dl1}\\ R_{dl2}\\ ... \end{bmatrix} \]
这可以表示为线性方程组
\[ AX=B \]
当参考颜色数量不小于多项式次数时,线性系统存在最小二乘解
\[ X=(A^TA)^{-1}A^TB \]
一旦我们得到多项式系数,就可以得到多项式 r。
这种寻找多项式系数的方法可以通过 numpy 中的 numpy.polyfit 实现,表示为
\[ R=polyfit(R_S, R_{dl}) \]
请注意,通常情况下,我们希望得到的多项式在区间 [0,1] 上是单调递增的,但这意味需要非线性方法来生成多项式(详见 [4])。这会大大增加程序的复杂性。考虑到单调性不影响色彩校正程序的正确运行,程序实现仍使用 polyfit。
其他通道的参数也可以通过类似的方式得出。
在该方法[2]中,所有通道都使用单一多项式。该多项式仍然是检测到的颜色到线性参考颜色的 polyfit 结果。但是,只有参考颜色的灰度可以参与计算。
由于检测到的与参考颜色灰度对应的颜色不一定是灰色的,因此需要将其灰度化。灰度是指 XYZ 色彩空间的 Y 通道。检测数据的色彩空间未确定,无法转换为 XYZ 空间。因此,使用 sRGB 公式进行近似[5]。
\[ G_{s}=0.2126R_{s}+0.7152G_{s}+0.0722B_{s} \]
然后可以使用 polyfit 获得多项式参数。
\[ f=polyfit(G_{s}, G_{dl}) \]
获得 \(f\) 后,即可执行线性化。
对于伽马校正公式,我们取对数
\[ ln(C_{sl})={\gamma}ln(C_s),\qquad C_s\ge0\ \]
可以看出 \(ln(C_s)\) 和 \(ln(C_{sl})\) 之间存在线性关系。可以认为该公式是多项式关系的近似,即存在一个多项式 \(f\),使得[2]
\[ ln(C_{sl})=f(ln(C_s)), \qquad C_s>0\\ C_{sl}=0, \qquad C_s=0 \]
因为 \(exp(ln(0))\to\infty \),所以在上述公式中,分量为 0 的通道直接映射为 0。
对于分别拟合通道,我们有
\[ r=polyfit(ln(R_s),ln(R_{dl}))\\ g=polyfit(ln(G_s),ln(G_{dl}))\\ b=polyfit(ln(B_s),ln(B_{dl}))\\ \]
请注意,\(ln(*) \) 的参数不能为 0。因此,我们需要从 \(R_s \) 和 \(R_{dl} \)、\(G_s\) 和 \(G_{dl}\)、\(B_s\) 和 \(B_{dl}\) 中删除值为 0 的通道。
因此
\[ ln(R_{sl})=r(ln(R_s)), \qquad R_s>0\\ R_{sl}=0, \qquad R_s=0\\ ln(G_{sl})=g(ln(G_s)),\qquad G_s>0\\ G_{sl}=0, \qquad G_s=0\\ ln(B_{sl})=b(ln(B_s)),\qquad B_s>0\\ B_{sl}=0, \qquad B_s=0\\ \]
对于灰度多项式,也有
\[ f=polyfit(ln(G_{sl}),ln(G_{dl})) \]
且
\[ ln(C_{sl})=f(ln(C_s)), \qquad C_s>0\\ C_sl=0, \qquad C_s=0 \]