Algorithme pour modifier une couleur pour la rendre moins similaire à l'arrière-plan

23

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, pygameaccepte 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)

MestreLion
la source
1
Pourquoi ne pas simplement mettre un contour autour de chaque balle?
ashes999
1
Ensuite, il pourrait y avoir un problème à faire une couleur de contour distincte de la couleur d'arrière-plan ET des boules;)
Kromster dit qu'il prend en charge Monica
1
@AlexM .: difficile de croire qu'il n'y a pas de solution facile pour "générer des couleurs aléatoires en évitant les couleurs arbitraires"
MestreLion
1
@MestreLion utilise simplement du noir pour le contour et génère des couleurs avec une valeur RVB minimale de 128. C'est aussi simple que cela.
ashes999

Réponses:

33

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.

René
la source
C'est une très bonne approche, je pourrais le faire :) Merci! Aussi, voulez-vous élaborer un peu sur la façon de trouver un seuil de "distance minimale" adéquat? Si RVB n'est pas adéquat, comment convertir en L a b? Je ne m'efforce pas d'obtenir des mesures de perception précises, donc tout défaut "assez bon" fera l'affaire.
MestreLion
1
J'adore cette réponse, bien pensée, bonne explication de la façon de faire la tâche tout en fournissant les équations et les références nécessaires. Bonne première réponse.
Tom 'Blue' Piddock
1
Si vous cherchez une approximation "assez bonne" de la perception humaine, vous voudrez peut-être regarder dans l' espace colorimétrique YUV , qui a une conversion directe de RVB.
trm
5
Gagnez un peu de temps et ne prenez pas la racine carrée (chère). Faites simplement votre valeur de distance de couleur minimale que vous comparez au carré.
Chris Cudmore
1
@MestreLion L' espace colorimétrique L a b * a été inventé pour être perceptuellement uniforme, ce qui signifie que la distance perçue entre deux couleurs est la même que la distance réelle dans l'espace colorimétrique. Étant donné que les couleurs RVB dépendent de l'appareil, vous ne pouvez pas convertir directement entre Lab et RVB. Cependant, si vous utilisez un espace colorimétrique RVB absolu spécifique, vous pouvez les convertir. Voir cet article: en.wikipedia.org/wiki/SRGB_color_space et cet article: en.wikipedia.org/wiki/Lab_color_space
jwir3
8

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:

  • Grand texte: le texte à grande échelle et les images de texte à grande échelle ont un rapport de contraste d'au moins 3: 1

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:

Contrast Ratio = (L1 + 0.05)/(L2 + 0.05)

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:

L = 0.2126 * R + 0.7152 * G + 0.0722 * B where R, G and B are defined as:

if RsRGB <= 0.03928 then R = RsRGB/12.92 else R = ((RsRGB+0.055)/1.055) ^ 2.4
if GsRGB <= 0.03928 then G = GsRGB/12.92 else G = ((GsRGB+0.055)/1.055) ^ 2.4
if BsRGB <= 0.03928 then B = BsRGB/12.92 else B = ((BsRGB+0.055)/1.055) ^ 2.4
and RsRGB, GsRGB, and BsRGB are defined as:

RsRGB = R8bit/255
GsRGB = G8bit/255
BsRGB = B8bit/255

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!)

  • Déterminer les valeurs R, G, B pour chaque couleur
  • Déterminer la luminance pour chaque couleur
  • Si le rapport de contraste de la couleur la plus lumineuse à la couleur la moins lumineuse est inférieur à 3, relancez!
John
la source
2
Pourrait noter que ^ est censé être l'exponentiation. Pour nous, utilisateurs fous de type C, cela signifie xor (je pensais vraiment que vous essayiez de faire une opération au niveau du bit sur des valeurs à virgule flottante pendant une minute).
Pharap
C'est une approche incroyable , j'aime ça! :)
MestreLion
Et ne vous inquiétez pas ^, 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 **)
MestreLion
1
Je corrige juste des fautes de frappe. De plus, si une personne a des problèmes avec le ^, il y a de fortes chances que quelqu'un d'autre le puisse aussi à l'avenir. Cela ne fait pas de mal d'être précis.
John
1
@John Pas de soucis,. Je ne sais pas d'où vient la confusion (c'est-à-dire la langue utilisée ^ dans quel but en premier). Je sais seulement que ^ est parfois utilisé pour l'exponentiation en raison de mon expérience avec VB (je ne connais pas d'autres langages qui l'utilisent comme exponentiation, mais il y en a probablement quelques-uns). Mais juste pour vous prévenir, c'est le symbole du curseur , pas le symbole de la carotte . Pourrait vouloir le changer avant que quelqu'un fasse une blague horrible à propos de la programmation avec des légumes (en particulier une impliquant des racines carrées).
Pharap
2

L'utilisation de valeurs RVB en générant une 0-255valeur 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:

numColors = 20;
stepSize = 360 / (numColors / 2 + 1); // hue step size
for(i = 0; i < numColors; i++){
    color = HSV(i / 2 * stepSize, 0.5 + (i % 2) * 0.5, 1.0) 
}

ce qui créera 20 couleurs, bien réparties. Cela suppose que vous utilisez des mathématiques entières i = 0et i = 1cré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 Vvaleur (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):

// background color, currently equals RGB(0, 0, 255)
bg = HSV(240, 1.0, 1.0)

// number of colors to create is equal to the amount of balls
numColors = balls.length

// set threshold to compare colors. you can tweak this to your liking
threshold = 0.15

for(i = 0; i < numColors; i++){
    do {
        // assuming rnd returns a random float 0-1 inclusive
        color = HSV(rnd() * 360, rnd(), rnd())
        // calculate delta values, normalize hue to 0-1
        dH = (180 - abs(abs(bg.h - color.h) - 180)) / 360
        dS = bg.s - color.s
        dV = bg.v - color.v
        // "distance" between bg and color
        difference = sqrt(dH * dH + dS * dS + dV * dV)
    } while(difference < threshold)

    ball[i].color = color
}
bummzack
la source
À propos de votre algorithme, comment prend-il en compte la couleur d'arrière-plan?
MestreLion
Il ne prend actuellement pas en compte la couleur d'arrière-plan ... vous pouvez la modifier en comparant les couleurs générées (comme décrit dans le dernier paragraphe), puis créer une couleur avec une autre V(car l'algorithme actuel ne change pas cela).
bummzack
@MestreLion Ajout d'une mise à jour avec un algorithme alternatif
bummzack
Génial, cela semble être une bonne stratégie. La force brute est OK, les couleurs ne sont générées qu'une seule fois à l'initialisation, pas dans la boucle de jeu. Il semble que vous utilisiez la même approche que celle de René, avec une distance euclidienne simple en HSV, n'est-ce pas? Avez-vous des références d'un seuil approprié pour le HSV? Est-ce que H, S et V ont le même poids en distance comme en RVB?
MestreLion
@MestreLion Oui, mon deuxième algorithme est à peu près ce que René a expliqué dans sa réponse. Malheureusement, il n'y a pas de valeur définitive pour un bon seuil car les changements de couleur ne sont pas perçus uniformément. Nous reconnaissons les changements dans le vert beaucoup plus rapidement que dans le bleu ... donc pour les tons verts, un seuil plus petit peut fonctionner mais ne sera pas suffisant pour d'autres couleurs, etc. Pour autant que je sache, l'espace colorimétrique Lab est proche de la perception des couleurs humaines et peut être mieux adapté si vous n'obtenez pas de résultats souhaitables avec l'espace colorimétrique HSV.
bummzack
1

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:

Black   #000000 rgb(0,0,0)
Red     #FF0000 rgb(255,0,0)
Green   #00FF00 rgb(0,255,0)
Blue    #0000FF rgb(0,0,255)
Yellow  #FFFF00 rgb(255,255,0)
Cyan    #00FFFF rgb(0,255,255)
Pink    #FF00FF rgb(255,0,255)
Gray    #C0C0C0 rgb(192,192,192)
White   #FFFFFF rgb(255,255,255)

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.

Red     #FF0000 rgb(255,0,0) ->     Cyan    #00FFFF rgb(0,255,255)
Green   #00FF00 rgb(0,255,0) ->     Purple   #FF00FF    rgb(255,0,255)
Blue    #0000FF rgb(0,0,255) ->     Yellow  #FFFF00 rgb(255,255,0)

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:

  1. Convertissez votre couleur en HSL.

  2. 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).

  3. Laissez les valeurs de saturation et de luminosité telles qu'elles étaient.

  4. 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

$redhex  = substr($hexcode,0,2);
$greenhex = substr($hexcode,2,2);
$bluehex = substr($hexcode,4,2);

Il peut également être présenté en rouge décimal 0 + vert décimal 0 + bleu décimal 255

$var_r = (hexdec($redhex)) / 255;
$var_g = (hexdec($greenhex)) / 255;
$var_b = (hexdec($bluehex)) / 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

$var_min = min($var_r,$var_g,$var_b);ttt
$var_max = max($var_r,$var_g,$var_b);
$del_max = $var_max - $var_min;

$l = ($var_max + $var_min) / 2;

if ($del_max == 0)
{
        $h = 0;
        $s = 0;
}
else
{
        if ($l < 0.5)
        {
                $s = $del_max / ($var_max + $var_min);
        }
        else
        {
                $s = $del_max / (2 - $var_max - $var_min);
        };

        $del_r = ((($var_max - $var_r) / 6) + ($del_max / 2)) / $del_max;
        $del_g = ((($var_max - $var_g) / 6) + ($del_max / 2)) / $del_max;
        $del_b = ((($var_max - $var_b) / 6) + ($del_max / 2)) / $del_max;

        if ($var_r == $var_max)
        {
                $h = $del_b - $del_g;
        }
        elseif ($var_g == $var_max)
        {
                $h = (1 / 3) + $del_r - $del_b;
        }
        elseif ($var_b == $var_max)
        {
                $h = (2 / 3) + $del_g - $del_r;
        };

        if ($h < 0)
        {
                $h += 1;
        };

        if ($h > 1)
        {
                $h -= 1;
        };
};

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

            $h2 = $h + 0.5;

            if ($h2 > 1)
                    {
                            $h2 -= 1;
                    };

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

    if ($s == 0)
    {
            $r = $l * 255;
            $g = $l * 255;
            $b = $l * 255;
    }
    else
    {
            if ($l < 0.5)
            {
                    $var_2 = $l * (1 + $s);
            }
            elset
            {
                    $var_2 = ($l + $s) - ($s * $l);
            };

            $var_1 = 2 * $l - $var_2;
            $r = 255 * hue_2_rgb($var_1,$var_2,$h2 + (1 / 3));
            $g = 255 * hue_2_rgb($var_1,$var_2,$h2);
            $b = 255 * hue_2_rgb($var_1,$var_2,$h2 - (1 / 3));
    };

   // Function to convert hue to RGB, called from above

    function hue_2_rgb($v1,$v2,$vh)
    {
            if ($vh < 0)
            {
                    $vh += 1;
            };

            if ($vh > 1)
            {
                    $vh -= 1;
            };

            if ((6 * $vh) < 1)
            {
                    return ($v1 + ($v2 - $v1) * 6 * $vh);
            };

            if ((2 * $vh) < 1)
            {
                    return ($v2);
            };

            if ((3 * $vh) < 2)
            {
                    return ($v1 + ($v2 - $v1) * ((2 / 3 - $vh) * 6));
            };

            return ($v1);
    };

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:

    $rhex = sprintf("%02X",round($r));
    $ghex = sprintf("%02X",round($g));
    $bhex = sprintf("%02X",round($b));

    $rgbhex = $rhex.$ghex.$bhex;

$ 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

Ace Caserya
la source
Merci! Mais le lien parle de générer une "couleur complémentaire" (quelle qu'elle soit) d' elle - même . Je ne sais toujours pas comment utiliser cela pour résoudre mon problème: assurez-vous que chaque couleur aléatoire n'est pas similaire à la couleur d'arrière-plan. La couleur d'arrière-plan est constante, une seule couleur et il y a plusieurs boules.
MestreLion
Merci Krom de faire ça maintenant. @MestreLion, puisque l'arrière-plan est constant, vous pouvez spécifier une plage de vos balles qui complète encore l'arrière-plan.
Ace Caserya
Expose actuellement ma réponse.
Ace Caserya
Terminé. Je n'ai pas grand chose à changer sur l'explication des sites car elle s'explique assez bien. Crédits aux gars sur EasyRGB.com
Ace Caserya
Continuons cette discussion dans le chat .
Ace Caserya
1

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).

def lerp(a,b,value): # assuming your library was not kind enough to give you this for free
    return a + ((b - a) * value);

def drawRandomBall(bgColour,radius,point):
    var ballColour = Colour(random(0,255),random(0,255),random(0,255);
    var outlineColour = Colour(lerp(bgColour.R,255 - ballColour.R,0.5),lerp(bgColour.G,255 - ballColour.G,0.5),lerp(bgColour.B,255 - ballColour.B,0.5));
    fillCircle(point,radius+1,outlineColour);
    fillCircle(point,radius,ballColour);

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:

# Colour generator
def generateColourNonBG(leeway):
    color = (randint(0,255), randint(0,255), randint(0,255))
    while color[0] >= BG_COLOR[0]-leeway and color[0] =< BG_COLOR[0] + leeway and
    color[1] >= BG_COLOR[1]-leeway and color[1] =< BG_COLOR[1] + leeway and
    color[2] >= BG_COLOR[2]-leeway and color[2] =< BG_COLOR[2] + leeway:
        color = (randint(0,255), randint(0,255), randint(0,255))

# Ball generator
def generateBall():
    Ball(generateColourNonBG(5),
                   radius=randint(10, radius),
                   position=[randint(100, screen.get_size()[0]-radius),
                             randint(100, screen.get_size()[0]-radius)],
                   velocity=[randint(50, 50+vel[0]), randint(50, 50+vel[1])],
                   )                       

# Create the balls
balls = pygame.sprite.Group()
for _ in xrange(BALLS):
    balls.add(generateBall())

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 leewaypart 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.

Pharap
la source
Je suis ouvert à toute stratégie :) quant à un programme à mutiler, je peux vous donner que: github.com/MestreLion/rainballs les lignes pertinentes seraient 279-284
MestreLion
J'utilise pygamecomme bibliothèque. Pas de Lerp, juste des conversions RGB-HSV-CYMK de base: pygame.org/docs/ref/color.html
MestreLion
@MestreLion Oh lordy, maintenant je dois installer pygame et python pour le tester. Je me suis tiré une balle dans le pied avec ce XP. Lerping est facile, la lerpfonction dans ma réponse est tout ce qu'il y a à faire. (Lerp signifie 'interpolation linéaire').
Pharap
@MestreLion Fiddled un peu, il s'avère que ma version de python n'aime pas que print soit appelé sans parenthèses. Correction de cela, mais maintenant j'ai des erreurs de pygame ne pouvant pas trouver les bonnes bibliothèques. Je vais réécrire mon code pour qu'il corresponde à ce que vous avez, mais je ne peux pas le tester avant d'avoir corrigé pygame. Je recommanderais d'ajouter ce fichier à la question si vous ne l'avez pas déjà fait (au cas où quelqu'un se sentirait assez gentil pour écrire du python pour vous).
Pharap
Vous êtes printdifférent parce que vous utilisez Python 3, et je suis toujours en Python 2. Et je ne sais pas encore s'il a pygameé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 :)
MestreLion
1

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.

UN B
la source