Je crée une démo de 20 balles qui rebondissent, avec un fond rempli de couleur unie. La couleur de chaque balle est choisie au hasard avec randint(0, 255)
pour chaque composant de tuple R, G, B.
Le problème est que certaines boules se retrouvent avec une couleur très similaire à l'arrière-plan, ce qui les rend difficiles à voir. Je voudrais éviter cela, soit en roulant une autre couleur si celle choisie est trop similaire (dans un seuil donné), soit en l'éloignant de la couleur de fond.
Comment calculer un indice de similitude à utiliser comme seuil? Ou comment transformer une couleur pour la rendre, disons, moins bleuâtre ?
Clause de non-responsabilité évidente: Je ne connais rien à la théorie des couleurs, donc je ne sais pas si les concepts ci-dessus existent même!
Je code en python, mais je recherche des concepts et des stratégies, donc le pseudo-code est bien (ou tout simplement la théorie).
MODIFIER:
Pour clarifier quelques points:
Chaque balle a sa propre couleur aléatoire. J'aimerais qu'ils restent aussi aléatoires que possible et explorent autant que possible l'espace colorimétrique (que ce soit RVB ou HSV,
pygame
accepte les deux formats pour définir la couleur)Je voudrais juste éviter que chaque couleur soit "trop proche" du fond. Le problème ne concerne pas seulement la teinte: je vais parfaitement bien avec une boule bleu clair sur un fond bleu foncé (ou un "plein bleu" contre un bleu "blanc", etc.)
Pour l'instant, peu m'importe si une balle se retrouve avec une couleur similaire (ou même identique) à une autre balle. Éviter cela est un bonus, mais c'est un problème mineur.
La couleur d'arrière-plan est une couleur RVB unique et constante. Pour l'instant, j'utilise du bleu "basique"
(0, 0, 255)
, mais je ne suis pas d'accord avec ça. Considérez donc l'arrière-plan comme étant d'une couleur arbitraire (avec une teinte arbitraire, une luminosité, une saturation, etc.).
EDIT2:
TL, version DR: donnez simplement un moyen de créer X couleurs aléatoires de sorte qu'aucune "ne se fane trop" sur un fond de couleur arbitraire (mais unique et constant)
Réponses:
Vous pouvez utiliser le fait que les couleurs constituent un espace colorimétrique (en trois dimensions) et calculer une distance dans cet espace colorimétrique. Vous devez ensuite définir une métrique dans cet espace colorimétrique pour trouver la distance entre deux couleurs.
Par exemple, la distance dans un espace euclidien entre deux points x = (x1, x2, x3) et y = (y1, y2, y3) est donnée par d (x, y) = sqrt ((y1-x1) * (y1- x1) + (y2-x2) * (y2-x2) + (y3-x3) * (y3-x3)).
Vous pouvez maintenant calculer la distance entre une couleur de boules et votre couleur d'arrière-plan et si elle est trop petite, créez une nouvelle couleur aléatoire et testez à nouveau.
Vous constaterez que ni RVB ni même HSV ne sont de bons espaces colorimétriques pour cette tâche. L' article de wikipedia sur la différence de couleur utilise l' espace colorimétrique L a b et donne plusieurs métriques possibles.
Il y a aussi une discussion sur stackoverflow sur le sujet.
la source
La page des normes d'accessibilité Web des Nations Unies ( http://www.un.org/webaccessibility/1_visual/13_colourcontrast.shtml ) indique une norme pour assurer un contraste de texte correct sur les sites Web, en gardant à l'esprit que certains utilisateurs sont daltoniens. Cela peut être particulièrement important pour vous car certains de vos utilisateurs peuvent également être daltoniens (il serait difficile de distinguer une boule rouge d'un fond vert s'ils ont la même luminance).
La page UN pointe vers l'analyseur de rapport de contraste de couleur de luminosité Juicy Studios sur ( http://juicystudio.com/services/luminositycontrastratio.php#specify ) qui indique que le texte en arrière-plan doit avoir un rapport de contraste de 4,5: 1, sauf pour ce que je pensez être similaire à votre cas:
Maintenant, qu'est-ce qu'un rapport de contraste? Suite aux hyperliens (c'est amusant!), Nous arrivons à une page W3 qui définit le rapport de contraste comme:
Où L1 et L2 sont les luminances relatives des couleurs. L1 est la couleur la plus lumineuse, L2 est la couleur la moins lumineuse. Encore une fois, nous suivons le lien vers la même page W3 qui spécifie:
REMARQUE : le symbole caret ^ ci-dessus fait référence à l'exponentiation (x²)
Et nous avons un assez bon cadre pour un algorithme de contraste (qui est compatible avec les daltoniens!)
la source
^
, je ne penserais jamais à un XOR au niveau du bit dans ce contexte. (ou dans n'importe quel fait. C'mon C phreaks,^
est le simbol de facto pour l'exponentiation dans les pseudo-codes (bien que très peu de langues l'utilisent réellement ... en python c'est**
)L'utilisation de valeurs RVB en générant une
0-255
valeur aléatoire pour chaque composant peut non seulement créer des couleurs similaires à l'arrière-plan, mais vous pouvez également vous retrouver avec des couleurs très similaires pour les balles.Je choisirais probablement une approche moins aléatoire et créerais des couleurs qui sont garanties à la place. Vous pouvez créer une couleur pour chaque ~ 32 degrés dans la gamme de teintes et alterner la luminosité ou la saturation (utilisez le modèle de couleur HSV au lieu de RVB).
Donc quelque chose comme ça:
ce qui créera 20 couleurs, bien réparties. Cela suppose que vous utilisez des mathématiques entières
i = 0
eti = 1
créera donc la même valeur de teinte.Bien sûr, cela ne se met pas à l'échelle trop bien .. si vous avez 100 valeurs de couleur à créer, l'espacement des teintes pourrait ne pas être suffisant et vous vous retrouverez avec des couleurs similaires. Dans ce cas, vous pouvez également faire varier la
V
valeur (luminosité).Je ne sais pas à quoi ressemble votre couleur d'arrière-plan, mais HSV facilite également la comparaison des couleurs (comparez simplement les 3 composants et n'oubliez pas que HUE est circulaire (0 == 360)).
MISE À JOUR:
Comme je n'ai pas vraiment répondu à votre question, mais plutôt fourni une autre approche, voici à quoi pourrait ressembler un algorithme pour un arrière-plan arbitraire et des boules de couleur complètement aléatoires (il s'agit d'une approche par force brute mais devrait fonctionner correctement pour votre cas d'utilisation):
la source
V
(car l'algorithme actuel ne change pas cela).Puisque vous avez mentionné que vous aviez un arrière-plan fixe, la couleur des boules peut toujours être aléatoire, mais elles doivent tomber à certaines plages qui complimentent encore l'arrière-plan.
Les bases. Avant de faire cela, vous devez connaître les bases. Considérez les couleurs suivantes:
Mélange de couleurs RVB [(0..255), (0..255), (0..255)] crée de nouvelles couleurs comme ci-dessus.
Calcul des couleurs négatives Le calcul des couleurs négatives revient à transformer le rouge en cyan, le vert en violet, le bleu en jaune.
Couleur complémentaire
Selon la référence sur l'informatique des couleurs complémentaires: http://serennu.com/colour/rgbtohsl.php
À propos de HSL
HSL exprime les couleurs en termes de teinte, de saturation et de luminosité, en donnant un nombre pour chacun de ces trois attributs de la couleur.
La teinte est la position de la couleur sur la roue chromatique, exprimée en degrés de 0 ° à 359 °, représentant les 360 ° de la roue; 0 ° étant rouge, 180 ° étant la couleur opposée du rouge cyan, et ainsi de suite.
La saturation est l'intensité de la couleur, à quel point elle est terne ou lumineuse. Plus la saturation est faible, plus la couleur est terne (plus grise). Ceci est exprimé en pourcentage, 100% étant la pleine saturation, le plus brillant et 0% étant sans saturation, le gris.
La légèreté est la luminosité de la couleur. Légèrement différent de la saturation. Plus la couleur est blanche, plus sa valeur de luminosité est élevée, plus elle est noire, plus sa luminosité est faible. Ainsi, 100% de légèreté transforme la couleur en blanc, 0% de légèreté transforme la couleur en noir et la couleur "pure" serait de 50% de légèreté.
Il est plus facile de voir la différence entre la saturation et la légèreté que de l'expliquer. Si vous souhaitez clarifier, essayez d'afficher les variations de luminosité et de saturation sur la page du calculateur de couleurs, en choisissant une couleur assez brillante comme couleur de départ.
Ainsi, la notation HSL ressemble à ceci, donnant les valeurs de teinte, de saturation et de luminosité dans cet ordre: t
Rouge: 0 ° 100% 50% Rose pâle: 0 ° 100% 90% Cyan: 180 ° 100% 50% Voici les étapes:
Convertissez votre couleur en HSL.
Modifiez la valeur de la teinte à celle de la teinte opposée (par exemple, si votre teinte est de 50 °, l'opposé sera à 230 ° sur la roue - 180 ° plus loin).
Laissez les valeurs de saturation et de luminosité telles qu'elles étaient.
Convertissez cette nouvelle valeur HSL à votre notation de couleur d'origine (RVB ou autre).
Des sites comme EasyRGB.com peuvent effectuer pour vous une conversion générique de RVB à HSL ou vice versa.
Exemple de programmation fait en PHP selon la référence
Conversion de RVB à HSL
La valeur supérieure à Blue # 0000FF rgb (0,0,255) peut être présentée comme Red Hexadecimal 00 + Green Hexadecimal 00 + Blue Hexadecimal FF
Il peut également être présenté en rouge décimal 0 + vert décimal 0 + bleu décimal 255
Maintenant, branchez ces valeurs dans la routine rgb2hsl. Voici ma version PHP du code générique d'EasyRGB.com pour cette conversion:
L'entrée est $ var_r, $ var_g et $ var_b d'en haut La sortie est HSL équivalente à $ h, $ s et $ l - ceux-ci sont à nouveau exprimés en fractions de 1, comme les valeurs d'entrée
Alors maintenant, nous avons la couleur comme valeur HSL, dans les variables $ h, $ s et $ l. Ces trois variables de sortie sont à nouveau considérées comme des fractions de 1 à ce stade, plutôt que comme des degrés et des pourcentages. Ainsi, par exemple, le cyan (180 ° 100% 50%) apparaîtrait comme $ h = 0,5, $ s = 1 et $ l = 0,5.
Ensuite, trouvez la valeur de la teinte opposée, c'est-à-dire celle qui est à 180 °, ou 0,5, loin (je suis sûr que les mathématiciens ont une façon plus élégante de le noter, mais):
Calculez la teinte opposée, $ h2
La valeur HSL de la couleur complémentaire est maintenant en $ h2, $ s, $ l. Nous sommes donc prêts à reconvertir cela en RVB (encore une fois, ma version PHP de la formule EasyRGB.com). Notez que les formats d'entrée et de sortie sont différents cette fois, voir mes commentaires en haut du code:
L'entrée est la valeur HSL de la couleur complémentaire, contenue dans $ h2, $ s, $ l sous forme de fractions de 1 La sortie est RVB au format 255 255 255 normal, conservée dans $ r, $ g, $ b La teinte est convertie à l'aide de la fonction hue_2_rgb, illustrée à la fin de ce code
Et après cette routine, nous avons enfin $ r, $ g et $ b au format 255 255 255 (RGB), que nous pouvons convertir en six chiffres hexadécimaux:
$ rgbhex est notre réponse - la couleur complémentaire en hexadécimal.
Étant donné que votre arrière-plan de couleur est bleu ou 0,0255, le HSL est
Teinte (H): 240 degrés / Saturation (S): 100% / Luminosité (L): 4,9%
l'opposé de 240 est 60 dans un cercle puis reconvertir en RVB donne une valeur de # 181800
la source
Je voudrais développer l'idée de @ ashes999 de créer un plan.
Mon code va être aussi semblable à python que possible du haut de ma tête (je n'ai jamais écrit une ligne de python de ma vie, mais j'ai jeté un coup d'œil sur un livre une ou deux fois).
Cela peut ne pas être particulièrement joli et ce n'est pas vraiment idéal pour le code de production, mais cela devrait suffire comme solution rapide. Je n'ai pas testé le code car je n'ai pas exactement de programme "balles qui rebondissent autour de l'écran" que je peux mutiler pour le tester.
Modifier:
En voyant le code réel en cours d'utilisation, la situation a basculé, alors je propose plutôt cette solution.
Remplacez les lignes 276-284 par ce qui suit:
Dans cette nouvelle version simplifiée, une méthode d'usine crache les boules et une méthode spécialisée génère les couleurs. Le générateur de couleurs teste la couleur générée aléatoirement pour voir si elle se situe dans une certaine plage de proximité avec la couleur d'arrière-plan. Une couleur est considérée comme trop proche de la couleur BG si les trois canaux de couleur se trouvent de
leeway
part et d'autre de BG. Donc, si la latitude est 0, seules les couleurs qui correspondent exactement à BG sont refusées. J'ai choisi 5 par défaut, ce qui refuse la couleur BG et les 5 couleurs de chaque côté. Étant donné que la couleur BG est blanche, je ne sais pas si elle refusera le noir car les chiffres s'enroulent. Cela peut être évité en utilisant les fonctions min et max, mais je les ai laissées de côté par souci de concision.la source
pygame
comme bibliothèque. Pas de Lerp, juste des conversions RGB-HSV-CYMK de base: pygame.org/docs/ref/color.htmllerp
fonction dans ma réponse est tout ce qu'il y a à faire. (Lerp signifie 'interpolation linéaire').print
différent parce que vous utilisez Python 3, et je suis toujours en Python 2. Et je ne sais pas encore s'il apygame
été porté sur Py3. Conclusion: ne vous embêtez pas :) La question concerne les couleurs, vous n'avez pas besoin de balles réelles rebondissant :)Pour un format RVB, cela semble fonctionner assez bien et c'est trivial:
Divers_score = (abs (r1 - r2) + abs (g1 - g2) + abs (b1 - b2)) / 765.0
Cela vous donnera un score entre 0,0 et 1,0. Plus il est bas, plus il est difficile de distinguer deux couleurs.
Cela devrait être évident, mais dans un souci d'exhaustivité: les valeurs r, g, b doivent d'abord être converties en un nombre à virgule flottante, et on suppose que leur valeur maximale est 255.
la source