Suivi: "Tri" des couleurs par caractère distinctif

Question d'origine

Si vous obtenez N couleurs éloignées au maximum (et une métrique de distance associée), pouvez-vous trouver un moyen de trier ces couleurs dans un ordre tel que les premiers M sont aussi raisonnablement proches d'être un ensemble distinct au maximum?

En d'autres termes, étant donné un tas de couleurs distinctes, arriver à une commande afin que je puisse utiliser autant de couleurs que j'ai besoin de commencer au début et être raisonnablement assuré qu'ils sont tous distincts et que les couleurs voisines sont également très distinctes (p. le rouge bleuté n'est pas à côté du bleu rougeâtre).

Randomiser est OK mais certainement pas optimal.

Clarification: Étant donné un grand ensemble de couleurs visuellement distinctes (disons 256, ou 1024), je veux les trier de telle sorte que lorsque j'utilise le premier, disons 16 d'entre elles, je reçois un sous-ensemble de couleurs relativement distinct . Cela équivaut, grosso modo, à dire que je veux trier cette liste de 1024 de sorte que plus les couleurs individuelles sont proches visuellement, plus elles sont éloignées de la liste.

0

9 Réponses

Vous pouvez les diviser en format RGB HEX afin que vous puissiez comparer le R avec R d'une couleur différente, même avec le G et B.

Même format que HTML

XX XX XX
RR GG BB

00 00 00 = black
ff ff ff = white
ff 00 00 = red
00 ff 00 = green
00 00 ff = blue

Donc, la seule chose que vous devez décider est de savoir à quelle distance vous voulez les couleurs et quelle est la différence acceptable pour que les segments soient considérés comme différents.

0
ajouté

Il semble que la perception soit importante pour vous, dans ce cas, vous pouvez envisager de travailler avec un espace de couleurs perceptuel tel que YUV, YCbCr ou Lab. Chaque fois que j'ai utilisé ceux-ci, ils m'ont donné de bien meilleurs résultats que sRGB seul.

La conversion vers et depuis sRGB peut être pénible, mais dans votre cas, cela pourrait rendre l'algorithme plus simple et, en prime, cela fonctionnera aussi pour les stores couleur!

0
ajouté

Do you mean that from a set of N colors, you need to pick M colors, where M < N, such that M is the best representation of the N colors in the M space?

Comme meilleur exemple, réduisez une couleur vraie (espace colorimétrique de 24 bits) à un espace colorimétrique mappé de 8 bits (GIF?).

Il existe pour cela des algorithmes de quantification, comme l'algorithme Adaptive Spatial Subdivision utilisé par ImageMagic.

En général, ces algorithmes ne sélectionnent pas uniquement les couleurs existantes dans l'espace source mais créent de nouvelles couleurs dans l'espace cible qui ressemblent le plus aux couleurs source. Comme exemple simplifié, si vous avez 3 couleurs dans l'image originale où deux sont rouges (avec des intensités différentes ou des teintes bleuâtres etc.) et la troisième est bleue, et doivent être réduites à deux couleurs, l'image cible pourrait avoir une couleur rouge c'est une sorte de moyenne des deux originaux rouges + la couleur bleue de l'image originale.

Si vous avez besoin d'autre chose, je n'ai pas compris votre question :)

0
ajouté

Cela me semble aussi comme un graphique de résistance où vous essayez de tracer le chemin de moindre résistance. Si vous inversez les exigences, chemin de la résistance maximale, il pourrait peut-être être utilisé pour produire un ensemble qui, dès le départ, produit la différence maximale au fur et à mesure, et vers la fin commence à revenir aux valeurs plus proches des autres.

Par exemple, voici une façon de faire ce que vous voulez.

  1. Calculate the distance (ref your other post) from each color to all other colors
  2. Sum the distances for each color, this gives you an indication for how far away this color is from all other colors in total
  3. Order the list by distance, going down

Cela produirait, semble-t-il, une liste qui commence par la couleur la plus éloignée de toutes les autres couleurs, puis descend, les couleurs vers la fin de la liste seraient plus proches des autres couleurs en général.

Edit: Lire votre réponse à mon premier post, sur la subdivision spatiale, ne correspondrait pas exactement à la description ci-dessus, car les couleurs proches des autres couleurs tomberaient au bas de la liste, mais disons que vous avez un groupe de couleurs quelque part, à au moins une des couleurs de ce groupe serait située près du début de la liste, et ce serait celle qui était généralement la plus éloignée de toutes les autres couleurs au total. Si ça a du sens.

0
ajouté

Vous pouvez simplement trier les couleurs candidates en fonction de la distance maximale de la distance minimale à l'une des couleurs d'index.

Utilisation de la distance de couleur euclidienne:

public double colordistance(Color color0, Color color1) {
    int c0 = color0.getRGB();
    int c1 = color1.getRGB();
    return distance(((c0>>16)&0xFF), ((c0>>8)&0xFF), (c0&0xFF), ((c1>>16)&0xFF), ((c1>>8)&0xFF), (c1&0xFF));
}

public double distance(int r1, int g1, int b1, int r2, int g2, int b2) {
    int dr = (r1 - r2);
    int dg = (g1 - g2);
    int db = (b1 - b2);
    return Math.sqrt(dr * dr + dg * dg + db * db);
}

Bien que vous pouvez le remplacer par tout ce que vous voulez. Il a juste besoin d'une routine de distance de couleur.

public void colordistancesort(Color[] candidateColors, Color[] indexColors) {
    double current;

    double distance[] = new double[candidateColors.length];
    for (int j = 0; j < candidateColors.length; j++) {
        distance[j] = -1;
        for (int k = 0; k < indexColors.length; k++) {
            current = colordistance(indexColors[k], candidateColors[j]);
            if ((distance[j] == -1) || (current < distance[j])) {
                distance[j] = current;
            }
        }
    }

    //just sorts.
    for (int j = 0; j < candidateColors.length; j++) {
        for (int k = j + 1; k < candidateColors.length; k++) {
            if (distance[j] > distance[k]) {
                double d = distance[k];
                distance[k] = distance[j];
                distance[j] = d;

                Color m = candidateColors[k];
                candidateColors[k] = candidateColors[j];
                candidateColors[j] = m;
            }
        }
    }
}
0
ajouté
Bien que, vraiment, cela pourrait sélectionner deux couleurs très semblables à partir des candidatsColors. Vous voudrez peut-être simplement trouver le meilleur candidat, l'ajouter aux couleurs de l'index et recommencer à zéro.
ajouté l'auteur Tatarize, source

Si je comprends bien la question, vous souhaitez obtenir le sous-ensemble des couleurs M avec la distance moyenne la plus élevée entre les couleurs, étant donné la fonction de distance d .

Autrement dit, en considérant l'ensemble initial de couleurs N comme un grand graphe non orienté dans lequel toutes les couleurs sont connectées, vous voulez trouver le chemin le plus long qui visite n'importe quel > M nœuds.

La résolution des problèmes de graphes NP-complets est bien au-delà de mes capacités, j'en ai bien peur, mais vous pourriez essayer d'exécuter une simple simulation physique:

  1. Generate M random points in colour space
  2. Calculate the distance between each point
  3. Calculate repulsion vectors for each point that will move it away from all other points (using 1 / (distance ^ 2) as the magnitude of the vector)
  4. Sum the repulsion vectors for each point
  5. Update the position of each point according to the summed repulsion vectors
  6. Constrain any out of bound coordinates (such as luminosity going negative or above one)
  7. Repeat from step 2 until the points stabilise
  8. For each point, select the nearest colour from the original set of N

C'est loin d'être efficace, mais pour un petit M , il peut être assez efficace et donner des résultats presque optimaux.

Si votre fonction de distance de couleur est simple, il peut y avoir une façon plus déterministe de générer le sous-ensemble optimal.

0
ajouté
Ce n'est pas NP-complet. C'est soit le tri O (NLog (N)) par le maximum de la distance minimale à toutes les couleurs d'indice O (N) ou par la moyenne O (N). C'est clairement O (N + NLog (N)) ou O (NLog (N)). Dans le pire des cas, vous devez ajouter les couleurs triées aux couleurs de l'index, ce qui en fait N²Log (N). Trouvez le meilleur, ajoutez-le à la liste des couleurs d'index. Recommencer.
ajouté l'auteur Tatarize, source

Ce problème est appelé quantification de couleur et possède de nombreux algorithmes bien connus: http://en.wikipedia.org/ wiki / Color_quantization Je connais des personnes qui ont mis en œuvre l'approche octree à bon escient.

0
ajouté

N couleurs éloignées au maximum peuvent être considérées comme un ensemble de points bien répartis dans un espace tridimensionnel (couleur). Si vous pouvez les générer à partir d'une séquence Halton , alors n'importe quel préfixe (les premières M couleurs) aussi consiste en des points bien répartis.

0
ajouté
  1. Commencez avec deux listes. CandidateColors, qui contient initialement vos couleurs distinctes et SortedColors, qui est initialement vide.
  2. Choisissez n'importe quelle couleur et supprimez-la de CandidateColors et placez-la dans SortedColors. C'est la première couleur et elle sera la plus courante, donc c'est un bon endroit pour choisir une couleur qui colle bien avec votre application.
  3. Pour chaque couleur dans CandidateColors, calculez sa distance totale. La distance totale est la somme de la distance entre CandidateColor et chacune des couleurs de SortedColors.
  4. Supprimez la couleur ayant la plus grande distance totale de CandidateColors et ajoutez-la à la fin de SortedColors.
  5. Si CandidateColors n'est pas vide, retournez à l'étape 3.

Cet algorithme glouton devrait vous donner de bons résultats.

0
ajouté