【问题标题】:Calculate perceived equal steps in color brightness计算颜色亮度的感知相等步长
【发布时间】:2013-05-11 16:25:02
【问题描述】:

我一直试图弄清楚这一点,这让我发疯了。正如大多数人所知,如果你在 HSV 亮度的相等步长中绘制 10 个相邻的矩形,范围从白色到黑色,它们将不会被视为与眼睛相同。这是一个例子:

以及处理中的代码:

void setup()
{
  size(600, 150);
  colorMode(HSB, 360, 100, 100);
  background(0, 0, 100);

  translate(50, 50);

  noStroke();
  for(int i = 0; i < 10; i++)
  {
    fill(0, 0, i * 10);
    rect(i * 50, 0, 50, 50);
  }
}

如您所见,一些较暗的瓷砖之间的对比度比一些白色瓷砖的对比度要大得多。

很多人都指出了这一点。 Josef Albers 在他的《色彩的艺术》一书中描述了(基于 Weber-Fechner 定律)你应该以指数级增加亮度。后来证明,Albers 做到了some nasty miscalculations,并且使用恒定对数增加亮度的想法被证明是正确的only within very limited bounds。有很多关于这方面的论文,但其中很多对我来说很难阅读,而且大多数都与视网膜的物理方面有关。

所以我的问题是:

给定任何颜色,我如何计算从 HSV 亮度 0 到 100 的 感知 等亮度步长?

更好的是,我如何计算从任何一种颜色到任何其他颜色的感知相等的亮度步长?

我正在通过代码生成用于打印的文件,我需要在处理中执行此操作。不过,任何语言的任何示例都可以。

【问题讨论】:

  • 在 HSB 颜色空间上无法理解颜色的感知,因为它是依赖于设备的颜色空间。您需要熟悉 CIE XYZ 和 CIE Lab* 颜色空间。 CIE Lab* 帮助您进行感知。您将不得不查看从 CIE Lab* 到 HSB 的转换并相应地计算您的亮度。对于打印,您必须查看 HSB 到 CYMK 的计算。
  • 是的,我认为是这样。我有一个颜色库,可以轻松使用 CIE LAB。所以如果我在 LAB 中做同样的事情,用一个常数值改变 L,我会得到正确的输出吗?
  • 据我了解,您可以将 Lab* 转换为线性色彩空间 XYZ。然后,您将更改 Y 的值并使用以下公式将其转换为 L*:L* = 116 * f(Y/Y0) - 16,其中 f(Y/Y0) 可以是 (Y/Y0)^1/ 3 或 1/3*(29/6)^2*(Y/Y0)+4/29。您选择的公式取决于 Y/Y0 是大于还是小于 (6/29)^3,如果大于,则选择前一个公式,否则选择后者。 Y0 通常取 100 左右。您可以根据需要在 Internet 上找到 Y0 的值。我个人一直使用 100。注意:Y0=Y 无。
  • 非常感谢。我在下面发布了答案。

标签: java colors processing brightness hsv


【解决方案1】:

对于希望在 Processing 中执行此操作的其他人,这就是答案。 Toxiclibs TColor 类附带 LAB -> RGB 转换,所以并不难。正如您在屏幕截图中看到的,区别很明显。

import toxi.color.*;
import toxi.geom.*;

void setup()
{
  size(600, 250);
  colorMode(RGB, 1, 1, 1);
  background(1);
  noStroke();
  translate(50, 50);

  // RGB: 10 rects where perceived contrast is NOT equal in all squares
  for(float i = 0; i < 10; i++)
  {
    fill(i / 10.0, i / 10.0, i / 10.0);
    rect(i * 50, 0, 50, 50);
  }

  // LAB: 10 rects where perceived contrast IS equal in all squares
  translate(0, 50);

  for(int i = 0; i < 10; i++)
  {
    float[] rgb = TColor.labToRGB(i * 10, 0, 0);
    TColor col = TColor.newRandom().setRGB(rgb);
    fill(col.toARGB());
    rect(i * 50, 0, 50, 50);
  }
}

这是输出:

【讨论】:

  • +1。我想我的路很长。我假设您最后必须使用 HSB 颜色(您仍然可以使用 RSB -> HSB 转换)。无论如何,很高兴您找到了解决方案。
  • 我实际上认为库本身正在按照您的描述进行操作:转换为 XYZ 空间,然后以某种方式转换为 RGB。 TColor 类有一个 toHSV() 函数,所以它在 HSB colorMode 中几乎是一样的。
  • 我的印象是,ColorSpace 类的fromCIEXYZ 方法可以做同样的事情,而不需要第三方依赖。
猜你喜欢
  • 1970-01-01
  • 2017-12-17
  • 2020-04-23
  • 2020-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-20
  • 2023-03-04
相关资源
最近更新 更多