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,
pygame
akceptują 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
Odpowiedzi:
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.
źródło
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:
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:
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:
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!)
źródło
^
, 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**
)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:
który stworzy 20 kolorów, ładnie rozmieszczonych. Zakłada się, że używasz matematyki na liczbach całkowitych, więc
i = 0
ii = 1
stworzy 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):
źródło
V
(ponieważ obecny algorytm tego nie zmienia).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:
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.
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:
Konwertuj kolor na HSL.
Zmień wartość Barwy na wartość Barwy przeciwnej (np. Jeśli Barwa wynosi 50 °, przeciwna wartość będzie na 230 ° na kole - 180 ° dalej).
Pozostaw wartości nasycenia i lekkości takie, jakie były.
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
Może być również prezentowany jako czerwony dziesiętny 0 + zielony dziesiętny 0 + niebieski dziesiętny 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
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
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
Po tej procedurze mamy wreszcie $ r, $ gi $ bw formacie 255 255 255 (RGB), które możemy przekonwertować na sześć cyfr szesnastkowych:
$ 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
źródło
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ę).
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:
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ą
leeway
się 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ść.źródło
pygame
jako biblioteki. Bez Lerp, tylko podstawowe konwersje RGB-HSV-CYMK: pygame.org/docs/ref/color.htmllerp
funkcja w mojej odpowiedzi to wszystko. (Lerp oznacza „interpolację liniową”).print
inny, ponieważ używasz Python 3, a ja wciąż korzystam z Python 2. I nie jestem pewien, czypygame
został jeszcze przeniesiony do Py3. Konkluzja: nie przejmuj się :) Pytanie dotyczy kolorów, nie potrzebujesz rzeczywistych piłek podskakujących dookoła :)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.
źródło