Wyzwanie algorytmu: generowanie schematu kolorów z obrazu

Tło

Pracuję nad nową iteracją aplikacji internetowej. Odkryliśmy, że nasi użytkownicy mają obsesję na punkcie lenistwa. Naprawdę leniwy. W rzeczywistości, im więcej pracy dla nich wykonujemy, tym bardziej kochają usługę. Część istniejącej aplikacji wymaga od użytkownika wybrania schematu kolorów do użycia. Mamy jednak obraz (zrzut ekranu strony użytkownika), więc dlaczego nie możemy po prostu zaspokoić ich lenistwa i zrobić to za nich? Odpowiedź: możemy, i to będzie zabawne programowanie ćwiczenia! :)

Wyzwanie

Biorąc pod uwagę obraz, jak utworzyć odpowiedni schemat kolorów? Innymi słowy, jak wybrać podstawowe kolory X na obrazie (gdzie X jest definiowane przez aplikację internetową). Obraz użyty w naszej konkretnej sytuacji to zrzut ekranu strony internetowej użytkownika, wykonany w pełnej rozdzielczości (np. 1280x1024). (Uwaga: proszę po prostu opisać swój algorytm - nie ma potrzeby publikowania rzeczywistego pseudokodu.)

Punkty bonusowe (street cred punkty, a nie rzeczywiste tak punkty) dla:

  • opisujący algorytm, który jest prosty, ale skuteczny. Kod to sposób, w jaki tworzymy - zachowaj go prosto i pięknie.
  • pozwala użytkownikowi dostosować schemat kolorów zgodnie z różnymi "nastrojami", takimi jak "kolorowe", "jasne", "wyciszone", "Głębokie" itp. (a la Kuler )
  • opisujący metodę niezawodnego określania głównegotekstu koloru użytego na zrzucie ekranu strony (będzie prawdopodobnie wymagał własnego, osobnego, algo).

Inspiracja

Istnieje kilka istniejących witryn, które spełniają podobną funkcję. Możesz je sprawdzić i zadać sobie pytanie: "jak mógłbym to powielać? Jak mogę to poprawić?"

Author: Sebastian Zartner, 2009-07-10

11 answers

  1. Aby znaleźć podstawowe kolory X, zrzut ekranu aplikacji. Uruchom histogram koloru na obrazie. Top x kolory w histogramie są motywem. Edit: jeśli używane są gradienty, będziesz chciał wybrać różne "szczyty" kolorów; to znaczy, możesz mieć całą masę kolorów wokół "pomarańczowego", jeśli pomarańczowy jest jednym z głównych kolorów używanych w gradientach. Skutecznie, po prostu wymusić pewną odległość między kolorami wybranymi z histogramu.

  2. Podkręcanie schemat kolorów można najlepiej wykonać w przestrzeni HSV; Konwertuj kolory na przestrzeń HSV, a jeśli użytkownicy chcą, aby była "jaśniejsza", zwiększ wartość, jeśli chcą, aby była bardziej" kolorowa", zwiększ nasycenie itp.

  3. Określenie koloru tekstu można najlepiej wykonać, charakteryzując obszary o dużej zmienności (wysoka częstotliwość w przestrzeni Fouriera). W tych obszarach powinieneś mieć: dwa kolory, tekst i tło, w którym to przypadku tekst jest mniej używanym kolorem; lub będziesz mieć kilka kolorów, tekst i kolory obrazu tła, w którym to przypadku kolor tekstu jest najczęstszym kolorem.

 25
Author: Paul Sonier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 20:43:46

Możesz spojrzeć na:

Https://github.com/dcollien/Dreamcoat

Który robi to w CoffeeScript (literacka kawa, więc jest dobrze udokumentowana)

Demo tutaj: http://dcollien.github.io/Dreamcoat/test.html

Ma zarówno podejście do kwantyzacji kolorów, jak i podejście KMeans, które są połączone.

 7
Author: Molange,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-08 16:02:26

Kwantyzacja kolorów jest tym samym procesem używanym do wyboru palety dla plików GIF o niskim kolorze. Aby uzyskać paletę kolorów z obrazu fotograficznego, użyłem kwantyzacji Nicka Rabinowitza.js , który opiera się na Mmcq Leptonica (modified median cut quantization).

Aplikacja internetowa NA ŻYWO, o .

 6
Author: forresto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-25 17:56:59

Robię to, aby znaleźć paletę używaną do obrazów (kompozycji).

  1. Zaczynam od imagemagick i zmieniam rozmiar dużego obrazu do wykonalnego rozmiaru (np.) To rzeczywiście pomaga konwertować subtelne lokalne różnice kolorów na mniej pikseli ze średnią tych kolorów.

  2. Przełącz każdy piksel na obrazie o zmienionym rozmiarze, odczytaj wartości RGB dla każdego piksela, przekonwertuj RGB na HSB i zapisz wartości HSB na / align = "left" /

  3. Dla każdego znalezionego koloru Piksela dzielę zakres barwy (0,255) przez 16, zakres nasycenia (0,100) przez 10 i zakres jasności (0,100) przez 10. Zaokrągl wynik w górę lub w dół do liczby całkowitej. Pomaga to grupować piksele w Kategorie o podobnych kolorach.

    Więc piksel o HSB 223,64,76 byłby w kategorii 14,6,8

    W każdej kategorii nadal można znaleźć dokładny kolor każdego piksela, ale w większości kategorii same są Zamknij dopasowanie kolorów do obrazu źródłowego.

    Wybierz, aby podzielić HSB na drobniejsze podziały, jeśli chcesz lepszej replikacji kolorów z kategorii. ie. podziel każde H, S, B przez 8,5,5 zamiast 16,10,10.

  4. Policz najpopularniejsze kategorie kolorów, Sortuj i wyświetlaj. Odrzucam kategorie kolorów z bardzo małą liczbą pikseli.

Uwaga: jest to naprawdę przeznaczone dla grafiki, która ma bardzo mało pikseli o identycznych wartościach kolorów (tj. obrazy z cieniami i gradienty.)

W większości przypadków strona HTML ma prawdopodobnie więcej pikseli, które dokładnie pasują do określonej wartości koloru (tj. kolor tła, kolor tekstu itp. wszystkie będą tego samego koloru, gdziekolwiek się pojawią.)

 6
Author: Gemini420,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-31 21:43:25
  1. Podziel obraz ekranu na siatkę r-wielu prostokątów, w n przez "siatkę" m, każdy z szerokością (Całkowita szerokość / n) i wysokością (Całkowita wysokość / m).

    1a. Przypisz wagę do obszarów o wysokim profilu, takich jak lewy obszar środkowy.

    1b. dla każdego prostokąta Przypisz piksele do przestrzeni (kolor,frequency )

  2. Dla każdego prostokąta R, rozkład częstotliwości f_R i waga w_r:

    2A. Określ i -kolor schematu (np. i = 1 kolor tła) poprzez skanowanie "top frequency", "second frequency" (tj. f_R[i,:]) dla każdego bloku.

    2b. dla każdego i , umieść go w tabeli wyników, ( color_i,score) gdzie score = f_R [i ," frequency"] * w_r

    2c. najlepszym strzelcem dla każdego i będzie i-kolor schematu.

Teoretycznie, jeśli masz dużo "niebieski na białym" lub " czerwony na czarnym", należy uzyskać biały podstawowy, niebieski wtórny, lub czarny podstawowy, czerwony wtórny, na przykład.

Dla koloru tekstu, albo oprzeć go bezpośrednio na obliczeniu off koloru tła, lub wybrać kolor wtórny, a jeśli różnica V HSV jest zbyt niska, bazuje kolor off obliczonego koloru schematu, ale zwiększyć wartość V.

PseudoCode:

float[][] weights = 
    { { 1.0, 3.0, 5.0, 5.0, 3.0, 1.0, 1.0, 1.0, 1.0 },
      { 2.0, 6.0, 7.0, 7.0, 6.0, 2.0, 3.0, 3.0, 2.0 },
      { 2.0, 8.0, 9.0, 9.0, 7.0, 3.0, 6.0, 6.0, 3.0 },
      { 2.0, 8.0, 9.0, 9.0, 7.0, 2.0, 3.0, 3.0, 2.0 },
      { 2.0, 7.0, 9.0, 9.0, 7.0, 2.0, 1.0, 1.0, 1.0 },
      { 2.0, 6.0, 7.0, 7.0, 6.0, 2.0, 3.0, 3.0, 1.0 },
      { 1.0, 3.0, 5.0, 5.0, 3.0, 2.0, 6.0, 6.0, 2.0 },
      { 1.0, 1.0, 2.0, 2.0, 1.0, 2.0, 6.0, 6.0, 2.0 },
      { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 3.0, 3.0, 1.0 } };

// Leave the following implementations to the imagination:
void DivideImageIntoRegions( Image originalImage, out Image[][] regions );
void GetNthMostCommonColorInRegion( Image region, int n, out Color color );
TKey FindMaximum<TKey, TValue>( Map<TKey, TValue> map );

// The method:
Color[] GetPrimaryScheme( Image image, int ncolors, int M = 9, int N = 9 )
{
    Color[] scheme = new Color[ncolors];
    Image[][] regions = new Image[M][N];

    DivideImageIntoRegions( image, regions );

    for( int i = 0; i < ncolors; i++ )
    {
        Map<Color, float> colorScores = new Map<Color, float>();

        for( int m = 0; m < M; m++ )
        for( int n = 0; n < N; n++ )
        {
            Color theColor;
            GetNthMostCommonColorInRegion( region, i, theColor );

            if( colorScores[theColor] == null )
            { colorScores[theColor] = 0; }

            colorScores[theColor] += weights[m][n];
        }

        scheme[i] = FindMaximum( colorScores );
    }

    return scheme;
}

Patrząc na powyższe, jest jasne, że jeśli istnieje region o małej zmienności, będzie miał ten sam drugi najczęściej spotykany kolor, co najczęściej spotykany kolor. Aby dopasować, drugim najczęściej spotykanym kolorem w takim przypadku może być null, przed którym można się uchronić:

            if( theColor != null )
                continue;

            if( colorScores[theColor] == null )
            { colorScores[theColor] = 0; }

            colorScores[theColor] += weights[m][n];
        }
 5
Author: maxwellb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-15 05:44:32

Nazwa pożądanego typu algorytmu to kwantyzacja kolorów.

Niestety nie mam kodu źródłowego dostępnego dla ciebie, ale jestem pewien, że wyszukiwarka Google może coś znaleźć.

W szczególności, Artykuł Dr Dobb w czasopiśmie na ten temat wydaje się obiecujący.

 4
Author: Lasse Vågsæther Karlsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 20:32:45

Podobne do rozwiązania McWafflestix, szczegóły trzeba będzie poprawić, ale moje ogólne podejście byłoby...

(zgadzam się, że HSV jest właściwą przestrzenią)

  1. Chwyć histogram obrazu, przefiltruj go, aby wygładzić szum i znajdź najwyższy wynik, w którym V i S znajdują się w (prawdopodobnie dynamicznej) gamie prawdopodobnych kolorów "tematycznych". Czerwony ptak na błękitnym niebie będzie wymagał, abyśmy byli wystarczająco mądrzy, aby nie opierać naszego planu na niebieskim, ale na czerwonym. Może to wymagać pewnych domysłów jeśli chodzi o kompozycję zdjęć, jak analiza "wyśrodkowana w kadrze" i "reguła trzech" może dać prawdopodobieństwo, że kolor jest istotny. Niezależnie od tego, to jest nasz podstawowy kolor.

  2. Wzdłuż linii Kuler Oblicz kolory, które uzupełniają bazę, poruszając się po kole kolorów. Dodatkowe punkty za obliczony komplement, jeśli pojawił się również w widocznym miejscu w histogramie z kroku 1.

  3. Użyj koloru bazowego i obliczonych komplementów, aby uzyskać przyjemny dodatek kolory, np. jaśniejsze i ciemniejsze wersje każdego, mniej lub bardziej nasycone itp.

 2
Author: Trueblood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 20:47:11

Istnieje już wiele dobrych sugestii, jak znaleźć podstawowe kolory i chciałbym spróbować podobnych podejść. Aby znaleźć kolor tekstu, mam inną sugestię.

Oblicz histogram dla każdej linii obrazu od góry do dołu. Za każdym razem, gdy dotrzesz do linii podstawowej linii, powinien nastąpić silny spadek częstotliwości koloru tekstu. Częstotliwość pozostanie niska, dopóki nie osiągniesz wielkich liter następnego wiersza po drugim kroku, gdy osiągniesz małe litery.

Jeśli jest inny silny szczyt, który staje się jeszcze większy po uderzeniu w linię podstawową, znalazłeś kolor tła. Gradientowe tło wygładzi ten szczyt, a zmiany pików - po wejściu lub wyjściu z nowej linii - zostaną wygładzone przez antyaliasing.

 2
Author: Daniel Brückner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 22:22:25

Trochę się na to spóźniłem, ale zaimplementowałbym mapę Kohonena (http://en.wikipedia.org/wiki/Self-organizing_map) w przestrzeni barw 3d. Liczba punktów na mapie będzie liczbą różnych kolorów, które chcesz dla palety, a następnie trenować mapę za pomocą wszystkich pikseli z obrazu. Sam tego nie próbowałem, ale jestem pewien, że ktoś inny już o tym pomyślał.

 1
Author: Nick Donnelly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-17 13:31:31

Poniżej kilka sugestii i dyskusji wokół różnych podejść do generowania schematu kolorów z obrazu:

Najpierw umieść / narysuj piksele w jakiejś przestrzeni kolorów. Może to być RGB, HSL lub inna przestrzeń kolorów. Następnie możesz użyć jednego z poniższych schematów kolorów:

  1. Tworzenie histogramu przestrzeni kolorów - polega to na podzieleniu przestrzeni na siatkę i zliczeniu pikseli w każdej komórce siatki. Wybierz górne N komórki (histogram wiader) z największą liczbą pikseli i średnią pikseli w każdym, Aby uzyskać kolor na komórkę. To może być twój schemat kolorów.

  2. Median Cut lub inna technika partycjonowania przestrzeni - jest to niezła poprawa w stosunku do #1, ponieważ podzieli przestrzeń patrząc na dane.

  3. klastrowanie pikseli - klastrowanie pikseli w grupy przy użyciu jednej z wielu technik klastrowania (k-means, mean-shift, itp.). Następnie uśrednić piksele w każdej grupie, aby wygenerować schemat kolorów.

Napisałem bardziej szczegółowy post na temat trzech powyższych podejść tutaj

Napisałem również interaktywną aplikację internetową , która pozwala załadować obraz i utworzyć wygenerować paletę kolorów za pomocą jednego z powyższych trzech podejść. Kod do niego znajdziesz na github

 1
Author: mattnedrich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-07 20:34:35

Uśredniaj odcień, nasycenie i jasność oddzielnie, zachowując wartości min / max.

Zablokuj docelowy odcień wszystkich kolorów do średniej i Interpoluj nasycenie i jasność dla punktów x między granicami. Powinno to zwrócić schemat z kolorowym odlewem takim samym jak na zdjęciu, ale z prostą odmianą. Może nawet będziesz wyglądać jak jabłko.

Mam nadzieję, że nie dostaniesz 3 odcieni psi rzygać.

 0
Author: Hans Malherbe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 20:44:52