Se débarasser de la palette « jet » avec Jet Killer

Un outil pour améliorer les visualisations de données

Ce billet présente Jet Killer, le petit projet ayant occupé mes soirées ces derniers temps. L’idée de ce projet est venue d’une discussion sur le forum.

Contexte

Dans le monde de la visualisation de données, la palette de couleur « jet » faisait jusque récemment office de reine, et était utilisée comme palette par défaut, notamment dans Matlab. Cependant, cette palette présente des défauts importants :

  • elle n’est pas perceptuellement uniforme, ce qui peut masquer des détails ou créer des artefacts ;
  • elle peut poser des difficultés aux personnes atteintes de daltonisme, ce qui est assez courant chez les hommes.
Exemple utilisant « jet ».
Exemple de visualisation utilisant « jet ».

Ces différents défauts ont poussé à l’adoption de nouvelles palettes de couleurs à la fois perceptuellement uniformes et adaptées au daltonisme. Ces palettes de couleur ont été choisies comme valeur par défaut, et on trouve donc de plus en plus de visualisations utilisant « viridis » (palette par défaut de matplotlib) ou « parula » (palette par défaut de Matlab).

Exemple utilisant « viridis ».
Exemple de visualisation utilisant « viridis ».

Le problème

Au vu des défauts de « jet », il est conseillé de l’éviter en premier lieu, et de choisir la palette de couleur par défaut de son outil préféré (« viridis » dans mon cas). Si on a une vielle figure utilisant « jet » et qu’on dispose encore des données d’origine, il est également conseillé de régénérer la figure avec une meilleure palette de couleur (« viridis » est souvent amplement suffisante).

Cependant, quand on ne dispose pas des données d’origine, il n’est pas possible de faire tout cela… Pourtant, la situation peut arriver dans des cas relativement courants :

  • récupération de figures depuis une source ayant fait un choix malheureux de palette de couleurs,
  • utilisation de graphes tracés à partir de données ayant été possiblement perdues,
  • visualisation rapide d’un mauvais graphe sans se fatiguer à le régénérer depuis les données originelles.

Que faire alors ?

Une solution : Jet Killer

Pour répondre à ce genre de problématiques, j’ai écrit un petit outil en Python, qui s’appelle Jet Killer.

Le principe est très simple : à partir d’une image utilisant « jet », Jet Killer génère une image utilisant une meilleure palette de couleur.

Principe de fonctionnement de Jet Killer.
Principe de fonctionnement de Jet Killer.

Le traitement se fait directement sur les pixels, sans avoir besoin de connaissance des données sous-jacentes. Pour chaque pixel de l’image (à l’exception des gris), on trouve la couleur la plus proche sur la palette « jet », qu’on remplace par la couleur correspondante sur la palette d’arrivée. Les pixels gris ne sont pas modifiés, ce qui permet, dans une certaine mesure, de conserver les textes et cadres des visualisations.

Exemple de conversion.
Exemple de conversion. À gauche l’image d’origine (source), à droite le résultat.

Installation

L’outil est disponible sur PyPi. Pour l’installer, il suffit d’utiliser la commande suivante, qui installe le package jetkiller et la commande du même nom :

pip install jetkiller

Si vous souhaitez seulement tester, l’utilisation d’un virtualenv est évidemment conseillée.

Si vous ne disposez pas de Python, ni de pip, il vous faudra les installer.

Utilisation

En ligne de commande

Jet Killer est conçu principalement pour être utilisé en ligne de commande.

Utilisez la commande suivante pour convertir input_file en output_file:

jetkiller input_file output_file

Si vous omettez l’argument output_file, Jet Killer convertit par défaut input_file en "output.png":

jetkiller input_file

Si le fichier "output.png" existe déjà, il est écrasé sans avertissement.

Il est possible de changer la palette de couleur d’arrivée (par défaut "viridis") en utilisant l’option --colormap (ou sa dénomination courte -cm). N’importe quelle valeur des palettes de matplotlib est acceptée. Voilà un exemple utilisant « inferno » :

jetkiller input_file output_file --colormap inferno

Depuis Python

L’utilisation depuis Python se fait en important le package jetkiller et en utilisant la fonction jetkiller :

import jetkiller as jk
jk.jetkiller("input_image.png", "output_image.png")

Similairement à la ligne de commande, le nom du fichier de sortie peut être omis et prend alors la valeur par défaut "output.png" :

import jetkiller as jk
jk.jetkiller("input_image.png")

Toujours pareil qu’en ligne de commande, si le fichier "output.png" existe déjà, il est écrasé sans avertissement.

Le changement de la palette de couleur se fait avec l’argument optionel colormap, qui vaut "viridis" par défaut, mais qui peut prendre n’importe quelle valeur prise dans la liste des palettes de matplotlib.

import jetkiller as jk
jk.jetkiller("input_image.png", "output_image.png", colormap="inferno")

Formats d’image pris en charge

Jet Killer prend notamment en charge PNG et JPEG, ainsi que la plupart des formats pris en charge par le package Pillow sur lequel Jet Killer se repose pour la manipulation des images.


En savoir plus

Pour en savoir plus (mais vous savez presque déjà tout), rendez-vous sur le depôt du projet.

10 commentaires

Chouette projet ! Il serait pratique de pouvoir travailler avec des objets Image en lieu et place des noms de fichiers. Ça permettrait de lire une image avec Pillow, de découper le morceau à convertir (le graphe) et de le remplacer par sa nouvelle version.

+1 -0

En tout cas c’est un projet sympa, mais c’est dommage de ne pas traiter les pdf qui sont le standard dans le milieu de l’édition scientifique.

adri1

Si tu connais un moyen simple de le supporter, je suis preneur. Pillow sait écrire des PDF, mais pas les lire. Et de ce que je comprends, Pillow écrit en fait des JPEG dans des PDF, c’est un peu de la triche.

L’architecture actuelle de Jet Killer ne permet pas du tout de gérer facilement des images vectorielles ceci dit.

A quel point est-ce que la palette pose problème pour les gens ayant du daltonisme ? Il me semblait que peu importe la variante, le bleu et l’orange étaient les deux couleurs qui se distinguaient le mieux. Le rouge est pas forcément top mais ça m’intéresserait de savoir comment la nouvelle palette corrige le problème :)

Un excellent document à ce propos (et bien d’autres choses sur jet).

En deux images :

Jet.
Jet.
Viridis.
Viridis.

Avec jet, les deux extrêmes pour un daltonien seront bleu foncé et noir. Avec Viridis, ce sera bleu foncé et jaune pâle.

Et même pour un non daltonien, on voit bien à quel point jet, c’est pas une bonne idée. ^^

+3 -0

O_o

Merci ! Je ne connaissais pas du tout cette problématique, vraiment cool comme projet !

+0 -0

J’avais envie presque depuis le début de faire un plugin pour GIMP faisant la même chose que le programme décrit dans ce billet.

Depuis peu, c’est maintenant chose faite et en libre service sur GitHub : https://github.com/Arnaud-D/jetkiller-gimp. Il est même plus pratique à utiliser que le programme initial, tant que ce n’est pas pour faire du traitement par lot. Je ferai peut-être un billet dessus, mais ce n’est vraiment pas sûr (et pas tout de suite).

Au passage, j’ai découvert des bugs dans le projet d’origine, que j’ai corrigés. C’est toujours au même endroit, mais sous un autre nom : https://github.com/Arnaud-D/jetkiller-python.

+2 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte