Quel est l'algorithme pour créer des couleurs pour une carte thermique?
En supposant que les valeurs sont normalisées de 0 à 1, quel est l'algorithme pour obtenir une couleur pour créer une carte thermique comme celle-ci?
1 est rouge .5 est vert, 0 est bleu foncé.
Travailler dans RMagick / ImageMagick.
6 answers
Voici un extrait de code JavaScript pour générer du code couleur CSS hsl à partir de [0, 1] value
function heatMapColorforValue(value){
var h = (1.0 - value) * 240
return "hsl(" + h + ", 100%, 50%)";
}
Cet algorithme est basé sur la carte thermique à 5 couleurs ,
Dans cet algorithme, les couleurs correspondant aux valeurs sont
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%))
Si simple!
J'ai trouvé cela étonnamment facile à faire avec HSL.
Dans 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
Cette méthode renvoie les valeurs HSL sous la forme d'une chaîne comprise entre 0% et 100%. Il peut être utilisé avec RMagick ou ImageMagick.
Référence: ImageMagick LGV documentation.
En Java, pour CSS, testé:
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);
}
Notez la différence clé entre CSS et ImageMagick: la première valeur est 0-360 et sans signe de pourcentage.
L'interpolation linéaire des composants RVB fonctionne assez bien dans la pratique, et le lien partagé par Bruno mentionne faire votre interpolation dans HSL, ce qui peut aider.
Vous pouvez également intercaler vos trois couleurs de base avec des intermédiaires plus bien choisis. Découvrez http://colorbrewer2.org / pour de bonnes progressions de couleurs. Ensuite, divisez vos étapes plus loin:
0 red
0.25 yellow
0.5 green
0.75 cyan
1 blue
Une approche générale consiste à interpoler les couleurs. Vous avez décidé que
0: 0 0 255 (or any blue)
0.5: 0 255 0 (or any green)
1: 255 0 0 (or any red)
Vous faites simplement une interpolation linéaire du RVB. Entre 2 valeurs de référence (par exemple t entre 0 et 0,5), la couleur interpolée C est comme
C = (1 - t) * c0 + t * c1
Vous devez appliquer cette formule sur chaque composant de couleur RVB. Quelques autres conseils sur l'interpolation linéaire des couleurs: Comment interpoler une séquence de couleurs?
- - - - modifier ----- J'ai supprimé l'en-tête de ma réponse, car j'ai réalisé que j'avais mal compris le question (voir commentaire). Je laisse une copie pour une lecture cohérente, et des informations, juste au cas où.
Une première possibilité est de construire une heatmap de référence avec n'importe quel logiciel qui: créez une image 256X1pixel avec des valeurs de pixels de 0 à 255 et appliquez la heatmap souhaitée avec ImageMagick: ensuite, vous pouvez lire le RVB et construire une carte (valeur: RGB).
Je laisse ici une implémentation Swift 4 basée sur cet article de blog pour n'importe quelle quantité de couleurs! L'explication parfaite est là! J'espère que cela aide et fait gagner du temps à quelqu'un!
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
}
}
Voici une carte thermique simple à 5 couleurs en python (en pyqt, mais facile à généraliser)
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