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.

heatmap

Author: B Seven, 2012-10-13

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!

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

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.

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

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
 11
Author: Superboggly, 2012-10-16 07:58:38

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

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

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

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