
[αρχική ερώτηση](https://stackoverflow.com/questions/180/function-for-creating-color-wheels)


Αν σας δοθεί Ν μέγιστη μακρινή χρώματα (και μερικά που σχετίζονται απόσταση μετρικό), μπορείτε να καταλήξει σε ένα τρόπο για να λύσουμε αυτά τα χρώματα σε κάποια τάξη, έτσι ώστε η πρώτη M είναι επίσης αρκετά κοντά για να είναι ένα μέγιστο ξεχωριστή σειρά;


Με άλλα λόγια, δίνεται μια δέσμη των διαφορετικών χρωμάτων, έρχονται με μια παραγγελία ώστε να μπορώ να χρησιμοποιήσετε όσα χρώματα όπως έχω ανάγκη ξεκινούν από την αρχή και είναι λογικό να είστε σίγουροι ότι όλα είναι διακριτές και ότι γύρω από το ξενοδοχείο χρώματα είναι επίσης πολύ διακριτές (π.χ., μπλε κόκκινο δεν είναι δίπλα στο κοκκινωπό μπλε).


Τυχαιοποίηση είναι εντάξει, αλλά σίγουρα δεν είναι η βέλτιστη.


*Διευκρίνιση: Λόγω κάποια μεγάλα και οπτικά διακριτό σύνολο χρωμάτων (δηλαδή 256 ή 1024), θα ήθελα να τους ταξινομήσετε ούτως ώστε όταν χρησιμοποιώ το πρώτο, ας πούμε, 16 από αυτά που παίρνω μια σχετικά οπτικά διακριτό υποσύνολο των χρωμάτων. Αυτό είναι ισοδύναμο, κατά προσέγγιση, για να πω θέλω να ταξινομήσετε αυτή τη λίστα των 1024 έτσι ώστε οι πιο μεμονωμένα χρώματα είναι οπτικά, η μεγαλύτερη απόσταση μεταξύ τους που βρίσκονται στη λίστα.*

 
Follow-up: «Ταξινόμηση» χρώματα με διακριτικό
=============================================



Εννοείτε ότι από ένα σύνολο Ν χρώματα, θα πρέπει να επιλέξετε Μ χρώματα, όπου M <N, έτσι ώστε το Μ είναι η *καλύτερη* αναπαράσταση των χρωμάτων Ν στον χώρο M;


Ως καλύτερο παράδειγμα, να μειώσει το πραγματικό χρώμα (χρωματικό χώρο 24 bit) σε ένα 8-bit αντιστοιχίζονται χρωματικό χώρο (GIF;).


Υπάρχουν αλγόριθμοι κβαντοποίησης γι 'αυτό, όπως το [Adaptive Χωρική Υποδιεύθυνση](http://www.imagemagick.org/www/quantize.html) αλγόριθμος που χρησιμοποιείται από ImageMagic.


Οι αλγόριθμοι αυτοί συνήθως δεν πάρει μόνο τα υπάρχοντα χρώματα από το χώρο προέλευσης, αλλά δημιουργεί νέα χρώματα στο χώρο στόχο που μοιάζουν περισσότερο με τα χρώματα πηγή. Ως ένα απλοποιημένο παράδειγμα, εάν έχετε 3 χρώματα στην αρχική εικόνα όπου δύο είναι κόκκινα (με διαφορετική ένταση ή μπλε αποχρώσεις, κλπ) και η τρίτη είναι μπλε, και πρέπει να μειωθεί σε δύο χρώματα, η εικόνα στόχος θα μπορούσε να έχει κόκκινο χρώμα ότι είναι κάποιο είδος του μέσου όρου των δύο αρχικών κόκκινο + μπλε χρώμα από την αρχική εικόνα.


Αν χρειάζεστε κάτι άλλο τότε δεν κατάλαβα την ερώτησή σας :)

 

Μπορείτε να χωρίζεται σε μορφή RGB HEX, έτσι ώστε να μπορείτε να συγκρίνετε το R με το R είναι ένα διαφορετικό χρώμα, ίδιο με το G και B.


Ίδια μορφή 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

```

Έτσι, το μόνο πράγμα που θα πρέπει να αποφασίσετε είναι πόσο κοντά θέλετε τα χρώματα και τι είναι μια αποδεκτή διαφορά για τα τμήματα που πρέπει να θεωρούνται διαφορετικές.

 

Αυτό ακούγεται επίσης για μένα σαν ένα είδος *γράφημα αντίστασης* όπου θα προσπαθήσει να χαράξει το δρόμο της μικρότερης αντίστασης. Αν αντιστρέψετε τις απαιτήσεις, τη διαδρομή της μέγιστης αντίστασης, θα μπορούσε ίσως να χρησιμοποιηθεί για την παραγωγή ενός συνόλου που από την αρχή παράγει μέγιστη διαφορά as you go, και προς το τέλος αρχίζει να επιστρέψω σε τιμές πιο κοντά στους άλλους.


Για παράδειγμα, εδώ είναι ένας τρόπος για να ίσως κάνει ό, τι θέλετε.


1. Υπολογίστε την απόσταση (ref [άλλη θέση σας](https://stackoverflow.com/questions/1313/followup-finding-an-accurate-distance-between-colors) ) από το κάθε χρώμα σε όλα τα άλλα χρώματα
2. Συνοψίζοντας τις αποστάσεις για κάθε χρώμα, αυτό σας δίνει μια ένδειξη για *το πόσο μακριά είναι αυτό το χρώμα είναι από όλα τα άλλα χρώματα στο σύνολο*
3. Παραγγείλετε τον κατάλογο απόσταση, κατεβαίνοντας


Αυτό, φαίνεται, να παράγει μια λίστα που ξεκινά με το χρώμα που είναι το πλέον απομακρυσμένο μακριά από όλα τα άλλα χρώματα, και στη συνέχεια να πάει κάτω, τα χρώματα προς το τέλος της λίστας θα είναι πιο κοντά σε άλλα χρώματα σε γενικές γραμμές.


Επεξεργασία: Διαβάζοντας την απάντησή σας στην πρώτη θέση μου, για τη χωρική υποδιαίρεση, δεν θα ταιριάζει ακριβώς την παραπάνω περιγραφή, δεδομένου ότι τα χρώματα κοντά σε άλλα χρώματα θα πέσει στο κάτω μέρος της λίστας, αλλά ας πούμε ότι έχετε ένα σύμπλεγμα χρωμάτων κάπου, σε τουλάχιστον ένα από τα χρώματα από αυτό το σύμπλεγμα θα βρίσκεται κοντά στην αρχή της λίστας, και θα ήταν αυτός που σε γενικές γραμμές ήταν πιο μακρινή απόσταση από όλα τα άλλα χρώματα συνολικά. Αν αυτό έχει νόημα.

 

Το πρόβλημα αυτό ονομάζεται χρώμα κβαντοποίηση, και έχει πολλά καλά γνωστοί αλγόριθμοι: <http://en.wikipedia.org/wiki/Color_quantization> Ξέρω ανθρώπους που εφάρμοσαν την προσέγγιση Octree για καλό αποτέλεσμα.

 

Φαίνεται ότι η αντίληψη είναι σημαντικό για εσάς, στην περίπτωση αυτή ίσως να θέλετε να εξετάσει το ενδεχόμενο συνεργασίας με την αντιληπτική χρωματικό χώρο, όπως YUV, YCbCr ή Lab. Κάθε φορά που έχω χρησιμοποιήσει εκείνους, που μου έδωσαν πολύ καλύτερα αποτελέσματα από ό, τι sRGB και μόνο.


Μετατροπή από και προς το sRGB μπορεί να είναι ένας πόνος, αλλά στην περίπτωσή σας θα μπορούσε πραγματικά να κάνει ο αλγόριθμος απλούστερη και ως μπόνους θα λειτουργήσει ως επί το πλείστον για το χρώμα τυφλοί πάρα πολύ!

 

Ν μέγιστη μακρινή χρώματα μπορεί να θεωρηθεί ένα σύνολο καλά κατανεμημένα σημεία σε ένα 3-διαστάσεων (χρώμα) χώρο. Αν μπορείτε να τα δημιουργήσετε από μία [ακολουθία Halton](http://en.wikipedia.org/wiki/Halton_sequence) , τότε κάθε πρόθεμα (τα πρώτα χρώματα M) αποτελείται επίσης από καλά κατανεμημένα σημεία.

 

Αν είμαι κατανόηση σωστά στην ερώτηση, επιθυμείτε να αποκτήσετε το υποσύνολο *Μ* χρώματα με την **υψηλότερη μέση απόσταση** μεταξύ των χρωμάτων, δίνεται κάποια συνάρτηση απόστασης *d* .


Με άλλα λόγια, λαμβάνοντας υπόψη το αρχικό σύνολο *Ν* χρωμάτων ως ένα μεγάλο, μη-κατευθυνόμενο γράφημα στο οποίο συνδέονται όλα τα χρώματα, θέλετε να βρείτε τη **μεγαλύτερη διαδρομή** που επισκέπτεται κάθε *Μ* κόμβους.


Επίλυση NP-πλήρη προβλήματα γράφημα είναι ο τρόπος πέρα ​​από μένα φοβάμαι, αλλά θα μπορούσατε να δοκιμάσετε τη λειτουργία μια απλή φυσική προσομοίωση:


1. Δημιουργία *Μ* τυχαία σημεία στο χρωματικό χώρο
2. Υπολογίστε την απόσταση ανάμεσα σε κάθε σημείο
3. Υπολογίστε διανύσματα απώθηση για κάθε σημείο που θα μετακινηθεί μακριά από όλα τα άλλα σημεία (με χρήση 1 / ( *απόσταση* ^ 2) ως το μέγεθος του διανύσματος)
4. Συνοψίζοντας τα διανύσματα απέχθεια για κάθε σημείο
5. Την ενημέρωση της θέσης κάθε σημείου σύμφωνα με τις αθροίζονται διανύσματα άπωση
6. Περιορισμός οποιαδήποτε από δεσμευμένου συντεταγμένων (όπως φωτεινότητα πρόκειται αρνητική ή πάνω από το ένα)
7. Επαναλάβετε από το βήμα 2 μέχρι τα σημεία σταθεροποιηθούν
8. Για κάθε σημείο, επιλέξτε το πλησιέστερο χρώμα από το αρχικό σύνολο *Ν*


Είναι μακριά από αποτελεσματική, αλλά για τις μικρές *Μ* μπορεί να είναι αρκετά αποτελεσματική, και θα δώσει σχεδόν τα βέλτιστα αποτελέσματα.


Εάν συνάρτηση απόστασης χρώμα σας είναι απλή, μπορεί να υπάρξει μια περισσότερο ντετερμινιστικό τρόπο παραγωγής του βέλτιστου υποσύνολο.

 

1. Ξεκινήστε με δύο λίστες. CandidateColors, η οποία αρχικά περιέχει διαφορετικά χρώματα και SortedColors σας, το οποίο είναι αρχικά κενή.
2. Διαλέξτε οποιοδήποτε χρώμα και αφαιρέστε το από CandidateColors και το βάζουμε σε SortedColors. Αυτό είναι το πρώτο χρώμα και θα είναι η πιο κοινή, γι 'αυτό είναι ένα καλό μέρος για να πάρει ένα χρώμα που jives καλά με την αίτησή σας.
3. Για κάθε χρώμα στο CandidateColors υπολογιστεί η συνολική απόσταση της. Η συνολική απόσταση είναι το άθροισμα της απόστασης από το CandidateColor σε κάθε ένα από τα χρώματα στο SortedColors.
4. Αφαιρέστε το χρώμα με τη μεγαλύτερη συνολική απόσταση από CandidateColors και προσθέστε το στο τέλος του SortedColors.
5. Αν CandidateColors δεν είναι κενή, επιστρέψτε στο βήμα 3.


Αυτό άπληστος αλγόριθμος θα πρέπει να σας δώσει καλά αποτελέσματα.

 

Θα μπορούσατε να ταξινομήσετε ακριβώς τις υποψήφιες χρώματα με βάση το μέγιστο-αποστασιοποιημένη της ελάχιστης απόστασης σε κάποιο από τα χρώματα του δείκτη.


Χρησιμοποιώντας Ευκλείδεια απόσταση χρώμα:



```
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);
}

```

Αν και μπορείτε να το αντικαταστήσετε με ό, τι θέλετε. Το μόνο που χρειάζεται είναι μια ρουτίνα απόσταση χρώμα.



```
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;
            }
        }
    }
}

```
 