“Arrondir” les valeurs de couleurs pour le plus proche, dans un petit ensemble de couleurs
Préambule
Comme une partie d'un projet sur lequel je travaille, je suis en train d'essayer de fournir un moyen pratique pour la recherche d'images dans notre système. Nous fournissons actuellement à la recherche par différents types d'utilisateurs ajout de métadonnées (titre, description, mots-clés) et par diverses métadonnées qui nous extraire (par exemple, EXIF, IPTC, XMP, etc). Je tiens aussi à ajouter une "recherche sur la couleur" semblable à ce que vous pouvez voir dans google recherche d'images.
Le projet utilise PHP et nous pouvons utiliser Imagemagick extension de segment et de quantification de l'image et d'en extraire les plus importants"," les couleurs de l'image; je ne suis pas certain de pouvoir les résultats que j'obtiens ici, mais ils semblent raisonnablement précis et certainement mieux que rien.
Le Problème
Le peu que j'ai de la difficulté à convertir ces couleurs importantes dans un jeu de couleurs représentant, par exemple, lorsque vous regardez Google recherche d'images il existe un ensemble de 12 couleurs là. J'aimerais mathématiquement rond "" mon la valeur de la couleur la plus proche représentant de la couleur, de sorte que je peux l'indice de l'image avec les couleurs que je détecte, puis facette de mes résultats de recherche de cette façon.
Des suggestions?
- Vous êtes à la recherche pour le tour de ces 12 couleurs dans la recherche d'images Google, ou était-ce juste un exemple de la couleur de l'arrondissement? Dans ce dernier cas, combien de couleurs souhaitez-vous idéalement comme à la fin avec l'?
- Ces 12 serait bien, mais je ne suis pas fixé sur eux. Je pense qu'une approche appropriée devrait fonctionner quelles que soient les valeurs que je suis arrondi, donc je ne pense pas que les valeurs réelles sont importantes.
Vous devez vous connecter pour publier un commentaire.
La première étape serait de définir les couleurs que vous souhaitez comparer.
La deuxième étape est de trouver la plus petite distance à partir de votre couleur à l'une des couleurs que vous avez choisi à l'étape précédente. Afin de pouvoir mesurer cette distance, vous avez besoin d'un espace Euclidien dans lequel le modèle de couleurs.
Naturellement, le simple choix serait l'espace RVB
Et la distance entre deux couleurs C1(r1, g1, b1) et C2(r2, g2, b2) serait
sqrt( (r1 - r2)2 + (g1 - g2)2 + b1 - b2)2 ).
Mais si vous avez besoin de plus de précision, il serait préférable d'utiliser la Teinte-Chroma-Légèreté bicone de l'espace, un dérivé de la LGV cylindre.
Dans l'espace RVB, les choses étaient simples de R, G et B, où chacun sur un axe distinct. Dans HCL, nous avons besoin de calculer les coordonnées sur chacun des axes.
Tout d'abord, nous calculons le chroma (qui est un peu différent de la saturation) comme:
Chroma = max(Rouge, Vert, Bleu) - min(Rouge, Vert, Bleu)
Puis nous normaliser notre H, C et L de la valeur, de sorte que H va de 0 à 2 (pour couvrir un cercle si nous multiplions par PI et de prendre le radian comme unité), C va de 0 à 1 (le rayon du cercle trigonométrique) et L va de -1 (Noir) à 1 (Blanc).
Prochaine que nous prenons z = L sans transformation, comme il est clair à partir de l'image qu'il va le long de l'axe vertical.
On peut facilement observer que, pour une couleur, Chroma est la distance de l'axe z et la Teinte correspond à l'angle. Nous obtenons donc
x = C * cos(H*PI) et
y = C * sin(H*PI)
À ce point x, y et z seront tous dans [-1, 1] et la distance entre deux couleurs seront, à l'aide de la même formule que ci-dessus,
sqrt( (x1 - x2)2 + (y1 - o2)2 + (z1 - z2)2 ).
Pour obtenir encore plus de précision et de trouver la couleur la plus proche selon la perception humaine de la couleur, vous pouvez utiliser les CIE-L*ab la modélisation de l'espace et de calculer la distance avec l'un de ces algorithmes. Les principes sont les mêmes que pour les deux cas présentés ci-dessus, seuls les algorithmes sont plus complexes.
Mise à jour (7 ans plus tard)
Enfin xkcd en vedette une bande dessinée que je peux utiliser dans ce post!
https://xkcd.com/1882/
C'est une bonne idée seulement vous en aurez besoin pour l'adapter à vos propres besoins.
En gros, j'ai pensé que, comme les couleurs sont comptabilisés à titre de RVB, soit comme une chaîne Hexadécimale "#000000" à "#ffffff", ou comme un RVB ensemble "rgb(0,0,0)" à "rgb(255,255,255)", et ceux-ci sont interchangeables/translateable, c'est un simple mathématique de l'arrondissement problème de.
Dans la gamme complète de couleurs, il serait (16*16)*(16*16)*(16*16) = 256*256*256 = 16,777,216 couleurs possibles.
Arrondi couleurs à leurs plus simple caractère Hex valeur qui réduit à 16*16*16 = de 4 096 couleurs possibles. Encore beaucoup trop, mais se rapproche.
L'arrondissement de couleurs pour une seule valeur de caractère, mais alors la limitation de, que de continuer à être l'un des 4 (0,3,7,f) le réduit à 4*4*4 = 32. Assez proche pour moi.
Donc, j'ai construit un très de base de la fonction PHP pour essayer et obtenir ceci:
Cette fonction, lorsqu'il est passé d'une chaîne hexadécimale, echos d'un échantillon de la couleur d'origine et un exemple de la version abrégée de la couleur.
C'est une simple preuve de concept, que je ne connais pas le format Imagemagick est de retour les couleurs, mais vous pouvez être en mesure d'utiliser cette logique de créer votre propre.
De ces 32 couleurs ensuite, vous pouvez regrouper les mêmes (il n'y aurait probablement environ 8 nuances de gris là) nom et le reste pour permettre à vos utilisateurs de faire des recherches par eux.
En fonction du nombre de couleurs que vous cherchez, pourquoi ne pas essayer d'utiliser les opérateurs sur les bits (PHP référence ici, puisque vous avez mentionné dans la question) afin de réduire le nombre de chiffres significatifs? Vous pourriez tour les valeurs RVB, avant de passer à l'augmentation de la précision.