Napisz program, który pobiera prawdziwy obraz RGB I , maksymalną liczbę linii do narysowania L oraz minimalną długość m i maksymalną długość M każdej linii. Wyjście obraz O , który wygląda jak najbardziej jak I i jest sporządzony za pomocą L lub mniej prostych linii, z których każdy ma długość od euklidesową m i M .
Każda linia musi mieć jeden jednolity kolor, mieć oba punkty końcowe w granicach O i być narysowana przy użyciu algorytmu linii Bresenhama (co większość bibliotek graficznych już dla ciebie zrobi). Pojedyncze linie mogą mieć grubość tylko 1 piksela.
Wszystkie linie, nawet te o długości 0, powinny zajmować co najmniej jeden piksel. Linie mogą być rysowane jeden na drugim.
Przed narysowaniem linii możesz zainicjować tło litery O dowolnym kolorem (zależnym od I ).
Detale
- O powinien mieć takie same wymiary jak ja .
- L zawsze będzie nieujemną liczbą całkowitą. To może być większy niż obszar I .
- m i M są nieujemnymi liczb zmiennoprzecinkowych o K > = m . Odległość między dwoma pikselami to odległość euklidesowa między ich środkami. Jeśli ta odległość jest mniejsza niż m lub większa niż M , linia między tymi pikselami jest niedozwolona.
- Linie nie powinny być antyializowane.
- Nie należy używać krycia i alfa.
- Twój program nie powinien zająć więcej niż godzinę, aby uruchomić się na przyzwoitym nowoczesnym komputerze na obrazach o mniej niż milion pikseli i L mniej niż 10.000.
Testuj obrazy
Powinieneś oczywiście pokazać nam swoje najdokładniejsze lub najciekawsze obrazy wyjściowe (które, jak się spodziewam, wystąpią, gdy L będzie między 5% a 25% liczby pikseli w I , a m i M są około jednej dziesiątej przekątnej).
Oto kilka zdjęć testowych (kliknij, aby zobaczyć oryginały). Możesz także opublikować własne.
Prostsze obrazy:
To konkurs popularności. Zwycięskie zgłoszenie wygrywa.
Notatki
- Pomocne może być pozwolenie na wyprowadzenie L z procentu całkowitej liczby pikseli w I, a także wartości bezwzględnej. np.
>>> imageliner I=img.png L=50% m=10 M=20
byłoby to to samo,>>> imageliner I=img.png L=32 m=10 M=20
jakby toimg.png
był obraz 8 na 8 pikseli. Coś podobnego można zrobić dla m i M . Nie jest to wymagane. - Ponieważ linie nie może przejść poza boiskiem, jak najdłuższej linii będzie przekątnej długości I . Posiadanie M wyższego niż to nie powinno jednak niczego łamać.
- Oczywiście, jeśli m wynosi 0, a L jest większa lub równa liczbie pikseli w I , O może być identyczne z I , mając długość 0 „linii” w każdym miejscu piksela. To zachowanie nie jest wymagane.
- Prawdopodobnie odtworzenie kształtu I jest ważniejsze niż odtworzenie koloru. Możesz zajrzeć do wykrywania krawędzi .
źródło
Odpowiedzi:
C ++ - nieco losowe linie, a potem trochę
Najpierw kilka losowych linii
Pierwszy krok algorytmu losowo generuje linie, przyjmuje dla obrazu docelowego średnią liczbę pikseli wzdłuż tego, a następnie oblicza, czy zsumowany kwadrat odległości rgb wszystkich pikseli byłby mniejszy, gdybyśmy namalowali nową linię (i tylko go pomaluj, jeśli jest). Nowy kolor linii dla tego jest wybierany jako średnia kanałowa wartości rgb, z losowym dodawaniem -15 / + 15.
Rzeczy, które zauważyłem i które wpłynęły na wdrożenie:
Eksperymentowałem z niektórymi liczbami, wybrałem
L=0.3*pixel_count(I)
i wyszedłemm=10
iM=50
. Będzie produkować ładne wyniki zaczynając od około0.25
aby0.26
do liczby linii, ale wybrałem 0,3 mieć więcej miejsca dla dokładnych szczegółów.W przypadku pełnowymiarowego obrazu złotej bramy spowodowało to malowanie 235929 linii (co zajęło tutaj aż 13 sekund). Pamiętaj, że wszystkie obrazy tutaj są wyświetlane w zmniejszonym rozmiarze i musisz je otworzyć w nowej karcie / pobrać je, aby wyświetlić pełną rozdzielczość.
Usuń niegodne
Następny krok jest dość drogi (dla 235 tys. Linii zajęło to około godziny, ale powinno to być w granicach „godziny dla 10 tys. Linii na 1 megapiksel”), ale jest to również nieco zaskakujące. Przechodzę przez wszystkie wcześniej malowane linie i usuwam te, które nie poprawiają obrazu. To pozostawia mnie w tym biegu z tylko 97347 liniami, które tworzą następujący obraz:
Prawdopodobnie trzeba je pobrać i porównać w odpowiedniej przeglądarce obrazów, aby wykryć większość różnic.
i zacznij od nowa
Teraz mam wiele linii, które mogę ponownie pomalować, aby mieć w sumie 235929. Niewiele do powiedzenia, więc oto obraz:
krótka analiza
Cała procedura wydaje się działać jak filtr rozmywający, wrażliwy na lokalny kontrast i rozmiary obiektów. Ciekawe jest również to, gdzie są malowane linie, więc program też je rejestruje (dla każdej linii kolor pikseli będzie o jeden stopień bielszy, na końcu kontrast zostanie zmaksymalizowany). Oto odpowiadające trzy powyżej kolorowe.
animacje
A ponieważ wszyscy uwielbiamy animacje, oto kilka animowanych gifów z całego procesu tworzenia mniejszego obrazu złotej bramy. Zauważ, że istnieje znaczące dithering z powodu formatu gif (a ponieważ twórcy formatów plików animacji w prawdziwych kolorach i producenci przeglądarek toczą wojnę o swoje ego, nie ma standardowego formatu dla animacji w prawdziwych kolorach, w przeciwnym razie mógłbym dodać plik .mng lub podobny ).
Trochę więcej
Zgodnie z życzeniem, oto niektóre wyniki innych obrazów (ponownie może być konieczne otwarcie ich w nowej karcie, aby nie skalować ich w dół)
Przyszłe myśli
Zabawa kodem może dać ciekawe odmiany.
Kod
To tylko dwie główne przydatne funkcje, cały kod nie mieści się tutaj i można je znaleźć na stronie http://ideone.com/Z2P6Ls
Te
bmp
zajęciaraw
iraw_line
funkcja zrobić dostępu pikseli i linii odpowiednio w obiekcie, który można zapisać do formatu bmp (To tylko niektóre Hack leżące wokół i pomyślałem, że czyni to nieco niezależny od jakiejkolwiek biblioteki).Format pliku wejściowego to PPM
źródło
Java - losowe linie
Bardzo podstawowe rozwiązanie, które rysuje losowe linie i oblicza dla nich średni kolor obrazu źródłowego. Kolor tła jest ustawiony na średni kolor źródłowy.
L = 5000, m = 10, M = 50
L = 10000, m = 10, M = 50
EDYTOWAĆ
Dodałem algorytm genetyczny, który obsługuje populację linii. W każdym pokoleniu zachowujemy tylko 50% najlepszych linii, usuwamy pozostałe i generujemy losowo nowe. Kryteria utrzymania linii są:
Ku mojemu wielkiemu rozczarowaniu algorytm tak naprawdę nie poprawia jakości obrazu :-( po prostu linie stają się bardziej równoległe.
Pierwsza generacja (5000 linii)
Dziesiąta generacja (5000 linii)
Zabawa z parametrami
źródło
C - linie proste
Podstawowe podejście w C, które działa na plikach ppm. Algorytm próbuje umieścić pionowe linie o optymalnej długości, aby wypełnić wszystkie piksele. Kolor tła i kolory linii są obliczane jako średnia wartość oryginalnego obrazu (mediana każdego kanału kolorów):
L = 5000, m = 10, M = 50
L = 5000, m = 10, M = 50
L = 100000, m = 10, M = 50
źródło
Python 3 - oparty na „nieco losowych liniach, a potem niektórych” oraz wykrywaniu krawędzi sobel.
kod teoretycznie może działać wiecznie (więc mogę uruchomić go dla zabawy), ale rejestruje jego postęp, więc wszystkie zdjęcia są robione od 1 do 10 minut.
Najpierw odczytuje obraz, a następnie używa detekcji krawędzi sobel, aby znaleźć kąt wszystkich krawędzi, aby mieć pewność, że linie nie przekroczą innego koloru. Po ustawieniu linii o losowej długości w ciągu (lengthmin, lengthmax), następnie sprawdza, czy przyczynia się do ogólnego obrazu. Podczas gdy mniejsze linie są lepsze, ustawiam długość linii na 10-50.
źródło