Algorytm modyfikacji koloru, aby był mniej podobny do tła

23

Tworzę demo odbijające się od siebie 20 kulek z tłem wypełnionym jednolitym kolorem. Kolor każdej kulki dobierany jest losowo z randint(0, 255)każdym składnikiem krotnym R, G, B.

Problemem jest to, że niektóre kule mają kolor bardzo podobny do tła, co utrudnia ich dostrzeżenie. Chciałbym tego uniknąć, albo przez zwijanie innego koloru, jeśli wybrany jest zbyt podobny (w ramach określonego progu), albo przez odsunięcie go od koloru tła.

Jak obliczyć wskaźnik podobieństwa, aby zastosować go jako próg? Lub jak przekształcić kolor, aby był, powiedzmy, mniej niebieski ?

Oczywiste zastrzeżenie: Nie wiem nic o teorii kolorów, więc nie wiem, czy powyższe pojęcia w ogóle istnieją!

Piszę w pythonie, ale szukam pojęć i strategii, więc pseudo-kod jest w porządku (lub po prostu teoria).

EDYTOWAĆ:

Aby wyjaśnić kilka punktów:

  • Każda piłka ma swój losowy kolor. Chciałbym, aby pozostawały jak najbardziej losowe i eksplorowały jak najwięcej przestrzeni kolorów (czy to RGB, czy HSV, pygameakceptują oba formaty do definiowania kolorów)

  • Chciałbym tylko uniknąć tego, by każdy kolor był „zbyt blisko” tła. Problem nie dotyczy tylko odcienia: jestem całkowicie w porządku z jasnoniebieską kulką na ciemnoniebieskim tle (lub „pełną niebieską” na niebiesko „białej bieli” itp.)

  • Na razie nie dbam o to, czy kula ma kolor podobny (a nawet identyczny) do innej. Unikanie tego jest premią, ale jest to niewielki problem.

  • Kolor tła to stały, pojedynczy kolor RGB. Na razie używam „podstawowego” niebieskiego (0, 0, 255), ale nie jestem z tym zadowolony. Dlatego rozważ tło w dowolnym kolorze (z dowolnym odcieniem, jasnością, nasyceniem itp.).

EDYCJA 2:

Wersja TL, DR: Po prostu daj sposób na utworzenie X losowych kolorów, aby żadne z nich nie „zanikało zbyt mocno” na tle dowolnego (ale pojedynczego i stałego) koloru

MestreLion
źródło
1
Dlaczego po prostu nie obrysować każdej kuli?
ashes999
1
Wtedy może być problem z odróżnieniem koloru konturu od koloru tła i kulek;)
Kromster mówi o wsparciu Moniki
1
@AlexM .: trudno uwierzyć, że nie ma łatwego rozwiązania, aby „generować losowe kolory, unikając jednego”
MestreLion
1
@MestreLion wystarczy użyć czarnego dla konturu i wygenerować kolory o minimalnej wartości RGB 128. To takie proste.
ashes999

Odpowiedzi:

33

Możesz wykorzystać fakt, że kolory tworzą (trójwymiarową) przestrzeń kolorów i obliczyć odległość w tej przestrzeni kolorów. Następnie musisz zdefiniować metrykę w tej przestrzeni kolorów, aby znaleźć odległość między dwoma kolorami.

Np. Odległość w przestrzeni euklidesowej między dwoma punktami x = (x1, x2, x3) iy = (y1, y2, y3) jest określone przez d (x, y) = sqrt ((y1-x1) * (y1- x1) + (y2-x2) * (y2-x2) + (y3-x3) * (y3-x3)).

Teraz możesz obliczyć odległość między kolorem kulek a kolorem tła, a jeśli jest zbyt mały, utwórz nowy losowy kolor i przetestuj ponownie.

Przekonasz się, że ani RGB, ani nawet HSV nie są dobrymi przestrzeniami kolorów do tego zadania. Artykuł w Wikipedii na temat różnicy kolorów wykorzystuje przestrzeń kolorów L a b i podaje kilka możliwych wskaźników.

Istnieje również dyskusja na temat przepełnienia stosu w tym temacie.

René
źródło
To bardzo miłe podejście, mógłbym to zrobić :) Dzięki! Czy chcesz też nieco opracować, w jaki sposób znaleźć odpowiedni próg „minimalnej odległości”? Jeśli RGB nie jest wystarczające, jak przekonwertować na L a b? Nie dążę do uzyskania dokładnych wskaźników postrzegania, więc wystarczą wartości domyślne „wystarczająco dobre”.
MestreLion,
1
Uwielbiam tę odpowiedź, dobrze przemyślane, dobre wyjaśnienie, jak wykonać to zadanie, jednocześnie zapewniając potrzebne równania i odniesienia. Dobra pierwsza odpowiedź.
Tom „Blue” Piddock,
1
Jeśli szukasz „wystarczająco dobrego” przybliżenia ludzkiej percepcji, możesz zajrzeć do przestrzeni kolorów YUV , która ma bezpośrednią konwersję z RGB.
trm
5
Zaoszczędź trochę czasu i nie rób pierwiastka kwadratowego (drogi). Po prostu określ minimalną odległość koloru w porównaniu do kwadratu.
Chris Cudmore,
1
@MestreLion Przestrzeń kolorów L a b * została wymyślona, ​​aby była percepcyjnie jednolita, co oznacza, że ​​postrzegana odległość między dwoma kolorami jest taka sama, jak rzeczywista odległość w przestrzeni kolorów. Ponieważ kolory RGB zależą od urządzenia, nie można bezpośrednio konwertować między Lab i RGB. Jeśli jednak używasz określonej absolutnej przestrzeni kolorów RGB, możesz je przekonwertować. Zobacz ten artykuł: en.wikipedia.org/wiki/SRGB_color_space i ten artykuł: en.wikipedia.org/wiki/Lab_color_space
jwir3
8

Strona ONZ dotycząca standardów dostępności stron internetowych ( http://www.un.org/webaccessibility/1_visual/13_colourcontrast.shtml ) wskazuje standard zapewniania właściwego kontrastu tekstu na stronach internetowych, pamiętając, że niektórzy użytkownicy są ślepi na kolory. Może to być szczególnie ważne dla Ciebie, ponieważ niektórzy użytkownicy mogą być ślepi na kolory (trudno byłoby odróżnić czerwoną kulkę od zielonego tła, jeśli mają taką samą luminancję).

Strona ONZ wskazuje analizator współczynnika kontrastu jasności Juicy Studios pod adresem ( http://juicystudio.com/services/luminositycontrastratio.php#specify ), który stwierdza, że ​​tekst w tle musi mieć współczynnik kontrastu 4,5: 1, z wyjątkiem tego, co I uważasz, że jest podobny do twojego przypadku:

  • Duży tekst: Duży tekst i obrazy dużego tekstu mają współczynnik kontrastu co najmniej 3: 1

Co to jest współczynnik kontrastu? Idąc dalej za linkami (to jest fajne!) Dochodzimy do strony W3, która definiuje współczynnik kontrastu jako:

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

Gdzie L1 i L2 są względnymi jasnościami kolorów. L1 to kolor bardziej luminantowy, L2 to kolor mniej luminantowy. Ponownie podążamy za linkiem do tej samej strony W3, która określa:

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

UWAGA : Symbol karetki ^ powyżej odnosi się do potęgowania (x²)

Mamy całkiem niezłą ramę dla algorytmu kontrastu (który jest przyjazny dla niewidomych kolorów!)

  • Określ wartości R, G, B dla każdego koloru
  • Określ luminancję dla każdego koloru
  • Jeśli współczynnik kontrastu koloru bardziej świecącego do najmniejszego koloru świecącego jest mniejszy niż 3, przewiń!
Jan
źródło
2
Może warto zauważyć, że ^ ma być potęgowaniem. Dla nas szalonych użytkowników podobnych do C oznacza to xor (naprawdę myślałem, że próbujesz wykonać bitową operację na wartościach zmiennoprzecinkowych przez minutę).
Pharap
To niesamowite podejście, podoba mi się! :)
MestreLion
I nie martw się ^, nigdy nie pomyślałbym o bitowym XOR w tym kontekście. (lub w rzeczywistości. C'mon C phreaks, ^to de facto simbol do potęgowania w pseudokodach (chociaż tak naprawdę niewiele języków używa go ... w pythonie **)
MestreLion
1
Naprawiam literówki. Dodatkowo, jeśli jedna osoba ma problemy z ^, są szanse, że ktoś w przyszłości też może. Nie zaszkodzi być konkretnym.
John
1
@John Nie martw się,. Nie jestem pewien, skąd bierze się zamieszanie (tj. Który język użył ^ w jakim celu jako pierwszy). Wiem tylko, że ^ jest czasami używany do potęgowania z powodu mojego doświadczenia z VB (nie znam innych języków, które używają go jako potęgowanie, ale prawdopodobnie są pewne). Jednak jako heads-up jest to symbol karetki , a nie marchewki . Być może zechce to zmienić, zanim ktoś zacznie okropnie żartować o programowaniu z warzywami (szczególnie z pierwiastkami kwadratowymi).
Pharap
2

Używanie wartości RGB przez generowanie losowego 0-255 wartości dla każdego komponentu może nie tylko tworzyć kolory podobne do tła, ale także uzyskać bardzo podobne kolory dla kulek.

Prawdopodobnie wybrałbym mniej losowe podejście i zamiast tego stworzyłem kolory, które z pewnością będą inne. Możesz stworzyć kolor dla każdego ~ 32 stopni w zakresie odcienia i naprzemiennie jasność lub nasycenie (użyj modelu kolorów HSV zamiast RGB).

Więc coś takiego:

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

który stworzy 20 kolorów, ładnie rozmieszczonych. Zakłada się, że używasz matematyki na liczbach całkowitych, więci = 0 i i = 1stworzy taką samą wartość odcienia.

Oczywiście nie skaluje się to zbyt dobrze .. jeśli masz 100 wartości kolorów do utworzenia, odstępy odcieni mogą być niewystarczające i znów uzyskasz podobne kolory. W takim przypadku możesz również zmienićV (jasności).

Nie wiem, jaki jest kolor tła, ale HSV ułatwia także porównywanie kolorów (po prostu porównaj 3 składniki i nie zapominaj, że HUE jest okrągły (0 == 360)).

AKTUALIZACJA:

Ponieważ tak naprawdę nie odpowiedziałem na twoje pytanie, a raczej podałem inne podejście, oto jak mógłby wyglądać algorytm dla dowolnego tła i całkowicie losowych kolorowych piłek (jest to podejście brutalne, ale powinno dobrze działać w twoim przypadku użycia):

// 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
}
grzmot
źródło
Co do twojego algorytmu, jak bierze pod uwagę kolor tła?
MestreLion,
Obecnie nie bierze pod uwagę koloru tła ... można go poprawić, porównując wygenerowane kolory (jak opisano w ostatnim akapicie), a następnie utworzyć kolor z innym V(ponieważ obecny algorytm tego nie zmienia).
bummzack
@MestreLion Dodano aktualizację z alternatywnym algorytmem
bummzack
Świetnie, to wydaje się niezła strategia. Brutalna siła jest OK, kolory są generowane tylko raz przy inicjalizacji, a nie w pętli gry. Wygląda na to, że używasz tego samego podejścia, co podejście René, ze zwykłą odległością euklidesową w HSV, prawda? Wszelkie odniesienia do odpowiedniego progu dla HSV? Czy H, S i V ważą takie same odległości jak w RGB?
MestreLion,
@MestreLion Tak, mój drugi algorytm jest dokładnie tym, co René wyjaśnił w swojej odpowiedzi. Niestety nie ma ostatecznej wartości dobrego progu, ponieważ zmiany kolorów nie są postrzegane jednolicie. Zmiany w kolorze zielonym są rozpoznawane znacznie szybciej niż w kolorze niebieskim ... więc dla odcieni zieleni może działać mniejszy próg, ale nie będzie wystarczający dla innych kolorów itp. O ile wiem, przestrzeń kolorów Lab jest zbliżona do postrzegania kolorów przez ludzi i najlepiej nadaje się, jeśli nie uzyskasz pożądanych rezultatów z przestrzenią kolorów HSV.
bummzack
1

Odkąd wspomniałeś, że masz nieruchome tło, kolor kulek może nadal być losowy, ale muszą spadać w pewnych zakresach, które nadal uzupełniają tło.

Podstawy Zanim to zrobimy, musisz znać podstawy. Rozważ następujące kolory:

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)

Mieszanka kolorów RGB [(0..255), (0..255), (0..255)] tworzy nowe kolory jak wyżej.

Obliczanie kolorów ujemnych Obliczanie kolorów ujemnych jest jak przekształcenie koloru czerwonego na cyjan, zielonego na fioletowy i niebieskiego na żółty.

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)

Kolor uzupełniający

Zgodnie z odniesieniem na Computing uzupełniające kolory: http://serennu.com/colour/rgbtohsl.php

O HSL

HSL wyraża kolory w kategoriach ich barwy, nasycenia i jasności, podając liczbę dla każdego z tych trzech atrybutów koloru.

Barwa to pozycja koloru na kole kolorów, wyrażona w stopniach od 0 ° do 359 °, reprezentująca 360 ° koła; 0 ° to czerwony, 180 ° to przeciwny kolor cyjanu i tak dalej.

Nasycenie to intensywność koloru, jak nudny lub jasny. Im niższe nasycenie, tym bardziej matowy (bardziej szary) kolor. Jest to wyrażone w procentach, 100% oznacza pełne nasycenie, najjaśniejsze, a 0% oznacza brak nasycenia, szare.

Lekkość to jasność koloru. Nieznacznie różni się od nasycenia. Im bardziej biały kolor, tym wyższa jest jego wartość jasności, tym więcej czerni, tym niższa jest jego jasność. Tak więc 100% lekkości zmienia kolor na biały, 0% lekkości zmienia kolor na czarny, a „czysty” kolor to 50% lekkości.

Łatwiej jest dostrzec różnicę między nasyceniem a jasnością niż wyjaśnić to. Jeśli chcesz to wyjaśnić, spróbuj przejrzeć warianty Jasność i Nasycenie na stronie kalkulatora kolorów, wybierając dość jasny kolor jako kolor początkowy.

Tak wygląda notacja HSL, podając wartości Barwy, Nasycenia i Jasności w następującej kolejności: t

Czerwony: 0 ° 100% 50% Jasnoróżowy: 0 ° 100% 90% Cyjan: 180 ° 100% 50% Oto kroki:

  1. Konwertuj kolor na HSL.

  2. Zmień wartość Barwy na wartość Barwy przeciwnej (np. Jeśli Barwa wynosi 50 °, przeciwna wartość będzie na 230 ° na kole - 180 ° dalej).

  3. Pozostaw wartości nasycenia i lekkości takie, jakie były.

  4. Konwertuj tę nową wartość HSL z powrotem na oryginalny zapis kolorów (RGB lub cokolwiek innego).

Strony takie jak EasyRGB.com mogą generować ogólne konwersje z RGB na HSL i odwrotnie.

Przykład programowania wykonany w PHP zgodnie z odnośnikiem

Konwersja RGB z HSL

Wartość powyżej niebieskiego # 0000FF rgb (0,0,255) można przedstawić jako czerwony szesnastkowy 00 + zielony szesnastkowy 00 + niebieski szesnastkowy FF

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

Może być również prezentowany jako czerwony dziesiętny 0 + zielony dziesiętny 0 + niebieski dziesiętny 255

$var_r = (hexdec($redhex)) / 255;
$var_g = (hexdec($greenhex)) / 255;
$var_b = (hexdec($bluehex)) / 255;

Teraz podłącz te wartości do procedury rgb2hsl. Poniżej moja wersja PHP ogólnego kodu EasyRGB.com do tej konwersji:

Dane wejściowe to $ var_r, $ var_g i $ var_b z góry Dane wyjściowe są równoważne HSL jako $ h, $ s i $ l - są one ponownie wyrażane jako ułamki 1, podobnie jak wartości wejściowe

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

Teraz mamy kolor jako wartość HSL w zmiennych $ h, $ s i $ l. Te trzy zmienne wyjściowe są ponownie utrzymywane jako ułamki 1 na tym etapie, a nie jako stopnie i procenty. Na przykład cyjan (180 ° 100% 50%) wyszedłby jako $ h = 0,5, $ s = 1, a $ l = 0,5.

Następnie znajdź wartość przeciwnego odcienia, tj. Oddaloną o 180 ° lub 0,5 (jestem pewien, że matematycy mają bardziej elegancki sposób na kropkowanie tego, ale):

Oblicz przeciwny odcień, $ h2

            $h2 = $h + 0.5;

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

Wartość HSL koloru uzupełniającego jest teraz w $ h2, $ s, $ l. Jesteśmy więc gotowi przekonwertować to z powrotem na RGB (znowu moja wersja PHP formuły EasyRGB.com). Uwaga: tym razem formaty wejściowe i wyjściowe są różne, zobacz moje komentarze na górze kodu:

Wejście to wartość HSL koloru uzupełniającego, przechowywana w $ h2, $ s, $ l jako ułamki 1 Wyjście to RGB w normalnym formacie 255 255 255, przechowywane w $ r, $ g, $ b Odcień jest konwertowany za pomocą funkcji hue_2_rgb, pokazano na końcu tego kodu

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

Po tej procedurze mamy wreszcie $ r, $ gi $ bw formacie 255 255 255 (RGB), które możemy przekonwertować na sześć cyfr szesnastkowych:

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

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

$ rgbhex to nasza odpowiedź - kolor uzupełniający w heksie.

Ponieważ tło w kolorze jest niebieskie lub 0,0,255, HSL jest

Barwa (H): 240 stopni / Nasycenie (S): 100% / Jasność (L): 4,9%

naprzeciwko 240 jest 60 w kole, a następnie konwersja z powrotem do RGB daje wartość # 181800

Ace Caserya
źródło
Dzięki! Ale link mówi o generowaniu „uzupełniającego koloru” (cokolwiek to jest) samego siebie . Nadal nie mam pojęcia, jak tego użyć, aby rozwiązać mój problem: upewnij się, że każdy losowy kolor nie jest podobny do koloru tła. Kolor tła jest stały, jeden kolor i jest wiele kulek.
MestreLion,
Dzięki Krom, że to teraz robi. @MestreLion, ponieważ tło jest stałe, możesz określić zakres kul, który nadal będzie uzupełniał tło.
Ace Caserya
Obecnie wyjaśniam moją odpowiedź.
Ace Caserya
Gotowy. Nie robię wiele, aby zmienić wiele w wyjaśnieniu stron, ponieważ jest wystarczająco dobrze wyjaśnione. Podziękowania dla facetów z EasyRGB.com
Ace Caserya
Pozwól nam kontynuować tę dyskusję w czacie .
Ace Caserya
1

Chciałbym rozwinąć pomysł @ ashes999 na stworzenie konturu.

Mój kod będzie tak podobny do pytona, jak to tylko możliwe, z góry mojej głowy (nigdy w życiu nie napisałem linii pytona, ale raz lub dwa rzuciłem okiem na książkę).

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

Może nie wygląda szczególnie ładnie i nie jest naprawdę idealny do kodu produkcyjnego, ale powinien wystarczyć jako szybka poprawka. Nie przetestowałem kodu, ponieważ nie mam pod ręką programu „kulki podskakujące po ekranie”, który można okaleczyć, aby go przetestować.


Edytować:

Po zobaczeniu właściwego kodu sytuacja się odwróciła, więc zamiast tego oferuję to rozwiązanie.

Zastąp wiersze 276–284 następującym:

# 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())

W tej nowej uproszczonej wersji metoda fabryczna wyrzuca kule, a metoda specjalistyczna generuje kolory. Generator kolorów sprawdza losowo generowany kolor, aby sprawdzić, czy mieści się w pewnym zakresie bliskości koloru tła. Kolor uważa się za zbyt bliski kolorowi BG, jeśli wszystkie trzy jego kanały kolorów znajdują leewaysię po obu stronach BG. Jeśli więc swoboda wynosi 0, odrzucane są tylko te kolory, które dokładnie pasują do BG. Wybrałem 5 jako domyślną, która odrzuca kolor BG i 5 kolorów po obu stronach. Ponieważ kolor BG jest biały, nie jestem pewien, czy odmówi czerni, ponieważ cyfry się zawijają. Można tego uniknąć za pomocą funkcji min i max, ale pominąłem je ze względu na zwięzłość.

Pharap
źródło
Jestem otwarty na każdą strategię :) jeśli chodzi o program do okaleczania, mogę ci powiedzieć, że: github.com/MestreLion/rainballs odpowiednie linie to 279-284
MestreLion
Używam pygamejako biblioteki. Bez Lerp, tylko podstawowe konwersje RGB-HSV-CYMK: pygame.org/docs/ref/color.html
MestreLion
@MestreLion O, lordy, teraz muszę zainstalować grę pygame i python, aby ją przetestować. Strzeliłem sobie w stopę tym jednym XP. Lerping jest łatwy, lerpfunkcja w mojej odpowiedzi to wszystko. (Lerp oznacza „interpolację liniową”).
Pharap
@MestreLion Zakłóciłem się nieco, okazuje się, że moja wersja Pythona nie lubi wywoływania print bez nawiasów. Naprawiłem to, ale teraz mam błędy z gry Pygame, które nie są w stanie znaleźć odpowiednich bibliotek. Przepiszę mój kod, aby pasował do tego, co masz, ale nie mogę go przetestować, dopóki nie naprawię pygame. Polecam dołączenie tego pliku do pytania, jeśli jeszcze tego nie zrobiłeś (na wypadek, gdyby ktoś czuł się wystarczająco fajnie, aby napisać dla ciebie jakiś python).
Pharap
Jesteś printinny, ponieważ używasz Python 3, a ja wciąż korzystam z Python 2. I nie jestem pewien, czy pygamezostał jeszcze przeniesiony do Py3. Konkluzja: nie przejmuj się :) Pytanie dotyczy kolorów, nie potrzebujesz rzeczywistych piłek podskakujących dookoła :)
MestreLion
1

W przypadku formatu RGB wydaje się, że działa wystarczająco dobrze i jest trywialny:

różnorodność_score = (abs (r1 - r2) + abs (g1 - g2) + abs (b1 - b2)) / 765,0

To da ci wynik od 0,0 do 1,0. Im niższy, tym trudniej rozróżnić dwa kolory.

Powinno to być oczywiste, ale ze względu na kompletność: wartości r, g, b należy najpierw rzucić na liczbę zmiennoprzecinkową i przyjmuje się, że ich maksymalna wartość wynosi 255.

AB
źródło