Ale*_*kov 11 algorithm wolfram-mathematica colors
我需要一种算法将HCL颜色转换为RGB,然后将RGB转换为HCL,同时要记住这些颜色空间具有不同的色域(我需要将HCL颜色约束为可以在RGB颜色空间中再现的颜色).算法是什么(该算法旨在在Wolfram Mathematica中实现,仅支持原生RGB颜色)?我没有使用色彩空间的经验.
PS一些关于HCL颜色的文章:
M. Sarifuddin(2005年).一种新的感知统一色彩空间,具有相关的颜色相似性度量,用于基于内容的图像和视频检索.
Zeileis,Hornik和Murrell(2009年):逃离RGBland:为统计图形选择颜色//计算统计和数据分析第53卷,第9期,2009年7月1日,第3259-3270页
更新: 正如Jonathan Jansson所指出的,在上述两篇文章中,不同的颜色空间用名称"HCL"描述:"第二篇文章使用L C h(uv),它与L u v*相同,但在极地中描述coordiates其中h(uv)是u*和v*坐标的角度,C*是该向量的大小".所以实际上我需要一种算法将RGB转换为L u v*并向后转换.
小智 7
我也只是在学习HCL色彩空间.您问题中两篇文章中使用的颜色空间似乎是不同的颜色空间.
第二篇文章使用L*C*h(uv),它与L*u*v*相同,但在极坐标中描述,其中h(uv)是u*和v*坐标的角度,C*是幅度那个向量.
第一篇文章中的LCH颜色空间似乎描述了另一个颜色空间,而不是使用更多算法转换.这里还有另一个版本的第一篇论文:http://isjd.pdii.lipi.go.id/admin/jurnal/14209102121.pdf
如果您打算使用CIE L*u*v*,则需要先将sRGB转换为CIE XYZ,然后转换为CIE L*u*v*.在大多数情况下,RGB实际上是指sRGB,因此无需从RGB转换为sRGB.
但我无法回答有关如何将颜色约束到sRGB空间的问题.您可以在转换后丢弃超出0到1范围的RGB颜色.只是夹紧颜色会产生非常奇怪的结果.尝试转到转换器并输入颜色RGB 0 0 255并转换为L*a*b*(类似于L*u*v*),然后将L*增加到70并将其转换回来,结果肯定是不再是蓝色了.
编辑:更正了URL编辑:将另一个答案合并到此答案中
HCL 是一个非常通用的名称,可以通过多种方式获得色调、色度和亮度。例如,Chroma.js 有一个叫做 HCL 的东西,它是极坐标转换实验室(当你查看实际代码时)。其他实现,即使是从同一站点链接的实现也使用 Polar Luv。由于您可以简单地借用 L 因子并通过转换为极坐标来导出色调,因此这些都是获得这三个元素的有效方法。由于混淆因素,将它们称为 Polar Lab 和 Polar Luv 会好得多。
M. Sarifuddin (2005) 的算法不是 Polar Luv 或 Polar Lab,并且在计算上更简单(您不需要先推导出 Lab 或 Luv 空间),实际上可能更好。论文中有些地方似乎是错误的。例如,将欧几里得距离应用于 CIE L*C*H* 色彩空间。使用 Hue 意味着它必须是圆形的,只是将这个数字塞进 A²+B²+C² 会给你带来问题。将基于色调的色彩空间应用于 D94 或 D00 也是如此,因为这些是距离算法,具有特定于 Lab 色彩空间的内置校正。除非我在那里遗漏了什么,否则我会忽略数字 6-8。我质疑图形中的拒绝容差。您可以设置较低的阈值并做得更好,并且颜色空间之间的数字未标准化。在任何情况下,尽管论文中存在一些看似缺陷,但所描述的算法值得一试。如果不是很重要,您可能想要在 RGB 上进行欧几里得运算。但是,如果您正在四处寻找颜色距离算法,那么您就可以了。
这是由 M. Sarifuddin 给出的用 Java 实现的 HCL。反复阅读这篇论文后,我无法避免得出这样的结论,即它根据 distance_hcl 例程中的色调变化将距离缩放了 0.16 到 180.16 之间的系数。这是一个如此深刻的因素,几乎不可能是正确的。并使配色变得糟糕。我已经注释掉了论文的行,并使用了仅包含 Al 因子的行。以常数 ~1.4 因子缩放 Luminescence 不会使其无法使用。没有任何比例因子,它最终与 cycldistance 相同。
http://w3.uqo.ca/missaoui/Publications/TRColorSpace.zip是论文的修正和改进版本。
static final public double Y0 = 100;
static final public double gamma = 3;
static final public double Al = 1.4456;
static final public double Ach_inc = 0.16;
public void rgb2hcl(double[] returnarray, int r, int g, int b) {
double min = Math.min(Math.min(r, g), b);
double max = Math.max(Math.max(r, g), b);
if (max == 0) {
returnarray[0] = 0;
returnarray[1] = 0;
returnarray[2] = 0;
return;
}
double alpha = (min / max) / Y0;
double Q = Math.exp(alpha * gamma);
double rg = r - g;
double gb = g - b;
double br = b - r;
double L = ((Q * max) + ((1 - Q) * min)) / 2;
double C = Q * (Math.abs(rg) + Math.abs(gb) + Math.abs(br)) / 3;
double H = Math.toDegrees(Math.atan2(gb, rg));
/*
//the formulae given in paper, don't work.
if (rg >= 0 && gb >= 0) {
H = 2 * H / 3;
} else if (rg >= 0 && gb < 0) {
H = 4 * H / 3;
} else if (rg < 0 && gb >= 0) {
H = 180 + 4 * H / 3;
} else if (rg < 0 && gb < 0) {
H = 2 * H / 3 - 180;
} // 180 causes the parts to overlap (green == red) and it oddly crumples up bits of the hue for no good reason. 2/3H and 4/3H expanding and contracting quandrants.
*/
if (rg < 0) {
if (gb >= 0) H = 90 + H;
else { H = H - 90; }
} //works
returnarray[0] = H;
returnarray[1] = C;
returnarray[2] = L;
}
public double cycldistance(double[] hcl1, double[] hcl2) {
double dL = hcl1[2] - hcl2[2];
double dH = Math.abs(hcl1[0] - hcl2[0]);
double C1 = hcl1[1];
double C2 = hcl2[1];
return Math.sqrt(dL*dL + C1*C1 + C2*C2 - 2*C1*C2*Math.cos(Math.toRadians(dH)));
}
public double distance_hcl(double[] hcl1, double[] hcl2) {
double c1 = hcl1[1];
double c2 = hcl2[1];
double Dh = Math.abs(hcl1[0] - hcl2[0]);
if (Dh > 180) Dh = 360 - Dh;
double Ach = Dh + Ach_inc;
double AlDl = Al * Math.abs(hcl1[2] - hcl2[2]);
return Math.sqrt(AlDl * AlDl + (c1 * c1 + c2 * c2 - 2 * c1 * c2 * Math.cos(Math.toRadians(Dh))));
//return Math.sqrt(AlDl * AlDl + Ach * (c1 * c1 + c2 * c2 - 2 * c1 * c2 * Math.cos(Math.toRadians(Dh))));
}
Run Code Online (Sandbox Code Playgroud)
正如其他答案中提到的,有很多方法可以实现 HCL 颜色空间并将其映射到 RGB。
HSLuv最终成为我使用的,并且具有 MIT 许可的 C、C#、Go、Java、PHP 和其他几种语言的实现。它与 CIELUV LCh 类似,但完全映射到 RGB。这些实现可以在 GitHub 上找到。
下面是网站上描述 HSLuv 色彩空间的简短图形,右侧两个面板中包含实现输出:
小智 5
我正在寻找在网络上插入颜色的方法,发现 HCL 是最合适的颜色空间,我找不到任何库可以使转换变得简单且高性能,所以我编写了自己的库。
有许多常量在起作用,其中一些常量根据来源的不同而有很大差异。
我的目标是网络,我认为最好匹配 chromium 源代码。这是用 Typescript 编写的最小化片段,sRGB XYZ 矩阵是预先计算的,所有常量都是内联的。
const rgb255 = (v: number) => (v < 255 ? (v > 0 ? v : 0) : 255);
const b1 = (v: number) => (v > 0.0031308 ? v ** (1 / 2.4) * 269.025 - 14.025 : v * 3294.6);
const b2 = (v: number) => (v > 0.2068965 ? v ** 3 : (v - 4 / 29) * (108 / 841));
const a1 = (v: number) => (v > 10.314724 ? ((v + 14.025) / 269.025) ** 2.4 : v / 3294.6);
const a2 = (v: number) => (v > 0.0088564 ? v ** (1 / 3) : v / (108 / 841) + 4 / 29);
function fromHCL(h: number, c: number, l: number): RGB {
const y = b2((l = (l + 16) / 116));
const x = b2(l + (c / 500) * Math.cos((h *= Math.PI / 180)));
const z = b2(l - (c / 200) * Math.sin(h));
return [
rgb255(b1(x * 3.021973625 - y * 1.617392459 - z * 0.404875592)),
rgb255(b1(x * -0.943766287 + y * 1.916279586 + z * 0.027607165)),
rgb255(b1(x * 0.069407491 - y * 0.22898585 + z * 1.159737864)),
];
}
function toHCL(r: number, g: number, b: number) {
const y = a2((r = a1(r)) * 0.222488403 + (g = a1(g)) * 0.716873169 + (b = a1(b)) * 0.06060791);
const l = 500 * (a2(r * 0.452247074 + g * 0.399439023 + b * 0.148375274) - y);
const q = 200 * (y - a2(r * 0.016863605 + g * 0.117638439 + b * 0.865350722));
const h = Math.atan2(q, l) * (180 / Math.PI);
return [h < 0 ? h + 360 : h, Math.sqrt(l * l + q * q), 116 * y - 16];
}
Run Code Online (Sandbox Code Playgroud)
这是上面代码片段的游乐场。
它包括 d3 的 interpolateHCL 和浏览器本机 css 转换以进行比较。
https://svelte.dev/repl/0a40a8348f8841d0b7007c58e4d9b54c
以下是在任何 Web 颜色格式之间进行转换并将其插值到 HCL 颜色空间的要点。
https://gist.github.com/pushkine/c8ba98294233d32ab71b7e19a0ebdbb9
| 归档时间: |
|
| 查看次数: |
9629 次 |
| 最近记录: |