2010-06-10 3 views
15

Je voudrais trier une liste de couleurs unidimensionnelle de sorte que les couleurs qu'un humain typique percevrait comme "similaires" les unes aux autres sont proches les unes des autres. Il est évident que c'est un problème difficile ou peut-être impossible à obtenir "parfaitement", car les couleurs sont généralement décrites en trois dimensions, mais cela ne signifie pas qu'il n'y a pas de méthodes de tri qui semblent plus naturelles que d'autres.Trier une liste de couleurs dans une dimension?

Par exemple, le tri par RVB ne fonctionne pas très bien, car il triera dans l'ordre suivant, par exemple:

(1) R = 254 G = 0 B = 0 (2) R = 254 G = 255 B = 0 (3) R = 255 G = 0 B = 0 (4) R = 255 G = 255 B = 0

Autrement dit, il alterne les couleurs rouge, jaune, rouge, jaune, avec les deux "rouges" étant essentiellement imperceptiblement différents les uns des autres, et les deux jaunes étant également imperceptiblement différents les uns des autres.

Mais le tri par HLS fonctionne beaucoup mieux, d'une manière générale, et je pense que la technologie HSL est encore meilleure que cela; avec l'un ou l'autre, les rouges seront côte à côte et les jaunes seront les uns à côté des autres.

Mais HLS/HSL a aussi quelques problèmes; les choses que les gens percevraient comme «noires» pourraient être séparées les unes des autres, tout comme les choses que les gens percevraient comme «blanches».

Encore une fois, je comprends que je dois à peu près accepter qu'il y aura des divisions comme ceci; Je me demande simplement si quelqu'un a trouvé un meilleur moyen que HLS/HSL. Et je suis conscient que "mieux" est quelque peu arbitraire; Je veux dire "plus naturel à un humain typique". Par exemple, une vague pensée que j'ai eue, mais que je n'ai pas encore essayée, est peut-être «L est la chose la plus importante si elle est très haute ou très basse», mais sinon c'est la moins importante. Quelqu'un at-il essayé cela? Cela a-t-il bien fonctionné? Qu'est-ce que vous avez spécifiquement décidé "très bas" et "très haut"? Etc. Ou est-ce que quelqu'un a trouvé autre chose qui améliorerait HSL? Je devrais également noter que je suis conscient que je peux définir une courbe remplissant l'espace à travers le cube de couleurs, et les ordonner unidimensionnellement comme ils seraient rencontrés tout en voyageant le long de cette courbe. Cela éliminerait les discontinuités perçues. Cependant, ce n'est pas vraiment ce que je veux; Je veux des groupements globaux décents à grande échelle plus que je ne veux des groupements parfaits à petite échelle.

Merci d'avance pour toute aide.

+0

Combien de couleurs (à peu près) parlons-nous? Et avez-vous besoin d'un algorithme pour cela, ou est-ce qu'une approche basée sur une table ou un seau serait suffisante? –

Répondre

4

Il existe deux approches possibles. L'approche simple consiste à distiller chaque couleur en une seule valeur, et la liste des valeurs peut ensuite être triée. L'approche complexe dépend de toutes les couleurs que vous devez trier; peut-être que ce serait une solution itérative qui mélange à plusieurs reprises les couleurs autour d'essayer de minimiser l'énergie de toute la séquence. Je suppose que vous voulez quelque chose de simple et rapide qui semble "assez sympa" (plutôt que d'essayer de comprendre le type de couleur esthétique "optimale"), donc l'approche simple est suffisante pour vous.

Je dirais que HSL est la voie à suivre. Quelque chose comme

sortValue = L * 5 + S * 2 + H 

en supposant que H, S et L sont chacun dans l'intervalle [0, 1].

+0

J'ai essayé cela et ça marche vraiment très bien. Je vous remercie. – liviucmg

+1

Est-ce que vous venez avec vous-même ou avez-vous une référence pour moi? – Sander

0

Voici une idée que j'ai trouvée après quelques minutes de réflexion. C'est peut-être de la merde, ou peut-être même pas du tout, mais je cracherai quand même.

définir une fonction de la distance sur l'espace des couleurs, d(x, y) (où les entrées x et y sont des couleurs et la sortie est peut-être un nombre à virgule flottante). La fonction de distance que vous choisissez n'est peut-être pas très importante. Il pourrait s'agir de la somme des carrés des différences dans les composantes R, G et B, disons, ou il peut s'agir d'un polynôme dans les différences dans les composantes H, L et S (les composantes étant pondérées différemment selon l'importance qu'elles sont).

Ensuite, vous calculez la "distance" de chaque couleur dans votre liste les uns des autres, ce qui vous donne effectivement un graphique. Ensuite, vous calculez le spanning tree minimum de votre graphique. Ensuite, vous identifiez le chemin le plus long (sans backtracking) qui existe dans votre MST. Les extrémités de ce chemin seront les extrémités de la liste finale. Ensuite, vous essayez de "aplatir" l'arbre en une ligne en amenant des points dans les "branches" de votre chemin dans le chemin lui-même.

Hmm. Cela ne fonctionnera peut-être pas très bien si votre MST finit par prendre la forme d'un espace de couleur proche de la boucle. Mais peut-être que toute approche aurait ce problème.

0
A. R=254 G=0 B=0 
B. R=254 G=255 B=0 
C. R=255 G=0 B=0 
D. R=255 G=255 B=0 

Vous devez regarder la différence entre les couleurs voisines.

La diff entre A et B est 0 + 255 + 0 = 255. La diff entre A et C est égal à 1 + 0 + 0 = 1.

La diff entre A et B est supérieur à A et C si A est plus proche de C, de sorte échanger B et C.

A. R=254 G=0 B=0 
C. R=255 G=0 B=0 
B. R=254 G=255 B=0 
D. R=255 G=255 B=0 

La diff entre C et B est 1 + 255 + 0 = 256. La diff entre C et D est égal à 0 + 255 + 0 = 255 La différence entre C et B est plus grande que C et D donc C est plus proche de D, donc échange B et D.

A. R=254 G=0 B=0 
C. R=255 G=0 B=0 
D. R=255 G=255 B=0 
B. R=254 G=255 B=0 

Traitez-le comme un tri à bulles. Ce n'est pas un algorythme parfait par tous les moyens et il y a probablement de meilleures façons d'aborder cela, mais cela pourrait être un coup de pied dans la bonne direction.

aussi ...

Vous auriez besoin d'une certaine façon funky de comparer sur votre sujet.

5

Vous ne pouvez pas faire cela sans réduire les 3 dimensions de couleur à une seule mesure. Il existe de nombreux moyens (infinis) de réduire cette information, mais il n'est pas mathématiquement possible de faire en sorte que deux points de données proches les uns des autres sur le continuum réduit soient également proches l'un de l'autre dans leurs trois couleurs valeurs. Par conséquent, toute formule de ce type finira potentiellement par regrouper des couleurs dissemblables. Comme vous l'avez mentionné dans votre question, une façon de procéder consiste à insérer une courbe complexe dans l'espace colorimétrique tridimensionnel occupé par les points de données que vous tentez de trier, puis à réduire chaque point de données à son emplacement le plus proche sur la courbe, puis à la distance de ce point le long de la courbe. Cela fonctionnerait, mais dans chaque cas, il s'agirait d'une solution personnalisée à un ensemble particulier de points de données (plutôt qu'une solution généralement applicable).Ce serait également relativement cher (peut-être), et ne fonctionnerait tout simplement pas sur un ensemble de données qui n'était pas bien distribué de façon incurvée.

Une alternative plus simple (qui ne fonctionnerait pas parfaitement) serait de choisir deux couleurs "d'extrémité", de préférence sur les côtés opposés de la roue chromatique. Ainsi, par exemple, vous pouvez choisir Rouge comme couleur de point final et Bleu comme l'autre. Vous devez ensuite convertir chaque point de données de couleur en une valeur sur une échelle de 0 à 1, où une couleur fortement rougeâtre obtiendrait un score proche de 0 et une couleur fortement bleutée obtiendrait un score proche de 1. Un score de. 5 indiquerait une couleur qui n'a pas de rouge ou de bleu (ou vert) ou bien a des quantités égales de rouge et de bleu (aka violet). Cette approche n'est pas parfaite, mais c'est ce que vous pouvez faire de mieux avec ce problème.

4

Il existe plusieurs techniques standard pour réduire plusieurs dimensions à une seule dimension avec une certaine notion de «proximité».

Je pense que vous devriez en particulier consulter le z-order transform.

Vous pouvez implémenter une version rapide de ceci en intercalant les bits de vos trois composants de couleur et en triant les couleurs en fonction de cette valeur transformée.

Le code Java suivant devrait vous aider à démarrer:

public static int zValue(int r, int g, int b) { 
      return split(r) + (split(g)<<1) + (split(b)<<2); 
    } 

    public static int split(int a) { 
      // split out the lowest 10 bits to lowest 30 bits 
      a=(a|(a<<12))&00014000377; 
      a=(a|(a<<8)) &00014170017; 
      a=(a|(a<<4)) &00303030303; 
      a=(a|(a<<2)) &01111111111; 
      return a; 
    } 
+1

p.s.Il est intéressant de noter que cette approche est également très rapide grâce au fait que vous pouvez l'implémenter avec des opérations au niveau du bit. – mikera

+1

Notez également qu'une courbe de Hilbert pourrait être une bonne alternative – mikera

+0

Extrêmement en retard, mais pour ceux qui sont plus curieux de savoir comment une courbe d'hilbert se déclenche pour le tri des couleurs, voir (en particulier la section intitulée "Hilbert Sorting") http://www.alanzucconi.com/2015/09/30/tri des couleurs / – Zimm3r

7

Si vous souhaitez trier une liste de couleurs dans une dimension vous devez d'abord décider ce que vous allez Metrics les trier. Le plus de sens pour moi est la luminosité perçue (related question).

J'ai rencontré 4 algorithmes pour trier les couleurs par luminosité et les comparer. Voici le résultat.

J'ai généré des couleurs en cycle où seulement environ toutes les 400e couleurs étaient utilisées. Chaque couleur est représentée par 2x2 pixels, les couleurs sont triées du plus foncé au plus clair (de gauche à droite, de haut en bas).

1ère photo - Luminance (relative)

0.2126 * R + 0.7152 * G + 0.0722 * B 

2ème photo - http://www.w3.org/TR/AERT#color-contrast

0.299 * R + 0.587 * G + 0.114 * B 

3ème photo - HSP Color Model

sqrt(0.299 * R^2 + 0.587 * G^2 + 0.114 * B^2) 

image 4TD - WCAG 2.0 SC 1.4.3relative luminance et contrast ratio formule

Le motif peut parfois être repéré sur les première et deuxième images en fonction du nombre de couleurs d'une rangée. Je n'ai jamais repéré aucun motif sur l'image du 3ème ou 4ème algorithme.

Si je devais choisir, j'aller avec le numéro de l'algorithme 3 depuis son beaucoup plus facile à mettre en œuvre et son environ 33% plus rapide que le 4

Perceived brightness algorithm comparison

Questions connexes