42

假设值从 0 标准化为 1,那么获取颜色以创建这样的热图的算法是什么?

1 为红色,0.5 为绿色,0 为深蓝色。

在 RMagick / ImageMagick 中工作。

热图

4

6 回答 6

45

这是一个 JavaScript 代码片段,用于从 [0, 1] 值生成 CSS hsl 颜色代码

function heatMapColorforValue(value){
  var h = (1.0 - value) * 240
  return "hsl(" + h + ", 100%, 50%)";
}

该算法基于5 色热图

在该算法中,与值对应的颜色为

0    : blue   (hsl(240, 100%, 50%))
0.25 : cyan   (hsl(180, 100%, 50%))
0.5  : green  (hsl(120, 100%, 50%))
0.75 : yellow (hsl(60, 100%, 50%))
1    : red    (hsl(0, 100%, 50%))

很简单!

于 2014-12-03T04:55:17.377 回答
15

我发现使用 HSL 非常容易做到这一点。

在红宝石中:

def heatmap_color_for value # [0,1]
  h = (1 - value) * 100
  s = 100
  l = value * 50
  "hsl(#{h.round(2)}%,#{s.round(2)}%,#{l.round(2)}%)"
end

此方法将 HSL 值作为 0% 到 100% 之间的字符串返回。它可以与 RMagick 或 ImageMagick 一起使用。

参考:ImageMagick HSL 文档

在 Java 中,对于 CSS,测试:

private String getHeatmapColorForCSS(double normalizedValue0to1) {
    double h = (1 - normalizedValue0to1) * 360;
    double s = 100;
    double l = 50;
    return String.format("hsl(%.2f, %.2f%%, %.2f%%)", h, s, l);
}

请注意 CSS 和 ImageMagick 之间的主要区别:第一个值是 0-360 并且没有百分号。

于 2012-10-17T13:50:39.003 回答
11

RGB 分量的线性插值在实践中效果很好,Bruno 分享的链接提到在 HSL 中进行插值可以提供帮助。

您还可以将您的三种基本颜色与更精心选择的中间色散布。查看http://colorbrewer2.org/了解一些不错的颜色渐变。然后进一步分解你的步骤:

0    red
0.25 yellow
0.5  green
0.75 cyan
1    blue
于 2012-10-16T07:58:38.020 回答
4

一般的方法是插入颜色。你决定了

0: 0 0 255 (or any blue)
0.5: 0 255 0 (or any green)
1: 255 0 0 (or any red)

您只需对 RGB 进行线性插值。在 2 个参考值之间(例如 0 和 0.5 之间的 t),插值颜色 C 就像

C = (1 - t) * c0 + t * c1

您必须在每个颜色分量 RGB 上应用此公式。关于颜色线性插值的其他一些提示: 如何插入颜色序列?

---- 编辑 ----- 我删除了答案的标题,因为我意识到我误解了这个问题(见评论)。为了以防万一,我留下一份副本以供一致阅读和信息。

第一种可能性是使用任何软件构建参考热图:创建像素值从 0 到 255 的图像 256X1pixel 并使用 ImageMagick 应用所需的热图:然后您可以读取 RGB 并构建地图(值:RGB) .

于 2012-10-13T18:10:40.147 回答
1

我在这里留下了一个基于这篇博文的 Swift 4 实现,用于任意数量的颜色!完美的解释就在那里!希望它对某人有所帮助并节省一些时间!

import Foundation
import UIKit

struct ColorPoint {
    let color: UIColor
    let value: CGFloat
}

class HeatMapColor {
    var colorPoints: [ColorPoint]

    init(colorPoints: [ColorPoint]) {
        self.colorPoints = colorPoints
    }

    func colorAt(value: CGFloat) -> UIColor {
        if(colorPoints.isEmpty) { return UIColor.black }

        let colorsPointsToUse = colorPoints.sorted { (colorPointA, colorPointB) -> Bool in
            return colorPointA.value <= colorPointB.value
        }

        for (index, colorPoint) in colorsPointsToUse.enumerated() where value < colorPoint.value {
            let previousColorPoint = colorsPointsToUse[max(0, index - 1)]
            let valueDiff = previousColorPoint.value - colorPoint.value
            let fraction = valueDiff == 0 ? 0 : (value - colorPoint.value) / valueDiff

            guard
                let prevComp = previousColorPoint.color.cgColor.components,
                let currComp = colorPoint.color.cgColor.components else { continue }

            let red = (prevComp[0] - currComp[0]) * fraction + currComp[0]
            let green = (prevComp[1] - currComp[1]) * fraction + currComp[1]
            let blue = (prevComp[2] - currComp[2]) * fraction + currComp[2]

            return UIColor(red: red, green: green, blue: blue, alpha: 1.0)
        }

        return colorsPointsToUse.last!.color
    }
}
于 2018-01-30T19:37:21.953 回答
0

这是python中的一个简单的5色热图(在pyqt中,但易于概括)

def genColorMap(self):
    points = [(255,0,0), (255,255,0), (0,255,0), (0,255,255), (0,0,255)]
    cm = {}
    for i in range(0, 256):
        p0 = int(numpy.floor((i/256.0)/len(points)))
        p1 = int(numpy.ceil((i/256.0)/len(points)))
        rgb = map(lambda x: x[0]*max(0,(i-p0)) + x[1]*max(0,(i-p1)), zip(points[p0], points[p1]))
        cm[i] = QtGui.qRgb(rgb[0], rgb[1], rgb[2])
    return cm
于 2015-05-09T18:54:32.777 回答