色彩校正及OpenCV mcc模块介绍

一、术语

1.:是电磁波,可见光是可被人眼感知的电磁波。可见光大约在400-700nm波段。光子携带的能量与波长成反比,400nm--700nm之间的单色光的颜色从紫色渐变成红色。

2.光谱:除了太阳光源外,LED灯、白炽灯等各种照明设备也是摄影的主要光源。除此之外,火、荧光、磷光、生物发光等也是可见光源。通常情况大部分光源发射的都是连续波长的光构成的,或称为光谱,但人工能造出光谱范围窄、单色性好的光源,如激光。

3.白点:当使用光源测量颜色时,光源照射在物体表面上。通过测量不同波长的反射系数,与光源的光谱功率分布(SPD),以及色度函数,我们可以测量物体在光源下的颜色。如果物体反射所有波长,则该物体在该光源下所有分量都是最大的,称为该光源下的白点。由于白点反射了光源的所有光,不区分的情况下,也用白点指代光源。

4.色温:是表示光线中包含颜色成分的一个计量单位。从理论上说,黑体温度指绝对黑体从绝对零度(-273℃)开始加温后所呈现的颜色。黑体在受热后,逐渐由黑变红,转黄,发白,最后发出蓝色光。当加热到一定的温度,黑体发出的光所含的光谱成分,就称为这一温度下的色温,计量单位为"K"(开尔文)。

如果光源符合黑体的光谱功率分布,则黑体的温度称为光源的色温。如果不符合,则与其最相近的黑体辐射对应的温度称为相关色温(correlated color temperature,CCT)。

D系列光源使用简单的函数来模拟日光,使用数字来代表色温。如D50代表5003K色温的D光源,通常用以模拟晨昏时的日光;而D65代表6504K色温,用以模拟正午时分的日光。

5.增益(Gain):指的是相机感光度的增加,可以通过调整相机感光度来控制增益。相机增益主要应用于高感光度拍摄模式,这种模式可以在光线较暗的环境下,通过增加感光度来提高拍摄效果。但需要注意的是,增加感光度会使照片产生噪点,影响画质。因此,在拍摄时,需要根据实际情况和拍摄要求来选择合适的相机增益。

6.白平衡(White Balance):指让白色的物体在任何颜色的光源下都显示为白色。

7.饱和度:指图像中颜色的浓度,饱和度越高,颜色越饱满。

8.Gamma 变换:是一种非线性运算,用于对视频或静态图像系统中的亮度或三色刺激值进行编码和解码,可以调整图像的对比度。

9.Debayer:是一种数字图像处理算法,用于从传感器(sensor)输出的不完整颜色样本重建全彩色图像。

10.色调:指图像的相对明暗程度,在彩色图像上表现为颜色。在明度、纯度、色相这三个要素中,某种因素起主导作用时,就可以称之为某种色调。例如:在RGB模式中,色调代表红、绿、蓝三种原色的明暗程度,对绿色就有淡绿、浅绿、深绿等不同的色调。

11.色相:指颜色的相貌,是区别各种不同色彩的最准确的标准。色相是色彩的首要特征,是各种色彩的相貌称谓,如大红、普蓝等。

12.亮度:是各种图像色彩模式下原色的明暗程度,亮度增加时,就会显得耀眼或刺眼。

13.对比度:是指不同颜色之间的差别,对比度越大,不同颜色之间的反差越大。

二、色彩空间

色彩空间是一些色彩的集合,色彩空间所包含的所有色彩叫做色彩空间的色域。色彩空间一个重要的分类是:绝对色彩空间和相对色彩空间 。所谓的绝对色彩空间,就是在空间上的点(或称向量)对应的色彩是固定的,不随着外部因素而变化,如CIE XYZ,sRGB;而所谓的相对色彩空间,实际显示的颜色与物理硬件相关,而非固定不变的,如RGB,CMYK色彩空间,一个RGB图片只是指定了红色、绿色和蓝色的显示比例,实际的显示效果和显示设备(如显示器)使用的灯管有关,因此同一种图片在不同的显示器上看的效果不太一样。

绝对色彩空间因为是对应的色彩是固定的,因此空间可以互相转换;而相对色彩空间,因其色彩并不固定,因此将其转换成绝对色彩空间或是转成其他相对色彩空间都是没有意义的。

通常情况下,绝对色彩空间是在某光源下测量的,不同光源下的色彩空间的转换过程称为色彩适应(将色彩从一种光源变换成另一种光源下的操作叫色彩适应)。

相对色彩空间如果其物理硬件的色彩被固定下,也就是指向绝对物理空间的一个点,那么相对色彩空间的色彩就定了下来,那么就将相对色彩空间转换成绝对色彩空间。通过定义一个ICC(International Color Consortium, 国际色彩联盟)配置文件来定义转换关系是许多行业的通用做法。被广泛接受的配置文件定义的RGB颜色包括sRGB(standard Red Green Blue)和Adobe RGB。

1.CIE XYZ 色彩空间

国际照明委员会(Commission Internationale de l'éclairage",CIE)在1931年制定的色彩空间。CIE组织试图去找到最符合人心理的色彩空间。CIE 1931 XYZ色彩空间便是在尽可能模拟感官水平的基础创建起来的。CIE 1931 XYZ色彩空间简称CIE XYZ,仍然是目前广泛使用的色彩空间。某种意义上来说,是绝对色彩空间中的标准空间。CIE模型把Y设置成亮度,Z近似于S视锥,而X被选择为非负的响应曲线的混合。

CIE XYZ空间下色彩是不均匀的,为此,CIE又提出了多种其他的色彩空间。

2.色度空间

色彩的概念可分成2部分,亮度和色度。CIE XYZ空间中Y表示亮度,因此还需要2个维度来表示色度。使用xyY三元组构成的空间便是xyY空间。将XYZ空间中的点映射到该点与原点的连线与X+Y+Z=1平面上的交点,然后将X+Y+Z平面直接射影到Z=0的平面而生成的。X,Y,Z比例相同的点被映射到了同一点,因此消除了亮度的影响。最终XYZ平面被映射到xy平面中由(0,0), (0,1), (1,0)构成的三角形中。这就是色度图。

色度图表示普通人可见的所有色度。如果选择色度图上的任意两个颜色点,则可以通过混合这两种颜色来形成位于两个点之间的直线中的所有颜色;如果选用3个点,则三点构成的三角形就形成了该3种颜料的色域。

3.CIE Lab

国际照明委员会(CIE)在1976年定义了CIE Lab色彩空间。CIE Lab是建立在对立过程说的理论基础之上。它由3个分量组成:L*,a*和b*。其中L*表示从黑色(0)到白色(100)的亮度,a*绿色(-)到红色(+)的亮度,b*蓝色(-)到黄色(+)的亮度。Lab色彩空间旨在逼近人类视觉,尽可能使得色彩变得均匀。CIE Lab色彩空间最主要的作用在于作为色彩距离公式定义的基础,CIE发布的多种色彩距离公式都是定义在CIE lab上。

4.RGB 色彩空间

RGB色彩空间是三原色的色彩空间,RGB色彩空间中的颜色是由三原色的分量来定义。如果三原色的色彩未定义,则RGB色彩空间是相对色彩空间。但当RGB的三原色红色、绿色和蓝色在绝对色彩空间定义后,此时RGB色彩空间就变成绝对色彩空间。比如未进行色彩校正的相机,生成的RGB图就是相对色彩空间,图片里颜色的RGB三分量的数据与相机的感光系统相关。而色彩校正的目的便是建立这个相对色彩空间与绝对色彩空间之间的关系

RGB色彩空间是一系列色彩空间。绝对色彩空间,包括sRGB,Adobe RGB等。这些色彩空间进行绝对化的主要区别是在三原色的定义和线性化的标准。

在色彩校正中,需要将RGB色彩空间转换成CIE Lab色彩空间。下图以sRGB和ProPhoto RGB为例,展示色彩空间转换的过程。其中绿色的箭头表示线性变换,而蓝色表示非线性变换。绿色的方框代表的色彩空间之间可以通过线性变换来实现。

5.三原色的定义

白点:当使用光源测量颜色时,光源照射在物体表面上。通过测量不同波长的反射系数,与光源的光谱功率分布(SPD),以及色度函数,我们可以测量物体在光源下的颜色。如果物体反射所有波长,则该物体在该光源下所有分量都是最大的,称为该光源下的白点。由于白点反射了光源的所有光,不区分的情况下,也用白点指代光源。

LMS三刺激值:人体通过感光细胞来感应外界电磁辐射,并将转化成生物信号。目前已经发现的在人体存在的三种感光细胞分别是视杆细胞、视锥细胞和自主感光视网膜神经节细胞(ipRGCs),它们均分布在视网膜上。

人体拥有大约600~700万个视锥细胞,数量上远远少于视杆细胞,但它们却是色觉的主要感光细胞。大部分人眼中有3种视锥细胞,能感应不同波长的光:S锥,M锥和L锥,分别对短波、中波和长波的可见光敏感。

对于任何输入光谱,S锥,M锥和L锥分别会对不同的响应的强度,将这些强度归一化后形成0-1之间的三元数值,这个三元数值原则上描述了任何人类的颜色感觉。LMS色彩空间便是在这基础上建立的。

不管进入人眼的光谱如何,如果它们对人眼的S锥,M锥和L锥的刺激强度一样,则对人眼来说它们便是同一颜色。LMS三元数值被称为三刺激值(tristimulus values)。由于LMS只有3个独立变量,在此基础上发展的很多色彩空间也都是由3个独立变量构成,这些三元组也被称为三刺激值。比如,我们可以选定3种基础颜色来混合出其他颜色,被选定的基础颜色也被称为原色。三原色的选定决定了可表达色彩范围的大小,也称色域。最通常选定的三原色便是红色、绿色和蓝色,而由此构成的色彩空间被称为RGB色彩空间,其描绘颜色使用R,G,B三个分量,也被称为三刺激值。

标准观察者:由于视锥在眼睛中的分布,三刺激值取决于观察者的视野。为了消除此变量,CIE定义了一种称为标准观察者,实质是个色度函数,以表示中央凹内2°弧内人类的平均色响应。选择该角度是因为相信颜色敏感的圆锥体位于中央凹的2°弧内。因此,CIE 1931标准观察者也称为CIE 1931 2°标准观察者。一种更现代但使用较少的替代方法是CIE 1964 10°标准观察者。

在定义色彩空间时,要先选定白点和观察者。然后在白点的基础上构建的XYZ空间上选定三原色。通常三原色选择会忽略亮度,选择在色度空间内选取。选取白点、观察者和三原色后,RGB空间便定义下来了

由于在色度图上,三原点构成的三角形涵盖了以这三原点组合得到的所有颜色,也被称为色域。因此,之前定义了RGB图三原点的在色域图上的位置,可以在色域图上画出各RGB空间图的色域。

sRGB是目前计算机显示器最常见的色彩空间,然而色域有限;而Adobe RGB,Wide Gamut RGB等色彩空间的色域相对就大得多。

6.线性化与反线性化

通过定义了三原色和白点,此时线性化的RGB的色彩空间已经定了下来。此时色彩空间的颜色各分量值与亮度成正比,但却不符合人类的视觉感受。人类对亮度的感知却是非线性的,遵循近似的幂函数,对较暗色调之间的相对差异比起亮色调之间的相对差异更敏感。因此,通常需要对色彩空间使用伽马校正来符合人类视觉感受

目前,绝大多数的RGB色彩空间的解码伽马值为2.2。

实际做色彩转换的时候,有可能计算值超出[0,1],为了避免计算出虚数值,通常将伽玛校正的图像关于原点做对称。

7.色彩适应

虽然转换成XYZ空间,但空间的白点却不相同,为此需要在不同白点的XYZ空间间转换,将色彩从一种光源变换成另一种光源下的操作叫色彩适应 。由于色彩是各波长反射函数到三刺激值的非单映射,这意味着在一种光源下相同的颜色可能在另一种光源下会有差异。因此正确的进行色彩适应是不可能的。但通常会用线性变换来近似色彩适应。

三、色彩校正

色彩校正的目的是调整输入输出设备的颜色响应到已知状态。被校准的设备有时被称为校准源; 用作标准的色彩空间有时也称为校准目标。

由于输入输出设备的制造工艺等,其通道响应存在非线性失真,为了较正该设备输出的图片,必须将其捕捉到的色彩与实际色彩进行校正

1.色彩校正流程

通常分成2个步骤:

(1).先将输入色彩空间线性化为与亮度成正比。这个过程是不适定问题,因此有许多不同的解决方案;

(2).做线性变换,把色彩空间变成绝对RGB色彩空间 。所用的线性变换的矩阵称为色彩变换矩阵(color correction matrix,CCM),也称为CCM矩阵。CCM矩阵需要通过非线性优化来求解

2.拟合过程

主要是指定线性化方案和求解CCM矩阵。拟合过程是会首先将输入色彩线性化,然后乘以CCM矩阵以变换到绝对色彩空间,接着变换成色彩距离计算空间(通常是CIE lab),与此同时,参考色彩也转成色彩距离计算空间,然后去优化输入色彩与参考色彩之间的距离,使其尽可能的小,由此求出CCM矩阵。

由于测量设备未标定,因此输入数据处于相对色彩空间中,而拟合的目的便是建立该相对色彩空间与绝对色彩空间之间的关系。

整个拟合过程所有的RGB色彩空间数值都必须做归一化,即取值在[0, 1]之间

拟合过程的流程图如下图所示:拟合的目的便是建立该相对色彩空间与绝对色彩空间之间的关系

3.推理过程

当完成拟合过程后,我们可以对图像进行校正

推理过程如下图所示:

推理过程需要走和拟合过程相似的流程,但却简单的多。对于输入的图片,我们使用拟合时使用的线性化方式进行线性化,然后乘以CCM矩阵,此时数据已成为绝对的线性RGB色彩空间。一般情况下,我们需要将线性化RGB空间转换成RGB空间,然后输出图像;但偶尔的,我们也可以选择直接输出Linear RGB图像,便于后续的处理。注意,线性化RGB空间转换成RGB空间的反线性化过程是由色彩空间决定的,与之前的线性化过程无关。

由于推理过程需要使用拟合过程的线性化方法,CCM矩阵,以及具体的RGB空间(以便进行反线性化)。因此拟合过程生成的模型至少要包括这3个内容。

4.校正色卡

通常使用的校准色彩叫做色卡(colorchecker),最著名的是麦克白色卡(Macbeth ColorChecker)。

色卡提供色彩校正中的参考色,所有的颜色都已经被标定麦克白色卡包括4*6个色块,其中,最后一行的色块是灰色色块,可以用于灰度线性化或是白平衡。

Macbeth色卡在2度角D50光源下的颜色被多人标定过,各自的结果互相有差异。2度角D65光源的颜色可以通过色彩适应来计算,也可以使用测量结果。

5.线性化

进行色彩校正的时候,对测量数据的第一步操作便是将其线性化。由于测量色彩空间尚未标定,我们通常采用一些经验的方式来进行线性化。

测量数据可能由于测量系统的物理机制或者为了适应人眼的习惯等原因与亮度存在非线性关系,如果不将其线性化,无法有效的用线性变换近似线性化的绝对色彩空间。只有相对色彩空间和绝对色彩空间的数值与亮度均成正比关系,才能使用线性变换近似两者之间的色彩转换。

由于测量色彩空间尚未标定,因此它不能直接使用绝对色彩空间如sRGB, Adobe RGB的线性化过程。除非完全掌握测量过程的物理机制,否则我们只能采用一些经验的方式来进行线性化。

经验上通常采用的线性化:线性化一般是逐元素(elementwise)的函数

(1).恒等变换:线性化时不做任何改变,通常原因是输入的RGB图像通道值与亮度成正比。比如输入的测量数据为RAW格式,那么测量数据已经是线性化了的,因此不需要进行线性化。

(2).伽马(gamma)校正:是RGB空间进行非线性的手段,在线性化部分中,gamma值通常设为2.2,也可以自定义。

(3).多项式拟合:是使用多项式来进行线性化,实际使用时,为了防止过拟合,拟合的次数通常不超过3。

多项式拟合有许多变种,关键是在如何生成f(x)。通常需要使用线性化的参考数据和对应的测量数据来求多项式的参数,但主要,并非所有通道都可以参与计算。通常,需要去除掉饱和的测量数据。

6.CCM 矩阵

色彩校正的时候通常使用CCM矩阵作为从线性化的输入色彩空间到线性绝对色彩空间变换的近似

测量数据线性化后,通过线性变换将其近似的转成某个线性的绝对RGB色彩空间。进行线性变换等价于乘以一个矩阵,而这个矩阵我们称为CCM矩阵 (color correction matrix)。CCM矩阵也是我们进行拟合的目标。我们可以设定进行线性变换后转成的具体色彩空间,如Linear sRGB,Linear Adobe RGB等。通常情况下,该色彩空间需和你想最终保存数据的色彩空间一致,以减少推断过程中色彩空间的换算。

CCM矩阵的形状通常3*3和4*3两种。前者对色彩的数值进行线性变换,而后者做仿射变换。换言之,色彩空间在前者的变换后保持原点不变,而后者可以发生平移。可见,3*3的CCM矩阵的变换集合是4*3的真子集,这意味着使用4*3 CCM矩阵拟合的解集更大。然而,最新的论文更愿意使用3*3的CCM矩阵而非后者。

在拟合过程时,CCM矩阵需要有个初始值用以之后的优化。通常,初始化的方案有2种,一种采用白平衡,一种采用最小二乘法估计。

7.色彩距离

色彩距离量化了人们感受的色彩差异 。通常情况下,使用国际照明委员会(CIE)提出的CIE76,CIE94或CIEDE2000的标准。它们都需要先将色彩空间转换成CIE Lab空间中,然后使用数学公式来计算。此外CMC l:c(1984)距离也是常见的色彩距离。

此外,我们可以使用RGB空间的欧式距离作为色彩距离,它在机器视觉有一定用途;或者使用线性RGB空间的欧式距离作为色彩距离,它计算简单,可以作为基于其他距离的模型的初始值,是最小二乘法初值估计的由来。

当测量数据转换成绝对色彩空间时,我们需要评估转换后的结果是否与参考值接近。评估使用的函数称为损失函数 ,我们需要找到合适的CCM的值,以尽可能的降低损失函数的大小。而损失函数通常设定为所有测量数据与参考数据对应颜色差值的加权平方和,因此要计算损失函数,我们要计算颜色的差值。颜色差值通用的标准是CIE76,CIE94和CIEDE2000以及CMC等标准,这些标准都是建立在CIE Lab色彩空间的基础上的,因此我们通常需要将线性变换后的色彩空间转换成CIE Lab色彩空间,以便计算距离。当然,我们也可以使用非标准的距离方程,如直接使用设定的绝对RGB色彩空间的欧拉距离,或是设定的线性化的绝对RGB色彩空间的欧拉距离。前者可能在机器视觉上有少量应用,而后者由于计算方便,可以作为测试或是生成使用其他距离方程时的拟合的初始值。

因此,在线性变换之后,我们需要将将色彩空间转换成CIE Lab色彩空间。由于只有指定白点和观察者(Illuminant and Observer,IO),CIE Lab空间才能被真正确立下来。尽管距离公式本身不需要确定CIE lab空间,也即是说,不需要指定IO值,但只有在指定IO值下,指定的线性化绝对RGB色彩空间与CIE Lab色彩空间的转换关系才能确立下来。

于此同时,参考数据也需要转换到距离公式所对应的色彩空间中。由于参考数据本身处于绝对色彩空间中,因此我们只需要直接进行色彩空间转换即可。也因此,我们除了要输入参数颜色值外,还要输入颜色值所处的色彩空间,如sRGB, CIE Lab等。如果是CIE Lab空间,我们同样需要IO值来确定色彩空间,以便于确定参考颜色的真实值。参考颜色和色彩空间确立了绝对的参考数据,我们称为色卡。

8.饱和

并非所有颜色都能参与到最终损失函数的计算 。最大的排斥理由是饱和。如果测量的某个颜色的R, G, B通道中有一通道达到或非常靠近最大值,很可能在这个通道发生了饱和。饱和的出现通常意味着该通道实际亮度可能被截断了,不能反映真实的值,无法被线性化。因此,需要将饱和的颜色去除,判定条件是其中任一通道发生了饱和。基于相同的理由,饱和通道也不能用于计算线性化过程的参数。

9.损失函数

为了优化CCM矩阵,需要一个CCM矩阵映射到实数值的函数,然后尽可能减少实数值以获取更好的CCM矩阵,而这个函数就被称为损失函数。色彩校正中,损失函数通常设置为所有测量数据与参考数据对应色彩距离的加权平方和,而这个权重值通常有几种设置方法:

(1).均为1,即所有颜色差值的地位相等;

(2).第二种是等比与亮度的幂,此处的亮度是简单的设置为参考色彩在CIE Lab色彩空间中的L*分量;

(3).第三种是手动输入,这种更为灵活,但前提是使用者充分掌握色彩领域相关知识。

所有的权重都将归一化,以便比较损失函数值。归一化并不会影响损失函数的收敛。

10.非线性优化

有了损失函数后,便可以对CCM矩阵做非线性优化

由于最常用的CIEDE2000的距离公式并不连续,因此不能采用基于导数的非线性优化方法。NelderMead方法是最广泛使用的无导数非线性优化方法,有许多已有的实现可使用,一般优先使用该方法作为非线性优化方法。此外,模式搜索(pattern search method, PSM)因其过程简单易懂易实现,也是业界经常使用的非线性优化方法。

(1).损失函数和比重:当测量数据和参考数据都转换成距离公式所处的色彩空间的时候,我们便可以计算色彩差值乃至损失函数。损失函数通常设置为所有测量数据与参考数据对应颜色差值的加权平方和,而这个权重值通常有几种设置方法:一种是默认,则所有颜色差值的地位相等;第二种是等比与亮度的幂,此处的亮度是颜色在CIE lab色彩空间中的l*分量;第三种是手动输入,这种更为灵活,但前提是使用者充分掌握色彩领域相关知识。所有的权重都将归一化,以便比较损失函数值。归一化并不会影响损失函数的收敛。

并非所有颜色都能参与到最终损失函数的计算 。最大的排斥理由是饱和。如果测量的某个颜色的R, G, B通道中有一通道达到或非常靠近最大值,很可能在这个通道发生了饱和。饱和的出现通常意味着该通道实际亮度可能被截断了,不能反映真实的值,无法被线性化。因此,需要将饱和的颜色去除,判定条件是其中任一通道发生了饱和。基于相同的理由,饱和通道也不能用于计算线性化过程的参数。

第二个排斥颜色的理由是色彩距离公式。通常情况下CIEDE2000标准被认为目前最接近人心理上的关于色彩距离的标准,然而CIEDE2000距离函数却不是连续函数。针对某参考颜色的距离方程在a*b*平面上从原点出发远离颜色位置的方向附近会有较大的不连续性,因此,这个不连续性极易发生在很接近原点的色彩上,也就是黑白灰色。

(2).距离函数的影响:大部分情况下,我们使用非线性优化来计算CCM矩阵,最主要的原因是从指定的线性化RGB空间转换成色彩距离空间是个非线性的过程。但如果距离函数设定为linear RGB,那么这个转换过程变成identity变换,那么我们可以直接使用加权最小二乘法求得最优的CCM矩阵。这也提供了其他距离函数下非线性优化初值生成的一种方式,也是推荐的一种方式。另外一种是保持白平衡的初值方式。

如果距离函数被设定为CIE Lab色彩空间,那么设定不同的RGB空间的最优化解本质上没有什么不同,是同一种颜色在不同色彩空间中的不同表达。其中的原因是各个linear RGB空间仅相差一个线性变换。当然,由于RGB转换成CIE Lab的函数非凸,因此这个非线性优化过程无法保证达到全局最优,使用不同的RGB空间很可能收敛到不同的局部最优的颜色组。

可能存在少量原因使用RGB色彩距离公式。此时由于linear RGB到RGB之间的转换对不同的RGB空间可能不一样,因此这时候设置不同的RGB空间会导致不同的收敛结果。

(3).优化方法:由于最常用的CIEDE2000的距离公式并不连续,因此不能采用基于导数的非线性优化方法。NelderMead方法是最广泛使用的无导数非线性优化方法。如前所述,全局最优无法被保证,因此不同初始值的选用、不同RGB空间的选用都可能会收敛到不同的局部最优,即使是距离函数设置为CIE lab色彩空间。

11.评估模型

(1).色彩空间和色彩分布:

1).色彩空间:由于我们使用三个分量值来描述颜色,因此色彩空间的数值也构成一个空间线性化时,数值空间是色彩空间的数值描述,数学意义来说并没有区别。

在线性化时,可采用gamma校正或多项式拟合。接下来乘以CCM矩阵(3*3或4*3),相当于对原来的色彩空间进行了线性变换。最后我们进行反线性化。

2).色彩分布(Color Distribution, CD):在色彩空间中,有些色彩可能比别的色彩更常见,因此形成了一个色彩概率空间,色彩在色彩空间中的分布我们称作色彩分布。

对于初始的色彩分布,如果已经输入色彩空间中已经获取了大量拍摄图片,那么统计一个色彩分布,就可以作为初始色彩分布;如果没有相关的数据,我们可以做以下近似。一种是我们可以简单的认为色彩在整个色彩空间中均匀分布。虽然不符合实际,但处理简单;另一种是我们可以使用大量图片进行统计获取一个平均色彩分布,然后使用这个色彩分布做为初始分布。要注意的是,未校准的色彩空间往往有某个方向上的偏移,因此使用平均色彩分布通常也不同于初始分布,但却是一个很好的近似。

(2).模型评估指标:不同的参数设置获得的模型结果相差是非常明显的。那怎么在推理前去评估一个模型的好坏呢,本文提出3个指标来判断。

1).第一个是残差,是收敛时损失函数的值的平方根,这也是最重要的一个指标。越小的残差,说明测量数据通过模型后生成的数据越接近于参考数据,虽然不能保证但通常也意味着其他的颜色值在转化后也能更接近真实值。通常残差在CIE76,CIE94时取到5,在CIEDE2000取到3是非常好的结果了。在RGB和Linear RGB空间中计算的残差值通常较小,不能直接和CIE76,CIE94,CIEDE2000的残差值进行比较。

2).第二个是过饱和度。最终评判模型的过饱和度被定义为对于随机一个输入颜色的过饱和度的期望值。要注意,随机输入的分布没有被指定,采用反映实际设备的色彩分布会较好,但受到实际的限制可能采用均匀分布或统计平均分布来近似。

3).第三个覆盖体积。如果仅以过饱和度为评估标准,则很容易会使模型输出结果往缩小的方向进行,这样会导致覆盖体积的减小。因此,以覆盖体积作为标准,可以综合评估模型。

对于第二项和第三项的判定标准直接进行积分计算的话会非常繁琐,使用蒙特卡罗法就简单的多。按输入分布随机多个色彩,统计最终的色彩的过饱和度,获得期望值,便是第二项的近似值;在[0, 1]3空间均匀生成色彩,反计算原像是否在[0, 1]3空间上,获得的比例便是覆盖体积。

:以上内容主要摘自于:github.com/riskiest/color_calibration

四、OpenCV mcc模块

OpenCV mcc模块中使用了两种命名空间:cv::mcc用在色卡检测而cv::ccm用在色彩校正。

1.两种色卡检测方法

(1).基本的检测算法

(2).使用神经网络提高检测精度

2.色彩校正

使用色彩校正模型(Color Correction Model),色彩校正执行过程:

(1).构造ColorCorrectionModel对象:

1).接收测量色卡的处理结果:3*1*24

2).Macbeth色卡的值在GetColor::getColor(color.cpp)函数中存储,ColorCorrectionModel构造函数中会获取到

(2).可设置的参数:设置不同的参数,对loss结果影响很大

1).ColorSpace:绝对色彩空间,默认为COLOR_SPACE_sRGB

2).CCM_TYPE:色彩校正矩阵的shape,默认为CCM_3x3

3).Distance:色彩距离的类型,默认为DISTANCE_CIE2000

4).Linear:线性化方法,默认为LINEARIZATION_GAMMA

5).LinearGamma: gamma校正的gamma值,仅当Linear设置为"gamma"时有效默认为2.2

6).LinearDegree:线性化多项式的次数,仅当Linear设置为COLORPOLYFIT, GRAYPOLYFIT,COLORLOGPOLYFIT,GRAYLOGPOLYFIT时有效,默认为3

7).SaturatedThreshold:饱和度阈值,闭区间[lower,upper]内的颜色被保留,用于参与损失函数和初始化参数的计算,默认值为[0, 0.98]

8).WeightsList:每种颜色的权重列表,默认为空

9).WeightCoeff:CIE Lab色彩空间中测量色卡颜色的L*分量的指数数,默认为0

10).InitialMethod:CCM初始值的计算方法,支持INITIAL_METHOD_WHITE_BALANCE和INITIAL_METHOD_LEAST_SQUARE,默认为INITIAL_METHOD_LEAST_SQUARE

11).MaxCount:用于MinProblemSolver-DownhillSolver,算法的终止标准,默认为5000

12).Epsilon:用于MinProblemSolver-DownhillSolver,算法的终止标准,默认为1.e-4

(3).run函数:

1).获取饱和色mask:saturate函数,输入为:测量色卡的处理结果,设置的饱和度阈值

2).获取线性化方法:getLinear函数,输入为:测量色卡的处理结果,设置的gamma值、线性化多项式的次数、绝对色彩空间、线性化方法,根据传入的线性化方法不同,仅使用其中的个别设置的值;new LinearGamma或LinearColor或LinearGray

3).计算权重:calWeightsMasks函数,输入为:设置的权重列表、测量色卡颜色的L*分量的指数数, 饱和色mask

4).线性化变换:线性类的linearize函数,如gamma校正,输入为:测量色卡的处理结果的mask结果,输出为线性化颜色空间,如sRGBL [0, 1]

5).参考色卡值处理:sRGBL [0, 1]

6).对ccm类型CCM_3x3不做任何更改,为CCM_4x3进行更改: prepare函数

7).对距离函数进行处理,其可能影响损失函数和拟合函数, CCM初始值计算:initialWhiteBalance函数或initialLeastSquare:测量色卡的sRGBL和参考色卡的sRGBL参与运算

8).拟合:fitting函数,主要调用DownhillSolver类的接口用于计算CCM和loss

(4).将带处理图像转为RGB,其值范围调整为[0, 1],用于infer

(5).infer函数:

1).对带处理图像进行线性化变换:线性类的linearize函数,如gamma校正,sRGBL

2).对ccm类型CCM_3x3不做任何更改,为CCM_4x3对带处理图像进行处理: prepare函数

3).带处理图像与ccm做multiple:multiple函数

4).反线性化操作(rgbl -> rgb):sRGBBase_::fromLFunc函数

(6).对结果处理处理:其值调整为[0, 255]并将其转换为BGR

五、测试代码

cpp 复制代码
int test_opencv_color_correction_Macbeth()
{
	constexpr char *name_src{ "../../../test_images/test_ccm.png" }, *name_dst{ "../../../test_images/ret_test_ccm.png" };

	cv::Mat imgchart = cv::imread(name_src, -1);
	cv::Mat imgsrc = cv::imread(name_src, -1);
	if (imgchart.empty() || imgsrc.empty()) return -1;
	if (imgchart.type() != CV_8UC3 || imgsrc.type() != CV_8UC3) return -1;

	// create the detector object
	auto detector = cv::mcc::CCheckerDetector::create();
	if (!detector) {
		std::cout << "fail to cv::mcc::CCheckerDetector::create" << std::endl;
		return -1;
	}

	// run the detector
	if (!detector->process(imgchart, cv::mcc::MCC24, 1)) {
		std::cout << "fail to cv::mcc::CCheckerDetector::process" << std::endl;
		return -1;
	}

	// get list of colorcheckers
	auto checkers = detector->getListColorChecker();
	if (checkers.empty()) {
		std::cout << "fail to cv::mcc::CCheckerDetector::getListColorChecker" << std::endl;
		return -1;
	}

	// draw the colorcheckers back to the image
	auto cdraw = cv::mcc::CCheckerDraw::create(checkers[0]);
	cv::Mat imgdraw = imgchart.clone();
	cdraw->draw(imgdraw);

	// the color type is RGB not BGR, and the color values are in [0, 1]
	cv::Mat chartsrgb = checkers[0]->getChartsRGB();
	cv::Mat mat = chartsrgb.col(1).clone().reshape(3, chartsrgb.rows / 3);
	mat /= 255.0;

	// compte color correction matrix
	cv::ccm::ColorCorrectionModel model(mat, cv::ccm::COLORCHECKER_Macbeth);

	// more models with different parameters
	model.setColorSpace(cv::ccm::COLOR_SPACE_sRGB);
	model.setCCM_TYPE(cv::ccm::CCM_3x3);
	model.setDistance(cv::ccm::DISTANCE_CIE2000);
	model.setLinear(cv::ccm::LINEARIZATION_GAMMA);
	model.setLinearGamma(2.2);
	model.setLinearDegree(3);
	model.setSaturatedThreshold(0, 0.98);
	model.setWeightsList(cv::Mat());
	model.setWeightCoeff(0);
	model.setInitialMethod(cv::ccm::INITIAL_METHOD_LEAST_SQUARE);
	model.setMaxCount(5000);
	model.setEpsilon(1e-4);

	model.run();
	auto ccm = model.getCCM();
	auto loss = model.getLoss();
	std::cout << "loss: " << loss << "\n";
	auto src_rgbl = model.get_src_rgbl();
	auto dst_rgbl = model.get_dst_rgbl();
	auto mask = model.getMask();
	auto weights = model.getWeights();

	// make color correction
	constexpr int inp_size{ 255 }, out_size{ 255 };
	cv::Mat imgrgb;
	cv::cvtColor(imgsrc, imgrgb, cv::COLOR_BGR2RGB);
	imgrgb.convertTo(imgrgb, CV_64F);
	imgrgb /= inp_size;

	cv::Mat imgdst = model.infer(imgrgb);
	imgdst *= out_size;

	// save corrected image
	imgdst.convertTo(imgdst, CV_8UC3);
	imgdst = cv::min(cv::max(imgdst, 0), out_size);
	cv::cvtColor(imgdst, imgdst, cv::COLOR_RGB2BGR);
	cv::imwrite(name_dst, imgdst);

	return 0;
}

结果图如下所示:左图为原图,右图为色彩校正后的结果图

GitHubhttps://github.com/fengbingchun/OpenCV_Test

相关推荐
jndingxin1 小时前
OpenCV相机标定与3D重建(1)概述
数码相机·opencv·3d
凤枭香18 小时前
Python OpenCV 傅里叶变换
开发语言·图像处理·python·opencv
ctrey_19 小时前
2024-11-4 学习人工智能的Day21 openCV(3)
人工智能·opencv·学习
可均可可20 小时前
C++之OpenCV入门到提高004:Mat 对象的使用
c++·opencv·mat·imread·imwrite
蒙娜丽宁20 小时前
《Python OpenCV从菜鸟到高手》——零基础进阶,开启图像处理与计算机视觉的大门!
python·opencv·计算机视觉
plmm烟酒僧21 小时前
Windows下QT调用MinGW编译的OpenCV
开发语言·windows·qt·opencv
AI小杨21 小时前
【车道线检测】一、传统车道线检测:基于霍夫变换的车道线检测史诗级详细教程
人工智能·opencv·计算机视觉·霍夫变换·车道线检测
冷凝女子1 天前
【QT】海康视频及openCv抓拍正脸接口
qt·opencv·音视频·海康
撞南墙者1 天前
OpenCV自学系列(1)——简介和GUI特征操作
人工智能·opencv·计算机视觉
柳鲲鹏1 天前
OpenCV视频防抖源码及编译脚本
人工智能·opencv·计算机视觉