2012-10-13 9 views
24

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

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

Lavorare in RMagick/ImageMagick.

heatmap

+0

Checkout questo: - http://stackoverflow.com/questions/2343681/algorithm-for-heat-map –

risposta

13

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 valori HSL come una stringa tra 0% e 100%. Può essere utilizzato con RMagick o ImageMagick.

Riferimento: ImageMagick HSL documentation.

+0

h non è una percentuale ma un grado da 0 a 360 sulla ruota dei colori. – pixelearth

4

Un orientamento 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) 

È sufficiente fare un interpolazione lineare del RGB. tra 2 valori di riferimento (per 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 RGB colore. Alcuni altri suggerimenti circa l'interpolazione lineare di colore: How to interpolate a color sequence?

---- ----- modificare ho rimosso l'intestazione della mia risposta, quando mi resi conto ho frainteso la questione (vedi commento). Lascio una copia per una lettura coerente e informazioni, per ogni evenienza.

Una prima possibilità è di costruire una mappa termica di riferimento con qualsiasi software che: creare un'immagine 256X1pixel con valori di pixel da 0 a 255 e applicare la mappa termica desiderata con ImageMagick: allora si può leggere il RGB indietro e costruire una mappa (value: RGB).

+0

ImageMagick ha una mappa termica? –

+0

Nessun indizio. Ad ogni modo, non è il mio punto di partenza per il primo approccio, intendevo: creare un file con valori da 0-255, quindi applicare una heatmap con i tuoi strumenti preferiti e utilizzare la heatmap creata come riferimento. –

+0

Ah, ho capito di aver frainteso la tua ultima frase. Ho detto che la trasformazione del colore della heatmap funzionava in Image magick e che volevi farlo da solo in un codice. Modifico la mia risposta –

10

L'interpolazione lineare delle componenti RGB funziona abbastanza bene nella pratica e il collegamento Bruno condiviso menziona l'interpolazione in HSL che può essere d'aiuto.

È anche possibile interspondere i tre colori di base con intermedi più ben selezionati. Controlla http://colorbrewer2.org/ per alcune buone progressioni di colore. Quindi rompere ulteriormente i tuoi passi:

0 red 
0.25 yellow 
0.5 green 
0.75 cyan 
1 blue 
+2

Questo colorbrewer è fantastico! – Offirmo

17

Ecco un frammento di codice JavaScript per generare il codice colore CSS HSL da [0, 1] valore

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

Questo algoritmo è basato sul 5 color heatmap,

In questo algoritmo, i colori corrispondenti con i 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!

+0

Bella soluzione e questo codice converte HSL in RGB https://github.com/optimisme/javascript-temperatureMap/blob/master/temperatureMap.js#L57 –

0

Ecco un semplice heatmap 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 
+2

Risposta decente ma prova a spiegare il codice in modo che l'OP possa capirlo piuttosto che usarlo senza coglierlo! – ShellFish

0

lascio qui un'implementazione Swift 4 sulla base delle this blog post per qualsiasi quantità di colori! La spiegazione perfetta è lì! Spero che aiuti e risparmia 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 
    } 
}