What is the algorithm to create colors for a heatmap?

后端 未结 6 1513
你的背包
你的背包 2021-01-30 10:31

Assuming values are normalized from 0 to 1, what is the algoritm to get a color to create a heatmap like this?

1 is red, .5 is green, 0 is dark blue.

Working in

相关标签:
6条回答
  • 2021-01-30 11:11

    I leave here a Swift 4 implementation based on this blog post for any amount of colors! Perfect explanation is there! Hope it helps and saves some time to someone!

    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
        }
    }
    
    0 讨论(0)
  • 2021-01-30 11:14

    Here is a JavaScript code snippet to generate CSS hsl color code from [0, 1] value

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

    This algorithm is based on the 5 color heatmap,

    In this algorithm, the colors corresponding with values are

    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%))
    

    So simple!

    0 讨论(0)
  • 2021-01-30 11:19

    Here's a simple 5 color heatmap in python (in pyqt, but easy to generalize)

    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
    
    0 讨论(0)
  • 2021-01-30 11:22

    A general approach is to interpolate colors. You decided that

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

    You simply do a linear interpolation of the RGB. Between 2 reference values (eg t between 0 and 0.5), the interpolated color C is like

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

    You must apply this formula on each color component RGB. Some other hints about color linear interpolation: How to interpolate a color sequence?

    ---- edit ----- I removed the header of my answer, as I realized I misunderstood the question (see comment). I leave a copy for consistent reading, and information, just in case.

    A first possibility is to build a reference heatmap with any software that would: create a image 256X1pixel with pixel values from 0 to 255 and apply the desired heatmap with ImageMagick: then you can read the RGB back and build a map (value:RGB).

    0 讨论(0)
  • 2021-01-30 11:23

    Linear interpolation of the RGB components works quite well in practice, and the link Bruno shared mentions doing your interpolation in HSL which can help.

    You can also intersperse your three basic colours with more nicely chosen intermediates. Check out http://colorbrewer2.org/ for some good colour progressions. Then break up your steps further:

    0    red
    0.25 yellow
    0.5  green
    0.75 cyan
    1    blue
    
    0 讨论(0)
  • 2021-01-30 11:34

    I found this surprisingly easy to do with HSL.

    In Ruby:

    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
    

    This method returns HSL values as a string between 0% and 100%. It can be used with RMagick or ImageMagick.

    Reference: ImageMagick HSL documentation.

    In Java, for CSS, tested:

    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);
    }
    

    Note the key difference between CSS and ImageMagick: the first value is 0-360 and without a percent sign.

    0 讨论(0)
提交回复
热议问题