Otrzymujesz prawdziwy kolorowy obraz. Twoim zadaniem jest wygenerowanie wersji tego obrazu, który wygląda tak, jakby został namalowany farbą po liczbach (aktywność dzieci, a nie nonogramy). Wraz z obrazem podane są dwa parametry: P , maksymalny rozmiar palety kolorów (tj. Maksymalna liczba różnych kolorów do użycia) i N , maksymalna liczba komórek do użycia. Twój algorytm nie musi używać wszystkich kolorów P i komórek N , ale nie może używać więcej. Obraz wyjściowy powinien mieć takie same wymiary jak wejście.
Komórka jest zdefiniowana jako zwarty obszar pikseli, które wszystkie mają ten sam kolor. Piksele dotykające tylko w rogu nie są uważane za ciągłe. Komórki mogą mieć dziury.
Krótko mówiąc, przybliżasz obraz wejściowy tylko za pomocą N płaskich cieniowanych / jednolitych obszarów i P różnych kolorów.
Aby wizualizować parametry, oto bardzo prosty przykład (brak konkretnego obrazu wejściowego; pokazanie moich szalonych umiejętności malowania). Poniższy obraz ma P = 6 i N = 11 :
Oto kilka zdjęć, na których można przetestować algorytm (głównie nasi podejrzani). Kliknij zdjęcia, aby zobaczyć większe wersje.
Podaj garść wyników dla różnych parametrów. Jeśli chcesz pokazać dużą liczbę wyników, możesz utworzyć galerię na imgur.com , aby zachować rozsądny rozmiar odpowiedzi. Ewentualnie umieść miniatury w swoim poście i umieść w nich linki do większych zdjęć, tak jak zrobiłem powyżej. Ponadto, jeśli znajdziesz coś fajnego, skorzystaj z innych zdjęć testowych.
Zakładam, że parametry około N ≥ 500 , P ~ 30 byłyby podobne do rzeczywistych szablonów malowania według numerów.
To konkurs popularności, więc wygrywa odpowiedź z największą liczbą głosów netto. Zachęca się wyborców do oceniania odpowiedzi według
- jak dobrze przybliżone są oryginalne obrazy.
- jak dobrze algorytm działa na różnych rodzajach obrazów (obrazy są zazwyczaj łatwiejsze niż zdjęcia).
- jak dobrze algorytm działa z bardzo restrykcyjnymi parametrami.
- jak wyglądają organiczne / gładkie kształty komórek.
Użyję następującego skryptu Mathematica, aby sprawdzić poprawność wyników:
image = <pastedimagehere> // ImageData;
palette = Union[Join @@ image];
Print["P = ", Length@palette];
grid = GridGraph[Reverse@Most@Dimensions@image];
image = Flatten[image /. Thread[palette -> Range@Length@palette]];
Print["N = ",
Length@ConnectedComponents[
Graph[Cases[EdgeList[grid],
m_ <-> n_ /; image[[m]] == image[[n]]]]]]
Sp3000 był na tyle miły, że napisał weryfikator w Pythonie 2 za pomocą PIL, który znajduje się w tym pastebinie .
źródło
Odpowiedzi:
Python 2 z PIL ( galeria )
Czas aktualizacji! Ta aktualizacja zawiera prosty algorytm wygładzania, aby obrazy były mniej rozmyte. Jeśli zaktualizuję ponownie, będę musiał przerobić sporą część mojego kodu, ponieważ robi się niechlujny i mam problem z 2 i więcej.
Stworzyłem także kolory wagowe k-średnich w oparciu o rozmiary komórek, które tracą detale dla bardziej restrykcyjnych parametrów (np. Środek mgławicy i widły American Gothic), ale sprawiają, że ogólny wybór kolorów jest ostrzejszy i ładniejszy. Co ciekawe, traci on całe tło dla sfer raytraced dla P = 5.
Podsumowanie algorytmu:
Czas przetwarzania każdego obrazu w dużej mierze zależy od jego wielkości i złożoności, przy czasach testowych od 20 sekund do 7 minut.
Ponieważ algorytm wykorzystuje randomizację (np. Scalanie, k-średnie), możesz uzyskać różne wyniki dla różnych przebiegów. Oto porównanie dwóch przebiegów obrazu niedźwiedzia, przy N = 50 i P = 10:
Uwaga: Wszystkie poniższe zdjęcia są linkami. Większość z tych obrazów pochodzi od pierwszego uruchomienia, ale jeśli nie podobało mi się wyjście, pozwoliłem sobie na trzy próby uczciwości.
N = 50, P = 10
N = 500, P = 30
Ale jestem dość leniwy, jeśli chodzi o malowanie kolorami, więc dla zabawy ...
N = 20, P = 5
Dodatkowo zabawnie jest zobaczyć, co się stanie, gdy spróbujesz wycisnąć 1 milion kolorów na N = 500, P = 30:
Oto krok po kroku algorytm dla obrazu podwodnego o N = 500 i P = 30, w animowanej formie GIF:
Zrobiłem też galerię dla poprzednich wersji algorytmu tutaj . Oto niektóre z moich ulubionych z ostatniej wersji (od kiedy mgławica miała więcej gwiazd, a niedźwiedź wyglądał na bardziej puszystego):
źródło
im = im.convert("RGB")
jest potrzebny do niektórych zdjęć. Włożę to po tym, jak trochę zrestrukturyzuję kod.Python 2 z PIL
Również rozwiązanie w języku Python i prawdopodobnie bardzo dużo pracy w toku:
Algorytm stosuje inne podejście niż SP3000, zaczynając od kolorów najpierw:
Znajdź paletę kolorów P za pomocą k-oznacza grupowania i pomaluj obraz w tej zmniejszonej palecie.
Zastosuj lekki filtr środkowy, aby pozbyć się szumu.
Zrób listę wszystkich komórek monochromatycznych i posortuj ją według rozmiaru.
Scal najmniejsze komórki z ich odpowiednimi największymi sąsiadami, aż pozostanie tylko N komórek.
Jest sporo miejsca na ulepszenia, zarówno pod względem szybkości, jak i jakości wyników. Zwłaszcza etap łączenia komórek może potrwać do wielu minut i daje dalekie od optymalnych rezultatów.
P = 5, N = 45
P = 10, N = 50
P = 4, N = 250
P = 11, N = 500
źródło
Matematyka
W tej chwili bierze to liczbę kolorów i promień Gaussa do zastosowania w filtrze Gaussa. Im większy promień, tym większe rozmycie i scalenie kolorów.
Ponieważ nie pozwala na wprowadzenie liczby komórek, nie spełnia jednego z podstawowych wymagań wyzwania.
Dane wyjściowe obejmują liczbę komórek dla każdego koloru, a także całkowitą liczbę komórek.
Aktualizacja
quantImage2
pozwala określić żądaną liczbę komórek jako dane wejściowe. Określa najlepszy promień gaussowski, przechodząc przez scenariusze z większymi promieniami, aż do znalezienia ścisłego dopasowania.quantImage2
dane wyjściowe (obraz, wymagane komórki, wykorzystane komórki, błąd, zastosowany promień gaussa).Jest jednak bardzo powolny. Aby zaoszczędzić czas, możesz zacząć od początkowego promienia, którego domyślną wartością jest 0.
Przykład, dla którego określamy liczbę komórek pożądanych w danych wyjściowych.
Przykład z prośbą o 90 komórek w 25 kolorach. Rozwiązanie zwraca 88 komórek, błąd 2%. Funkcja wybrała promień Gaussa na 55. (Dużo zniekształceń).
Przykłady, dla których dane wejściowe obejmują promień Gaussa, ale nie liczbę komórek.
25 kolorów, promień Gaussa 5 pikseli
Trzy kolory, promień 17 pikseli
Dwadzieścia kolorów, promień 17 pikseli
Zwiększyliśmy liczbę kolorów, ale nie skupiliśmy się. Zwróć uwagę na wzrost liczby komórek.
Sześć kolorów, promień 4 pikseli
Gwieździsta noc
Tylko 6 kolorów i 60 komórek. Występuje niedopasowanie kolorów w kolorach, których
showColors
używa roszczenia. (Żółty nie pojawia się wśród 5 kolorów, ale jest używany na rysunku.) Zobaczę, czy mogę to rozgryźć.źródło
showColors
zapętleniem zakresu kolorów i promieni oraz wybranie kombinacji najbliższej pożądanej liczbie komórek. Nie jestem pewien, czy mam teraz na to benzynę. Może później.Python 2 z PIL
To wciąż jest trochę w toku. Ponadto poniższy kod jest okropnym bałaganem spaghetti i nie powinien być wykorzystywany jako inspiracja. :)
Jak to działa
Program dzieli płótno na
P
regiony, z których każdy składa się z pewnej liczby komórek bez otworów. Początkowo płótno jest po prostu podzielone na przybliżone kwadraty, które są losowo przypisywane do regionów. Następnie obszary te są „zdeformowane” w procesie iteracyjnym, w którym dany piksel może zmienić swój region, jeśliTen ostatni warunek można egzekwować lokalnie, więc proces jest trochę jak automat komórkowy. W ten sposób nie musimy wykonywać żadnych poszukiwań ścieżek, co znacznie przyspiesza proces. Ponieważ jednak komórek nie można rozbić, niektóre z nich kończą się jako długie „włókna”, które graniczą z innymi komórkami i hamują ich wzrost. Aby to naprawić, istnieje proces zwany „cięciem filamentu”, który czasami rozbija komórkę w kształcie filamentu na dwie części, jeśli
N
w tym czasie jest mniej niż komórek. Komórki mogą również zniknąć, jeśli ich rozmiar wynosi 1, co powoduje miejsce na cięcia włókien.Proces kończy się, gdy żaden piksel nie ma motywacji do przełączania regionów, a następnie każdy region jest po prostu pokolorowany przez swój średni kolor. Zwykle na wyjściu pozostaną pewne włókna, co można zobaczyć w poniższych przykładach, zwłaszcza w mgławicy.
P = 30, N = 500
Więcej zdjęć później.
Niektóre interesujące właściwości mojego programu są takie, że jest on probabilistyczny, więc wyniki mogą się różnić między różnymi uruchomieniami, chyba że użyjesz oczywiście tego samego pseudolosowego ziarna. Losowość nie jest jednak istotna, chciałem tylko uniknąć przypadkowych artefaktów, które mogą wynikać ze szczególnego sposobu, w jaki Python przemierza zbiór współrzędnych lub coś podobnego. Program zwykle używa wszystkich
P
kolorów i prawie wszystkichN
komórek, a komórki nigdy nie zawierają otworów z założenia. Ponadto proces deformacji jest dość powolny. Wyprodukowanie kolorowych kulek zajęło prawie 15 minut na mojej maszynie. Z drugiej strony, włączaszGRAPHICAL_LOGGING
opcja, otrzymasz fajną serię zdjęć procesu deformacji. Zrobiłem te Mona Lisa w animację GIF (zmniejszyłem 50%, aby zmniejszyć rozmiar pliku). Jeśli przyjrzysz się uważnie jej twarzy i włosom, zobaczysz proces cięcia filamentu w akcji.źródło