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.
J'ai trouvé cela étonnamment facile à faire avec HSL.
En rubis:
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 entre 0% et 100%. Il peut être utilisé avec RMagick ou ImageMagick.
Référence: documentation ImageMagick HSL .
Voici un extrait de code JavaScript pour générer du code couleur CSS hsl à partir de la valeur [0, 1]
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!
L'interpolation linéaire des composants RVB fonctionne très bien dans la pratique, et le lien partagé par Bruno mentionne que votre interpolation en HSL peut vous aider.
Vous pouvez également entremêler vos trois couleurs de base avec des intermédiaires plus bien choisis. Consultez http://colorbrewer2.org/ pour de bonnes progressions de couleurs. Décomposez ensuite vos étapes:
0 red
0.25 yellow
0.5 green
0.75 cyan
1 blue
Une approche générale consiste à interpoler les couleurs. Tu as 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 effectuez 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 composante 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 je me suis rendu compte que j'avais mal compris la question (voir commentaire). Je laisse une copie pour une lecture cohérente et des informations, au cas où.
Une première possibilité est de construire une carte thermique de référence avec n'importe quel logiciel qui: créerait une image 256X1pixel avec des valeurs de pixel de 0 à 255 et appliquerait la carte thermique souhaitée avec ImageMagick: alors vous pouvez lire le RVB en arrière et construire une carte (valeur: RVB) .
Je laisse ici une Swift 4 implémentation basée sur ce billet de blog pour n'importe quelle quantité de couleurs! Une 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 simple carte thermique à 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