Existe-t-il une "valeur de couloeurs chromatiques" en Java/Scala ?

Le problème exposé dans ce sujet a été résolu.

Bonjour à tous,

Je cherche à attribuer un nom à une couleur RGB que je reçois en entrée. Pour simplifier les choses, j’aimerais utiliser un modèle qui donne, à partir des composantes R, G et B, une seule et unique valeur, comprise entre X et Y et qui soit unique.

EXEMPLE :

  1. Si j’obtiens une valeur comprise entre [ 0 ; 50 ] , il s’agirait d’un noir

  2. Entre [ 51 ; 100 ] : gris

  3. Entre [ 101 ; 170 ] : bleu

  4. Etc. jusqu’au blanc

Existe-t-il un tel modèle ? Si oui : quelle est la fonction Java / Scala permettant d’en faire usage ?

Merci d’avance !

Banni

Salut,

Si tu veux que l’association (r,g,b) ↦ la valeur unique soit continue (quand on bouge juste un peu la couleur, ça bouge juste un peu la valeur unique), cela n’est pas possible dans un cadre continu car l’espace des couleurs est tridimensionnel. L’espace des couleurs forme un carré, tu peux voir que si tu l’aplatis sur une droite sans le déchirer, il va y avoir deux couleurs envoyées au même endroit. Mais de toute manière on est dans un cadre discret.

Si tu ne demande pas la continuité, alors tu peux par exemple prendre (r,g,b) ↦ r+256×g+256²×b (représentation d’un nombre en base 256). De la même manière qu’un nombre en base 10 compris entre 0 et 999 correspond à trois chiffres, ici un nombre en base 256 compris entre 0 et 256³-1 correspond à trois « chiffres » (un entier entre 0 et 256-1).

Mais ensuite je n’ai pas bien compris : faut-il que (par exemple) le noir corresponde aux valeurs entre deux entiers spécifiques ? Si oui, peut-être que le modèle HSV t’intéressera : https://en.wikipedia.org/wiki/HSL_and_HSV . Tu peux essayer de découper le cylindre en autant de parties que tu as de couleurs (noir, gris, bleu…), puis simplement énumérer chacune de ces parties les unes à la suite des autres.

À la place d’une simple énumération tu peux aussi essayer de faire un parcours hamiltonien pour que les couleurs se suivent (c’est sûrement faisable mai il faudrait détailler les couleurs voulues).

Mais pourquoi veux-tu faire ça ?

edit Ah ok, j’ai relu le « Je cherche à attribuer un nom à une couleur RGB que je reçois en entrée. ». Dans ce cas je ne pense pas que ça simplifie de faire ce que tu dis (et je n’ai jamais entendu parler d’un tel identifiant des couleurs, ça m’étonnerait qu’une fonction standard existe pour faire ça). Ce que tu peux faire est énumérer les différentes couleurs « typiques » (bleu, noir, etc.) et prendre la plus proche de la couleur que tu veux catégoriser (par exemple en prenant la distance euclidienne dans l’espace RGB mais il y a sûrement des distances plus adaptées).

edit Il y a cette page qui peut être pertinente : https://en.wikipedia.org/wiki/Color_difference

+1 -0

Merci !

Je cherche simplement à découper les couleurs codées en RGB en catégories (qui sont leurs noms).

Comme ceci : https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/davidlean/WindowsLiveWriter/SQLReportingHowtoConditionalColor24Funct_B98C/image_8.png

Sauf que je souhaiterais ne pas devoir me baser sur les valeurs R, G et B pour déterminer cela.

Le code HTML serait une bonne solution, mais on ne peut pas l’utiliser en Java/Scala.

Garde en tête que le nom des couleurs est sujet à débat. Si tu prends un truc comme http://www.color-blindness.com/color-name-hue/ , je parie que tu trouveras des noms avec lesquels tu ne seras pas d’accord. C’est toujours le cas.

Si tu demandes aux gens le nom des couleurs suivantes : #008277, #00DDB1, #007F7B, #00DDB5, tu seras probablement surpris du résultat.

+1 -0
Banni

Dans la première partie de mon message je n’avais rien compris à ce que tu voulais faire.

Il existe plusieurs distances pour les couleurs, plus ou moins complexes. Le lien donné par victor utilise la distance $\sqrt{{d_\mathrm{RGB}}^2 + 2 {d_\mathrm{HSL}}^2}$ avec $d_\mathrm{RGB}$ et $d_\mathrm{HSL}$ les distances euclidiennes dans les modèles RGB et HSL.

Merci pour vos réponses,

J’ai opté pour une solution alternative : je récupère le code HTML hexadécimal du pixel à tester, et je le compare aux valeurs minimales et maximales indiquées dans cette image : http://e-bergi.com/media/images/2010-Mart-bmp2.jpg

Par "valeurs minimales et maximales", j’entends par exemple : "#FFFF00 à #00FFFF" qui désigne le vert (colonne "Green").

Du coup je regarde si le code HTML de mon pixel est supérieur à #FFFF00 et inférieur à #00FFFF et si c’est le cas, c’est du vert.

Je fais ça avec chacune des trois colonnes rouge, vert, bleu. Mais je n’ai pas le résultat voulu. Est-ce normal, ou ai-je selon vous commis une erreur d’inattention dans mes conditions de test ?

+0 -0

J’ai pas compris ton explication.

je regarde si le code HTML de mon pixel est supérieur à #FFFF00

Ça signifie quoi ? Tu fais ça comment ?

Es-tu certain que répartir toutes les couleurs de RGB dans trois bacs (soit rouge, soit vert, soit bleu) est possible ?

Quand tu dis que tu n’as pas le résultat voulu, ça veut dire quoi ? Tu lui donnes du jaune ou du noir, et comme ton programme ne peut que répondre rouge vert bleu il ne te dit jamais jaune ou noir ? Ou tu lui donnes un truc que tu vois vert mais qui est bleu et il te dit bleu ?

Par "valeurs minimales et maximales", j’entends par exemple : "#FFFF00 à #00FFFF" qui désigne le vert (colonne "Green").

Donc en fait ton programme ne donne "jaune" que pour le code FF FF 00 ? Est-ce que tu es d’accord avec ça ? Il n’y a vraiment qu’un seul jaune dans tout RGB ?

+0 -0

J’ai opté pour une solution alternative : je récupère le code HTML hexadécimal du pixel à tester, et je le compare aux valeurs minimales et maximales indiquées dans cette image : http://e-bergi.com/media/images/2010-Mart-bmp2.jpg

The-Aloha-Protocol

Bonjour,

Pour une classification simple avec ce genre d’intervalles par couleur, tu ferais mieux d’utiliser la teinte du format TSV.

Tu pourras aussi ajouter des conditions sur la saturation et la valeurs pour gérer les noirs, blancs et gris.

J’ai pas compris ton explication.

je regarde si le code HTML de mon pixel est supérieur à #FFFF00

Ça signifie quoi ? Tu fais ça comment ?

Es-tu certain que répartir toutes les couleurs de RGB dans trois bacs (soit rouge, soit vert, soit bleu) est possible ?

Quand tu dis que tu n’as pas le résultat voulu, ça veut dire quoi ? Tu lui donnes du jaune ou du noir, et comme ton programme ne peut que répondre rouge vert bleu il ne te dit jamais jaune ou noir ? Ou tu lui donnes un truc que tu vois vert mais qui est bleu et il te dit bleu ?

Par "valeurs minimales et maximales", j’entends par exemple : "#FFFF00 à #00FFFF" qui désigne le vert (colonne "Green").

Donc en fait ton programme ne donne "jaune" que pour le code FF FF 00 ? Est-ce que tu es d’accord avec ça ? Il n’y a vraiment qu’un seul jaune dans tout RGB ?

victor

Bonjour Victor, encore merci pour ton aide !

Je récupère le code hexa de la couleur (pas HTML, j’ai fait un abus de langage) et je regarde s’il est supérieur à FFFF00.

Je souhaite effectivement répartir toutes les couleurs de RGB dans des bacs (pas forcément juste rouge, bleu et vert). Je pense que c’est possible (il faut que ça le soit, sinon je devrais clairement abandonner mon projet).

Mon programme ne donnait pas le résultat voulu car il ne rangeait certains pixels dans aucune catégorie (actuellement rouge vert bleu).

Pour tout pixel dont le code hexa est compris entre FFFF00 et 00FFFFF, le programme doit retourner vert. Donc non, "jaune" ne sera pas retourné pour le code FFFF00. Par ailleurs, "jaune" ne sera jamais retourné (actuellement. (car seules trois catégories existent : rouge, vert et bleu)).

MAIS : j’ai opté pour l’utilisation de TSV (HSB en anglais), comme me l’a recommandé entwanne ! Donc tout ce qui est dit ci-dessus n’est plus valable a priori.

===========================

J’ai opté pour une solution alternative : je récupère le code HTML hexadécimal du pixel à tester, et je le compare aux valeurs minimales et maximales indiquées dans cette image : http://e-bergi.com/media/images/2010-Mart-bmp2.jpg

The-Aloha-Protocol

Bonjour,

Pour une classification simple avec ce genre d’intervalles par couleur, tu ferais mieux d’utiliser la teinte du format TSV.

Tu pourras aussi ajouter des conditions sur la saturation et la valeurs pour gérer les noirs, blancs et gris.

entwanne

Salut, merci !

J’essaie ta solution.

  1. Je convertis le code RGB du pixel en code TSV (HSB en anglais) : val color_hsb = Color.RGBtoHSB(color.getRed, color.getGreen, color.getBlue, null)

  2. D’après la JavaDoc, Color.RGBtoHSB retourne un tableau de float de taille 3. Le premier élément est la "hue" (i.e. : l’angle qui permet de définir la couleur hors-blanc et hors-noir - pour une saturation et luminosité suffisantes)

  3. Pour trouver un rouge, voici donc la condition que j’utilise : color_hsb(0) >= 0 && color_hsb(0) <= 90

Problème : l’angle donné n’est pas du tout compris dans l’intervalle [0;360], mais est un nombre à virgule qui semble compris entre 0 et 1 (rien dans la JavaDoc ne l’indique). En outre, multiplier ça par 1000 ou autre ne permet visiblement pas de récupérer le bon angle (i.e. : un angle compris entre [0;360]. Je pense que c’est parce qu’il s’agit de radians et non de degrés, je vais me renseigner à ce sujet.

EDIT :

Non, il semblerait que ce ne soit pas une histoire de radians/degrés. Effectivement : en partant du principe que la valeur est exprimée en radians, j’obtiens un degré de "32.29547373561102" (et un radian de "0.56366235") pour la couleur de code hexa "0090e9". Bref, je ne comprends pas. Gimp m’indique, quant à lui, une hue de "203" pour cette même couleur "0090e9".

+0 -0

Problème : l’angle donné n’est pas du tout compris dans l’intervalle [0;360], mais est un nombre à virgule qui semble compris entre 0 et 1 (rien dans la JavaDoc ne l’indique). En outre, multiplier ça par 1000 ou autre ne permet visiblement pas de récupérer le bon angle (i.e. : un angle compris entre [0;360]. Je pense que c’est parce qu’il s’agit de radians et non de degrés, je vais me renseigner à ce sujet.

The-Aloha-Protocol

Si la valeur retournée est comprise entre 0 et 1, il suffit de la multiplier par 360 pour obtenir un angle en degrés comme tu le souhaites.

Mais pourquoi ne pas directement travailler avec la valeur initiale ?

Non, il semblerait que ce ne soit pas une histoire de radians/degrés. Effectivement : en partant du principe que la valeur est exprimée en radians, j’obtiens un degré de "32.29547373561102" (et un radian de "0.56366235") pour la couleur de code hexa "0090e9". Bref, je ne comprends pas. Gimp m’indique, quant à lui, une hue de "203" pour cette même couleur "0090e9".

The-Aloha-Protocol

Je ne sais pas où tu es allé chercher cette histoire de radians, mais 0,564 × 360 donne une valeur proche de 203.

Une méthode simple et efficace : tu prends une liste de couleurs avec leurs noms, tu considère chaque couleur comme un point dans un espace donné par les composants de ladite couleur (RGB, TSV, etc.), et tu retourne le nom du plus proche voisin de ta couleur d’entrée.

C’est d’ailleurs à peu prés ce que fait le code JS de la page linkée plus haut par victor : http://chir.ag/projects/ntc/ntc.js

+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