具有平滑过渡的16位灰度值的颜色映射

时间:2018-09-27 11:45:12

标签: colormap color-space color-mapping

我的数据精度为16位。尝试以8位灰度显示此数据会导致明显的条带化。我的想法是我可以将这16位值存储为彩色。例如,前8位可能在红色通道中,而后8位可能在绿色通道中。

但是,这将导致突然的过渡。从65280(255,0,0)变为65279(254,255,0)会导致颜色立即从红色变为黄色。这确实对人类的解释没有帮助。

我知道HSB可以很容易地提供360度的变化,但是360色值的确不比我已经有8级但灰度级的256种颜色值要多。

就以对人类有意义的方式转换的颜色而言,最合适的方式来表示0-65535之间的值?

2 个答案:

答案 0 :(得分:0)

我不清楚您为什么以(255,0,0)跟(254,255,0)的方式来计算RGB值。似乎应该以以下方式进行修改:

(0, 0, 0) -> (254, 0, 0) -> (254, 1, 0) -> (254, 254, 0) -> (254, 254, 1) -> (254, 254, 254)

这将表示从黑色到白色到红色,橙色和黄色的过渡,而没有任何突然的变化。由于我们的眼睛是非线性工作方式,因此可能无法感觉到它完全光滑,但您应该能够在不明显束缚的情况下进行操作。例如:

let canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d');

let rgb = [0, 0, 0]
// fill channels fromgre
for (let j = 0; j < 3; j++){
  for (let i = 0; i < 254; i++) {
    rgb[j]++
    ctx.fillStyle = `rgba(${rgb.join(",")}, 1)`
    ctx.fillRect(i +254*j, 0, 1, 50);
  }
}
<canvas id="canvas" width="765"></canvas>

或者从另一端开始以蓝色显示:

let canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d');

let rgb = [0, 0, 0]
// fill channels fromgre
for (let j = 0; j < 3; j++){
  for (let i = 0; i < 254; i++) {
    rgb[2-j]++
    ctx.fillStyle = `rgba(${rgb.join(",")}, 1)`
    ctx.fillRect(i +254*j, 0, 1, 50);
  }
}
<canvas id="canvas" width="765"></canvas>

答案 1 :(得分:0)

如果要保留一个属性,那就不可能做到这一点:相似的数字应该具有相似的颜色,或者反之亦然:完全不同的数字永远不应该具有相似的颜色。

但是,如果您写过有关条带的信息,则数据看起来好像是渐变的,因此,由于附近颜色的不同,如果两个不同的“数字区域”具有相似的颜色,那么我可以原谅我的眼睛。

我不会使用完整的16位(这太多了,我们不能清楚地看到所有RGB颜色,很少有人拥有真正好的显示器)。可能您可以构建一个界面,该界面可以放大并在限制范围内增加对比度。

对于更少的位,您可以先从蓝绿色(0,x,x)上升[x从0到255],然后移到绿色(0,255,x)[从255到0],然后移到黑色(0,x,0),从255到0,然后到黄色(x,x,0),然后到红色(255,0,0),然后到黑色,然后到紫色(x,0,x),然后变成蓝色,然后变成黑色,最后变成白色(x,x,x)。

所以10个刻度,这给了我们3个额外的信息位。

我可能永远也不会变黑(如您所见,这是重复的),而只是x直到5或10,这将减少位数。但是,我认为您仍然拥有11位信息,而且人眼可以分辨规模。

在此示例中,我使用了6种原色+次要颜色(+灰度),因此很容易区分它们。从理论上讲,可以使用其他中间色,但是我认为这会使我们的眼睛更加困惑。

我将提供一个附加输入来上下移动原始数据编号,以便用户可以在某些区域中检入更多详细信息(并获得更多位)。但是,如果附近的数字之间没有太多的极端变化,这很好用,