Qual è l'algoritmo per creare colori per una heatmap?


Supponendo che i valori siano normalizzati da 0 a 1, qual è l'algoritmo per ottenere un colore per creare una heatmap come questa?

1 è rosso, .5 è verde, 0 è blu scuro.

Lavorare in RMagick / ImageMagick.

mappa termica

Author: B Seven, 2012-10-13

6 answers

Ecco uno snippet di codice JavaScript per generare codice colore CSS hsl dal valore [0, 1]

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

Questo algoritmo è basato su 5 color heatmap,

In questo algoritmo, i colori corrispondenti ai valori sono

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

Così semplice!

 41
Author: Mekajiki, 2015-08-29 01:29:54

Ho trovato questo sorprendentemente facile da fare con 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

Questo metodo restituisce i valori HSL come una stringa compresa tra 0% e 100%. Può essere utilizzato con RMagick o ImageMagick.

Riferimento: Documentazione ImageMagick HSL .

In Java, per CSS, testato:

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

Nota la differenza fondamentale tra CSS e ImageMagick: il primo valore è 0-360 e senza un segno di percentuale.

 15
Author: B Seven, 2020-06-04 04:25:34

L'interpolazione lineare dei componenti RGB funziona abbastanza bene nella pratica, e il link che Bruno ha condiviso menziona l'interpolazione in HSL che può aiutare.

Puoi anche intercalare i tuoi tre colori di base con intermedi più ben scelti. Controlla http://colorbrewer2.org / per alcune buone progressioni di colore. Quindi interrompi ulteriormente i tuoi passi:

0    red
0.25 yellow
0.5  green
0.75 cyan
1    blue
 11
Author: Superboggly, 2012-10-16 07:58:38

Un approccio generale è quello di interpolare i colori. Hai deciso che

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

Fai semplicemente un'interpolazione lineare del RGB. Tra 2 valori di riferimento (ad esempio t tra 0 e 0,5), il colore interpolato C è come

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

È necessario applicare questa formula su ogni componente di colore RGB. Alcuni altri suggerimenti sull'interpolazione lineare del colore: Come interpolare una sequenza di colori?

- - - - modifica ----- Ho rimosso l'intestazione della mia risposta, quando mi sono reso conto di aver frainteso il domanda (vedi commento). Lascio una copia per una lettura coerente e informazioni, per ogni evenienza.

Una prima possibilità è quella di costruire una heatmap di riferimento con qualsiasi software che: creare un'immagine 256X1pixel con valori di pixel da 0 a 255 e applicare la heatmap desiderata con ImageMagick: quindi è possibile leggere il RGB indietro e costruire una mappa (valore:RGB).

 4
Author: Bruno von Paris, 2017-05-23 10:31:30

Lascio qui un'implementazione Swift 4 basata su questo post del blog per qualsiasi quantità di colori! La spiegazione perfetta è lì! Spero che aiuta e consente di risparmiare un po ' di tempo a qualcuno!

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
    }
}
 1
Author: Andres, 2018-01-30 19:37:21

Ecco una semplice heatmap a 5 colori in python (in pyqt, ma facile da generalizzare)

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
Author: Tim, 2015-05-09 18:54:32