Wyobraź sobie ciągłą dwuwymiarową ścieżkę, która może tylko skręcać w lewo, w prawo lub iść prosto, nie może się przecinać i musi wypełniać prostokątną siatkę, taką jak siatka pikseli na obrazie. Nazwiemy tę ścieżkę wężem .
Ten powiększony przykład pokazuje ścieżkę węża na siatce 10 × 4, która zaczyna się na czerwono i zwiększa odcień o około 2% na każdym kroku, aż stanie się fioletowa. (Czarne linie mają jedynie podkreślać kierunek, w którym się porusza.)
Cel
Celem tego konkursu popularności jest napisanie algorytmu, który próbuje odtworzyć dany obraz za pomocą jednego węża, którego kolor zmienia się ciągle w niewielkich ilościach.
Twój program musi przyjmować obraz w prawdziwych kolorach o dowolnym rozmiarze, a także wartość zmiennoprzecinkową od 0 do 1 włącznie, z tolerancją .
Tolerancja określa maksymalną wielkość, którą kolor węża może zmieniać w każdym kroku wielkości piksela. Zdefiniujemy odległość między dwoma kolorami RGB jako odległość euklidesową między dwoma punktami RGB, gdy są ustawione na kostce kolorów RGB . Odległość zostanie następnie znormalizowana, więc maksymalna odległość wynosi 1, a minimalna odległość wynosi 0.
Pseudokod odległości kolorów: (Zakłada, że wszystkie wartości wejściowe są liczbami całkowitymi w zakresie [0, 255]
; dane wyjściowe są znormalizowane).
function ColorDistance(r1, g1, b1, r2, g2, b2)
d = sqrt((r2 - r1)^2 + (g2 - g1)^2 + (b2 - b1)^2)
return d / (255 * sqrt(3))
Jeśli wynik wywołania tej funkcji na bieżącym kolorze węża i innym kolorze jest większy niż podana tolerancja, wąż może nie zmienić się na inny kolor.
Jeśli wolisz, możesz użyć innej funkcji odległości kolorów. Musi to być coś dokładnego i dobrze udokumentowanego, takiego jak wymienione na stronie http://en.wikipedia.org/wiki/Color_difference . Musisz również znormalizować go, aby był w środku [0, 1]
, tj. Maksymalna możliwa odległość musi wynosić 1, a minimalna musi wynosić 0. Powiedz nam w odpowiedzi, jeśli używasz innej miary odległości.
Testuj obrazy
Powinieneś oczywiście opublikować swoje zdjęcia wyjściowe (a nawet animacje węża rosnącego, jeśli chcesz). Sugeruję opublikowanie różnych tych zdjęć przy użyciu różnych niskich tolerancji (może około 0,005 do 0,03).
Wygraj kryteria
Jak wspomniano, jest to konkurs popularności. Najwyższa głosowana odpowiedź wygra. Odpowiedzi, które zapewniają najdokładniejsze i najbardziej estetyczne przedstawienie „ścieżki węża” obrazów wejściowych, powinny zostać poddane pod głosowanie.
Każdy użytkownik, który okaże się, że złośliwie przesyła obrazy, które nie są rzeczywistymi wężami, zostanie zdyskwalifikowany na zawsze.
Uwagi
- Można użyć tylko jednej ścieżki węża i musi ona całkowicie wypełnić obraz bez dwukrotnego dotknięcia tego samego piksela.
- Wąż może zaczynać się i kończyć w dowolnym miejscu obrazu.
- Wąż może zaczynać się w dowolnym kolorze.
- Wąż musi pozostać w granicach obrazu. Granice nie są cykliczne.
- Wąż nie może poruszać się po przekątnej ani więcej niż o jeden piksel na raz.
źródło
Odpowiedzi:
Pyton
Generuję ścieżkę dynamiczną, aby zminimalizować zmiany kolorów podczas podróży węża. Oto kilka zdjęć:
tolerancja = 0,01
Cykliczne ścieżki kolorów dla powyższych obrazów (od niebieskiego do czerwonego, coraz bardziej zielone w miarę powtarzania):
Ścieżka jest generowana, zaczynając od ścieżki początkowej, a następnie dodając do niej 2x2 pętle, aż obraz zostanie wypełniony. Zaletą tej metody jest to, że pętle można dodawać w dowolnym miejscu na ścieżce, dzięki czemu nie można pomalować się w kącie i mieć więcej swobody w budowaniu pożądanej ścieżki. Śledzę możliwe pętle przylegające do bieżącej ścieżki i przechowuję je w kupie, ważonej zmianą koloru wzdłuż pętli. Następnie zrywam pętlę z najmniejszą zmianą koloru i dodaję ją do ścieżki i powtarzam, aż obraz się zapełni.
Właściwie śledzę same pętle („DetourBlock” w kodzie), a następnie rekonstruuję ścieżkę; to był błąd, ponieważ istnieją specjalne przypadki nieparzystej szerokości / wysokości i spędziłem kilka godzin debugując metodę rekonstrukcji. No cóż.
Metryka generowania ścieżki wymaga dostrajania. Mam też pomysł na lepsze kolorowanie, ale pomyślałem, że najpierw to wyjdę, ponieważ działa całkiem dobrze. Z wyjątkiem tego, który wydaje się lepszy na niektórych stałych ścieżkach:
Oto kod Pythona z przeprosinami za moje okropne nawyki programistyczne:
I jeszcze kilka zdjęć przy bardzo niskiej tolerancji 0,001 :
A także świetna ścieżka fali, ponieważ jest schludna:
EDYTOWAĆ
Generowanie ścieżki wydaje się lepsze przy minimalizowaniu odległości między średnimi kolorami sąsiednich bloków, niż minimalizowaniu sumy odległości kolorów między sąsiadującymi pikselami. Okazuje się również, że można uśrednić kolory dowolnych dwóch ścieżek węża zgodnych z tolerancją i otrzymać inną ścieżkę węża zgodną z tolerancją. Przemierzam ścieżkę w obie strony i uśredniam je, co wygładza wiele artefaktów. Zombie Lena i Scary Hands Mona wyglądają znacznie lepiej. Ostateczne wersje:
Tolerancja 0,01 :
Tolerancja 0,001 :
źródło
Jawa
Mój program generuje ścieżkę węża dla danej szerokości i wysokości, używając algorytmu podobnego do tego, który generuje krzywą Hilberta.
(mała gra: na powyższym obrazku wąż zaczyna się w lewym górnym rogu. Czy możesz znaleźć, gdzie kończy się? Powodzenia :)
Oto wyniki dla różnych wartości tolerancji:
Tolerancja = 0,01
Tolerancja = 0,05
Tolerancja = 0,1
Tolerancja = 0,01
Z blokami pikseli 4x4 i widoczną ścieżką
Obliczanie ścieżki węża
Ścieżka węża jest przechowywana w podwójnej tablicy liczb całkowitych. Wąż zawsze wchodzi w siatkę w lewym górnym rogu. Istnieją 4 podstawowe operacje, które mój program może wykonać na danej ścieżce węża:
utwórz nową ścieżkę węża dla siatki o szerokości 1 lub wysokości 1. Ścieżka jest prostą linią, która biegnie od lewej do prawej lub od góry do dołu, w zależności od przypadku.
zwiększ wysokość siatki, dodając u góry ścieżkę węża od lewej do prawej, a następnie odbijając siatkę (wąż musi zawsze wchodzić do siatki w lewym górnym rogu)
zwiększ szerokość siatki, dodając po lewej stronie ścieżkę węża od góry do dołu, a następnie odwracając siatkę (wąż musi zawsze wchodzić do siatki w lewym górnym rogu)
podwoić wymiar siatki za pomocą algorytmu „stylu Hilberta” (patrz opis poniżej)
Korzystając z szeregu tych operacji atomowych, program jest w stanie wygenerować ścieżkę węża o dowolnym rozmiarze.
Poniższy kod oblicza (w odwrotnej kolejności), które operacje będą potrzebne do uzyskania danej szerokości i wysokości. Po obliczeniu akcje są wykonywane jeden po drugim, dopóki nie otrzymamy ścieżki węża o oczekiwanym rozmiarze.
Podwojenie rozmiaru ścieżki węża:
Algorytm, który podwaja rozmiar działa w następujący sposób:
Rozważ ten węzeł, który jest powiązany z PRAWYM i DOLNYM. Chcę podwoić jego rozmiar.
Istnieją 2 sposoby, aby podwoić jego rozmiar i zachować te same wyjścia (prawy i dolny):
lub
Aby określić, który wybrać, muszę dla każdego kierunku węzła obsługiwać wartość „przesunięcia”, wskazując, czy drzwi wyjściowe są przesunięte w lewo / prawo czy w górę / w dół. Podążam ścieżką, tak jak zrobiłby to wąż, i aktualizuję wartość przesunięcia wzdłuż ścieżki. Wartość przesunięcia określa jednoznacznie, którego rozwiniętego bloku muszę użyć w następnym kroku.
źródło
Pyton
Oto bardzo prosty algorytm na początek. Zaczyna się w lewym górnym rogu obrazu i spiralnie obraca się do wewnątrz, dzięki czemu kolor jest możliwie najbliższy kolorowi następnego piksela, pozostając w granicach tolerancji.
Uruchomienie większych obrazów zajmuje minutę lub dwie, ale jestem pewien, że spiralna logika mogłaby zostać znacznie zoptymalizowana.
Wyniki
Są interesujące, ale nie wspaniałe. O dziwo, tolerancja powyżej 0,1 daje całkiem dokładne wyniki.
Wielka Fala przy tolerancji 0,03:
Mona Lisa przy tolerancji 0,02:
Lena z tolerancją 0,03, następnie 0,01, następnie 0,005, a następnie 0,003:
Różne rzeczy z tolerancją 0,1, następnie 0,07, następnie 0,04, a następnie 0,01:
źródło
Kobra
Wypełnia obraz wężem takim jak:
Pozwala to na znacznie szybsze dopasowanie kolorów niż tylko linie w naprzemiennych kierunkach, ale nie staje się tak blokowe, jak w przypadku wersji 3-szerokiej.
Nawet przy bardzo niskich tolerancjach krawędzie obrazu są nadal widoczne (chociaż przy utracie szczegółów w mniejszych rozdzielczościach).
0,01
0,1
0,01
0,01
0,1
0,03
0,005
źródło
DO#
Wąż zaczyna się od lewego górnego piksela w kolorze białym i zmienia się od lewej do prawej, a następnie od prawej do lewej w dół obrazu.
Wynikowa tolerancja obrazu = 0,1
źródło