Java 计算颜色亮度的感知相等步长

Java 计算颜色亮度的感知相等步长,java,colors,processing,brightness,hsv,Java,Colors,Processing,Brightness,Hsv,我想弄明白这件事已经有一段时间了,我快疯了。正如大多数人所知道的,如果你在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 &

我想弄明白这件事已经有一段时间了,我快疯了。正如大多数人所知道的,如果你在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);
  }
}
void setup()
{
尺寸(600、150);
彩色模式(HSB,360,100,100);
背景(0,0,100);
翻译(50,50);
仰泳();
对于(int i=0;i<10;i++)
{
填充(0,0,i*10);
rect(i*50,0,50,50);
}
}
正如你所看到的,一些深色瓷砖之间的对比度比一些白色瓷砖之间的对比度要大得多

很多人都指出了这一点。约瑟夫·阿尔伯斯(Josef Albers)在他的《色彩艺术》(The Art of Color)一书中描述(基于韦伯·费希纳定律),你应该以指数级的速度增加亮度。后来证明,反照率确实如此,而使用亮度恒定对数增加的想法被证明是正确的。有很多关于这方面的论文,但其中很多对我来说很难阅读,而且大部分都与视网膜的物理方面有关

所以我的问题是:

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

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


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

对于希望在处理过程中执行此操作的其他人,以下是答案。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);
  }
}
导入有毒物质颜色。*;
进口toxi.geom.*;
无效设置()
{
尺寸(600250);
彩色模式(RGB,1,1,1);
背景(1);
仰泳();
翻译(50,50);
//RGB:10个矩形,其中感知对比度在所有正方形中不相等
用于(浮点i=0;i<10;i++)
{
填充(i/10.0、i/10.0、i/10.0);
rect(i*50,0,50,50);
}
//实验室:10个矩形,所有正方形的感知对比度相等
翻译(0,50);
对于(int i=0;i<10;i++)
{
float[]rgb=TColor.labToRGB(i*10,0,0);
TColor col=TColor.newRandom().setRGB(rgb);
填充(col.toARGB());
rect(i*50,0,50,50);
}
}
以下是输出:


由于HSB颜色空间依赖于设备,因此无法在HSB颜色空间上理解颜色感知。您需要熟悉CIE XYZ和CIE Lab*颜色空间。CIE实验室*帮助您进行感知。您必须查看从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。选择f的公式取决于Y/Y0是否大于或小于(6/29)^3,如果大于,则选择前者,否则选择后者。Y0通常取100左右。根据您的需要,您可以在internet上找到Y0的值。我个人总是用100来表示。注:Y0=Y零。非常感谢。我把答案贴在下面。我想我的方式是相当冗长的。我假设您必须在最后使用HSB颜色(您仍然可以使用RSB->HSB转换)。不管怎样,很高兴你找到了解决方案。我实际上认为库本身正在做你描述的事情:转换成XYZ空间,然后以某种方式转换成RGB。TColor类有一个toHSV()函数,因此在HSB colorMode中几乎相同。我得到的印象是,ColorSpace类的方法将做同样的事情,而不需要第三方依赖。