用于图像处理的感知色彩空间

2020-12-24 21:44:57

当进行多种图像处理时,理想的色彩空间是理想的。它对于诸如以下的事情很有用:

不幸的是,据我所知,虽然有一些色彩空间旨在实现感知上的统一,但在用于图像处理时,没有任何明显的缺点。

因此,我设计了一种新的感知色彩空间,该色彩空间设计易于使用,同时在预测感知的亮度,色度和色相方面做得很好。之所以称为Oklab颜色空间,是因为它是OK Lab颜色空间。

在深入探讨为什么需要新色彩空间以及如何衍生新色彩的细节之前,这里是使用色彩空间所需的一切:

Oklab中的颜色用三个坐标表示,类似于CIELAB的工作方式,但具有更好的感知特性。 Oklab使用D65白点,因为这是sRGB和其他常见色彩空间所使用的。这三个坐标是:

对于许多操作,可以直接使用L a b Lab L a b坐标,但也可以将其转换为极坐标形式,其坐标为亮度,色度和色相,L C h LCh L C h:

C = a 2 + b 2,h∘= atan 2(a,b)C = {\ sqrt {a ^ 2 + b ^ 2}},\ qquad h ^ {\ circ} = \ text {atan2}(a ,b)C =√a 2 + b 2 *,h = = atan 2(a,b)

根据C C C和h∘h ^ {\ circ} h∘可以计算出a a a和b b b,如下所示: a = C cos(h∘),b = C sin(h∘)a = C \ cos(h ^ {\ circ}),\ qquad b = C \ sin(h ^ {\ circ})a = C cos (h∘),b = C罪(h∘) 让我们看一个实际的例子,看看Oklab的性能如何,然后再看如何计算L a b Lab L a b坐标。 这是一个Oklab颜色渐变,具有不同的色相和恒定的亮度和色度。 将此与具有变化的色相,恒定值和饱和度(使用sRGB颜色空间的HSV)的HSV颜色梯度的类似图进行比较。 渐变非常不均匀,并且不同色调的亮度存在明显差异。 黄色,品红色和青色看上去比红色和蓝色要轻得多。 给定X Y Z XYZ X Y Z坐标中的颜色以及D65白点,可以按以下方式计算Oklab坐标:

(lms)= M 1×(XYZ)\ begin {pmatrix} l \\ m \\ s \ end {pmatrix} = \ mathbf {M_1} \ times \ begin {pmatrix} X \\ Y \\ Z \ end { pmatrix} l l l m s s = = = M××⎝⎛

(l'm's')=(l 1 3 m 1 3 s 1 3)\ begin {pmatrix} l' \\ m' \\ s \ end {pmatrix} = \ begin {pmatrix} l ^ {\ frac 1 3} \\ m ^ {\ frac 1 3} \\ s ^ {\ frac 1 3} \ end {pmatrix} end⎛ l m m s s = = = = =⎝⎜l l l l l 3 3 3 1 m m 3 1 1 3 3 1 1⎠⎟⎞⎞⎞⎞⎞⎞⎞

(L a b)= M 2×(l'm′s')\ begin {pmatrix} L \\ a \\ b \ end {pmatrix} = \ mathbf {M_2} \ times \ begin {pmatrix} l' \\ m' \\ s \ end {pmatrix} L L a a b⎠= = = M 2×⎝l l′′m′′ s的⎠⎞

对于M 1 \ mathbf {M_1} M 1和M 2 \ mathbf {M_2} M 2具有以下值:

M 1 =(+ 0。8 1 8 9 3 3 0 1 0 1 + 0。3 6 1 8 6 6 7 4 2 4 − 0。1 2 8 8 5 9 7 1 3 7 + 0。0 3 2 9 8 4 5 4 3 6 + 0 .9 2 9 3 1 1 8 7 1 5 + 0 .0 3 6 1 4 5 6 3 8 7 + 0 .0 4 8 2 0 0 3 0 1 8 + 0.2 6 4 3 6 6 2 6 9 1 + 0。6 3 3 8 5 1 7 0 7 0)\ mathbf {M_1} = \ begin {pmatrix} +0.8189330101& +0.3618667424& -0.1288597137 \\ +0.0329845436& +0.9293118715& +0.0361456387 \\ +0.0482003018& +0.2643662691& +0.6338517070 \ end {pmatrix} M 1 =⎝+ 0。 8 1 8 9 3 3 0 1 0 1�+ 0。 0 3 2 9 8 4 5 4 3 6-0 0 4 8 2 0 0 3 0 1 8 + 0。 3 6 1 8 6 6 7 4 2 4 + 0。 9 2 9 3 1 1 8 7 1 5 + 0。 2 6 4 3 6 6 2 6 9 1-0。 1 2 8 8 5 9 7 1 3 7 + 0。 0 3 6 1 4 5 6 3 8 7 + 0。 6 3 3 8 5 1 7 0 7 0⎠⎞

M 2 =(+ 0。2 1 0 4 5 4 2 5 5 3 + 0。7 9 3 6 1 7 7 8 5 0-0。0 0 4 0 7 2 0 4 6 8 + 1。9 7 7 9 9 8 4 9 5 1 − 2。4 2 8 5 9 2 2 0 5 0 + 0 .4 5 0 5 9 3 7 0 9 9 + 0 .0 2 5 9 0 4 0 3 7 1 + 0 .7 8 2 7 7 1 7 6 6 2-0。8 0 8 6 7 5 7 6 6 0)\ mathbf {M_2} = \ begin {pmatrix} +0.2104542553& +0.7936177850& -0.0040720468 \\ +1.9779984951& -2.4285922050& +0.4505937099 \\ +0.0259040371& +0.7827717662& -0.8086757660 \ end {pmatrix} M 2 =⎝+ 0。 2 1 0 4 5 4 2 5 5 3 +1。 9 7 7 9 9 8 4 9 5 1 +1。 0 2 5 9 0 4 0 3 7 1 + 0 7 9 3 6 1 7 7 8 5 0 0-2。 4 2 8 5 9 2 2 0 5 0 + 0。 7 8 2 7 7 1 7 6 6 2 2-0。 0 0 4 0 7 2 0 4 6 8 + 0。 4 5 0 5 9 3 7 0 9 9-0。 8 0 8 6 7 5 7 6 6 0⎠⎞

(l'm''s')= M 2 − 1×(L ab),(lms)=((l'')3(m'')3(s')3),(XYZ)= M 1 − 1× (lms)\ begin {pmatrix} l' \\ m' \\ s \ end {pmatrix} = \ mathbf {M_2} ^ {-1} \ times \ begin {pmatrix} L \\ a \\ b \ end {pmatrix},\ qquad \ begin {pmatrix} l \\ m \\ s \ end {pmatrix} = \ begin {pmatrix} {(l')} ^ {3} \\ {(m')} ^ {3} \\ {(s')} ^ {3 } \ end {pmatrix},\ qquad \ begin {pmatrix} X \\ Y \\ Z \ end {pmatrix} = \ mathbf {M_1} ^ {-1} \ times \ begin {pmatrix} l \\ m \\ s \ end {pmatrix}⎝⎛l m m m s s = = M M = 2 2 − 1×× L L L a b⎞,,l m m = = = = =⎝= =((( l'')3 3(m)3(s)3 3,,,,,,,,,,,,,, X Y Z⎠= M = M 1 − 1××l l l m s ⎠⎞

由于这是一个常见的用例,因此这里是将线性sRGB值转换为Oklab并返回的代码。要计算线性sRGB值,请参阅我的上一篇文章。

该代码是C ++,但是没有任何高级功能,因此应易于翻译。该代码可在公共领域使用,请随时以任何方式使用它。

struct Lab {float L;浮动float b;}; struct RGB {float r;浮点g; float b;}; Lab linear_srgb_to_oklab(RGB c){float l = 0.4121656120f * c.r + 0.5362752080f * c.g + 0.0514575653f * c.b;浮点数m = 0.2118591070f * c.r + 0.6807189584f * c.g + 0.1074065790f * c.b;浮点数s = 0.0883097947f * c.r + 0.2818474174f * c.g + 0.6302613616f * c.b;浮点数l_ = cbrtf(l);浮点数m_ = cbrtf(m);浮点数s_ = cbrtf(s);返回{0.2104542553f * l_ + 0.7936177850f * m_-0.0040720468f * s_,1.9779984951f * l_-2.4285922050f * m_ + 0.4505937099f * s_,0.0259040371f * l_ + 0.7827717662f * m_-0.8086757660f * s_,};} RGB oklab_to_linear_srgb(实验c){float l_ = cL + 0.3963377774f * ca + 0.2158037573f * cb;浮点数m_ = c.L-0.1055613458f * c.a-0.0638541728f * c.b;浮点数s_ = c.L-0.0894841775f * c.a-1.2914855480f * c.b;浮点数l = l_ * l_ * l_;浮点数m = m_ * m_ * m_; float s = s_ * s_ * s_; return {+ 4.0767245293f * l-3.3072168827f * m + 0.2307590544f * s,-1.2681437731f * l + 2.6093323231f * m-0.3411344290f * s,-0.0041119885f * l-0.7034763098f * m + 1.7068625689f * s, };}

这就是使用Oklab颜色空间所需的一切!如果您需要简单的感知色彩空间,请尝试一下。

文章的其余部分将探讨为什么需要新的色彩空间,如何构造新色彩空间以及如何将其与现有色彩空间进行比较。

感知色彩空间需要满足哪些属性才能对图像处理有用?答案总是比较主观的,但是根据我的经验,这是一组很好的要求:

应预测亮度,色度和色相。 L L L,C C C和h h h应该被认为是正交的,因此可以更改其中一个而不影响其他两个。这对于将图像变为黑白,增加色彩而不引入色相偏移等很有用。

混合两种颜色应导致均匀的过渡。过渡色应该看起来介于混合色之间(例如,穿过比任何一种原始颜色都暖的颜色都不好)。

应假定为D65白点。这就是sRGB,rec2020和Display P3等常见色彩空间的用途。

数值上应该表现良好。该模型应易于计算,数值稳定且可微分。

应假定正常光线充足的观看条件。在大多数应用中,支持不同观看条件的复杂性并不现实。如果在某些情况下需要,可以结合使用其他模型。

如果更改了颜色的比例/曝光,则应将感知坐标仅按比例缩放。应避免依赖于绝对亮度的更复杂的模型,因为无法精确地控制观看条件,并且错误的行为会造成混淆。

让我们看一下现有模型以及它们如何与这些要求相结合。下方有一些图表说明了其中的一些问题。

CIELAB和CIELUV –最大的问题是它们无法预测色相。特别是蓝色的预测很差。还存在其他较小的问题

CIECAM02-UCS和更新的CAM16-UCS –在整体上在感知上均一方面表现出色,但不满足其他要求:不良的数字行为,缩放比例不变且混合由于色度压缩而表现不佳。色相均匀性不错,但是其他模型可以更准确地预测。

OSA-UCS –总体上做得很好。不幸的是,向OSA-UCS的转换缺少解析逆,这使其不切实际。

IPT –出色地建模色调均匀性。不能很好地预测亮度和色度,但可以满足所有其他要求。计算简单,不依赖于比例/曝光。

JzAzBz –总体来说做得不错。设计用于HDR数据的亮度均匀缩放。尽管在某些情况下很有用,但这会导致对比例/曝光的依赖性,这使得在一般情况下很难使用。

sRGB的HSV表示–仅在此列表中,因为它已被广泛使用。除具有D65白点外,不满足任何要求。

在所有这些模型中,有两个模型脱颖而出:CAM16-UCS是总体上具有最佳感知均匀性的模型,而IPT是具有简单的计算结构,除了可以很好地预测亮度和色度之外,还可以满足所有要求。

因此,尝试以与IPT相同的计算结构尝试创建新的色彩空间是合理的,但在预测亮度和色度方面,其表现更接近CAM16-UCS。这项探索导致了Oklab。

使用CAM16和正常查看条件生成的具有相同亮度但具有随机色相和色度的成对颜色数据集。颜色仅限于Pointer的色域-可能的表面颜色集。

使用CAM16和正常查看条件生成的具有相同色度但具有随机色相和亮度的颜色对的已生成数据集。颜色仅限于Pointer的色域内

用于导出IPT的统一感知色相数据。根据这些数据,将颜色组合成具有相同感知色相的颜色对。

这些数据集可分别用于测试亮度,色度和色相的预测。如果色彩空间准确地为LLL,CCC和hhh建模,则亮度数据集中的所有对都应具有相同的LLL值,色度数据集中的所有对均应具有CCC值,并且色相数据集中的所有对均具有hh值。

为了测试色彩空间,不可能简单地在测试的色彩空间中检查预测中的距离,因为这将取决于色彩空间的缩放比例。准确预测L L L,C C C和h h h的地面真实值也是不可取的,因为与模型在每个坐标内具有相同的间距相比,我们的模型具有感知正交的坐标更为重要。

而是使用以下方法来创建独立于色彩空间的误差度量:

交换在一对中原本应该相同的坐标以生成一组新的变更对:对于明度数据集,在两个对之间交换L坐标,依此类推。

如果模型可以完美地预测数据集,那么这些变更对将等于原始对。

使用CIEDE2000计算原始颜色和更改的颜色之间的感知距离。

每对误差以两个色差中的最小值给出。

整个数据集的误差是色差的均方根误差。

Oklab是通过优化具有与IPT相同结构的色彩空间的参数而得出的,以在所有数据集上获得较低的误差。为了完整起见,这里是色彩空间的结构-要优化的参数是3x3矩阵M 1 \ mathbf {M_1} M 1和M 2 \ mathbf {M_2} M 2以及正数γ \γ。

(lms)= M 1×(XYZ)\ begin {pmatrix} l \\ m \\ s \ end {pmatrix} = \ mathbf {M_1} \ times \ begin {pmatrix} X \\ Y \\ Z \ end { pmatrix} l l l m s s = = = M××⎝⎛

(L ab)= M 2×(lγmγsγ)\ begin {pmatrix} L \\ a \\ b \ end {pmatrix} = \ mathbf {M_2} \ times \ begin {pmatrix} l ^ \ gamma \\ m ^ \ gamma \\ s ^ \ gamma \ end {pmatrix} L⎛L L a a b⎠= M = M 2×⎝⎛ lγmγsγ⎠⎞

还添加了一些额外的约束,因为此错误并不能单独确定颜色模型的比例和方向。

缩放a a a和b b b平面,以使大约50%的灰度沿亮度轴的色差比与a a和b b b平面的色差比与CIEDE2000预测的色差比相同。

使用这些约束条件,找到了一个很好的模型,但是基于结果,又做了两个更改。 γ\ gammaγ值最终非常接近1/3(0.323),并且当查看sRGB色域时,蓝色略微向内折叠,从而导致非凸sRGB色域。通过将γ\ gammaγ的值强制为1/3并添加一个约束条件,使蓝色不向内折叠,从而得出最终的Oklab模型。这些限制并未明显影响该错误。

为了能够将HSV包括在这些比较中,已通过将HSV解释为圆柱色空间并转换为规则网格,在此基础上定义了类似Lab的颜色空间。

这是跨颜色空间的三个不同数据集的误差,以均方根误差和第95个百分位数的形式给出。最好的结果在每行中以粗体突出显示(忽略CAM16,因为它是测试数据的来源)。由于亮度和色度数据是使用CAM16生成的,而不是来自实验的数据,因此该数据不能用来说明哪个模型最符合人类的感知。可以说,Oklab在预测色调方面做得很好,其色度和亮度预测与CAM16-UCS接近。

这是在各种颜色空间中绘制的Munsell比色图表数据(V = 5)。如果色彩空间的色度预测与Munsell数据的色度预测相匹配,则由数据形成的环应显示为正圆。此数据的质量有点难以评估,因为它不是直接使用实验数据,而是一种根据1940年代的实验数据创建的色表。

Oklab和CAM16-UCS似乎可以很好地预测Munsell数据,而其他空间则以各种方式挤压数据集中的圆圈,这表明Oklab可以比大多数色度预测色域做得更好。

这些图显示了三件事,椭圆,根据对Luo-Rigg数据集的色差的感知进行缩放,完整可见色域的形状(黑线对应于纯单波长光)和sRGB色域的一部分。

在CIELAB和OSA-UCS中,全色域的形状很奇怪,这可能意味着它们的预测对于高度饱和的颜色是非常不利的

除CAM16-UCS外,椭圆随着色度的增加而伸展。 CAM16显式压缩色度以更好地匹配实验数据,这使该数据看起来不错,但使颜色混合更糟

这是使用测试的各种颜色空间将白色与蓝色混合的图。选择了蓝色,因为它是空间之间变化最大的色调。 CIELAB,CIELUV和HSV都显示出色调向紫色转变。 CAM16的问题不同,颜色迅速变色,导致过渡看起来不像其他过渡一样。

这篇文章介绍了Oklab颜色空间,这是一种用于图像处理的感知颜色空间。 Oklab能够很好地预测感知的亮度,色度和色相,同时在数值上简单,行为良好且易于采用。

在以后的文章中,我想研究使用Oklab构建更好的感知颜色选择器等。

Oklab和这篇文章中的图像都是使用python,jupyter,numpy,scipy matplotlib,colorio和colour制作的。