Monday 4 December 2017

Ruchoma średnia jak splot


Rozmycie dla początkujących Wprowadzenie Jest to krótki samouczek dotyczący technik rozmycia dla początkujących. Kiedy uczyłem się tych rzeczy, było bardzo mało dostępnych materiałów, które były przydatne. To oczywiście nie jest prawdą - było mas materiału, ale połowa była zbyt prosta, a druga połowa zaczęła Let T być funkcją wektorową ocenianą w półotwartym przedziale. i był pełen bardzo przerażających równań wieloliniowych z tymi wielkimi symbolami sigma i rzeczami. Ten artykuł ma na celu zaradzenie temu. Mówię o różnych rodzajach rozmycia i efektach, z których można ich używać, z kodem źródłowym w Javie. Zrzeczenie się O ile wspomina się rozmycie, zawsze jest ktoś, kto mówi: "Nie jestem prawdziwym rozmyciem ruchu" lub pisze w złym tonie zielonym atramentem, narzekając, że matematyka jest wątpliwa lub że jest o wiele szybszy sposób, aby to zrobić, używając rejestrów sponglerizera na HAL. -9000. Ignoruj ​​tych ludzi. To duży temat, a ten artykuł jest przeznaczony tylko dla początkujących (z których mogę z dumą powiedzieć, że jestem jednym). Liczy się to, że osiągasz zamierzone rezultaty, a jeśli rezultaty, które chcesz osiągnąć, wymagają wątpliwej matematyki, to niech tak będzie. Jeśli rezultaty, których szukasz, wyglądają dla mnie okropnie, to dobrze, o ile wyglądają dobrze. Kolejne zastrzeżenie Kod źródłowy w Javie jest całkiem niezły, o czym mówię tutaj. Nie twierdzę, że są one zoptymalizowane w jakikolwiek sposób - Ive optował za prostotą nad prędkością wszędzie i prawdopodobnie będziesz w stanie sprawić, że większość tych rzeczy pójdzie szybciej przy odrobinie wysiłku. Możesz użyć kodu źródłowego do dowolnych celów, w tym do celów komercyjnych, ale nie ponosisz żadnej odpowiedzialności. Jeśli twoja elektrownia jądrowa lub system rakiet ulegnie awarii z powodu niewłaściwego rozmycia, to nie moja wina. Co to jest rozmycie Wszyscy wiemy, czym jest rozmycie, nie jest to, co dzieje się, gdy kamera nie jest skupiona lub pies kradnie okulary. Dzieje się tak dlatego, że to, co powinno być postrzegane, jako ostry punkt zostaje rozmazany, zwykle w kształcie dysku. Pod względem obrazu oznacza to, że każdy piksel w obrazie źródłowym zostaje rozłożony i zmieszany z otaczającymi pikselami. Innym sposobem patrzenia na to jest to, że każdy piksel w docelowym obrazie składa się z mieszaniny otaczających pikseli z obrazu źródłowego. Operacja, której potrzebujemy, nazywa się splotem. Brzmi to skomplikowanie, ale to tylko dlatego, że matematycy lubią sprawiać, że rzeczy wydają się skomplikowane, aby utrzymać atmosferę magii i utrzymać finansowanie. Cóż, jestem na nich i mogę zdradzić, że splot nie jest aż tak skomplikowany (i tak na moim poziomie) . Działa to w następujący sposób: wyobrażamy sobie przesuwanie prostokątnego szeregu liczb nad naszym obrazem. Ta tablica nazywa się jądrem splotu. Dla każdego piksela na obrazku bierzemy odpowiednie liczby z jądra i pikseli, na których się znajdują, pomnóż je razem i dodaj wszystkie wyniki razem, aby utworzyć nowy piksel. Na przykład wyobraźmy sobie, że chcemy zrobić naprawdę proste rozmycie, w którym po prostu przeciętnie ze sobą każdy piksel i jego ośmiu bezpośrednich sąsiadów. Jądro, którego potrzebujemy, to: Zauważ, że wszystkie te elementy sumują się do 1, co oznacza, że ​​nasz wynikowy obraz będzie tak samo jasny jak oryginał. Bez zbędnych ceregieli możemy zamazać obraz w Javie. Wszystkie te spory komplikacje wydają się trudne do wdrożenia, ale na szczęście Java ma wbudowany i gotowy do użycia operator, który właśnie to robi. Mówię tutaj ConvolveOp. Oto kod: Fantastyczny. Rozmazany obraz. Nie jest jednak rozmazany. Zróbmy naprawdę duże rozmycie: Hmmmmmm. Cóż, nie jest tak dobrze. Nie tylko to trwało bardzo długo, ale wynik jest nieco dziwny - wszystko wygląda, cóż, trochę kwadratowo, a co na świecie stało się na krawędziach. Po pierwsze krawędzie: ConvolveOp to nieśmiała rzecz o nazwie namby-pamby, która jest przestraszona upadku z krawędzi obrazu. Jeśli jądro zachodzi na krawędź obrazu, po prostu rezygnuje i pozostawia piksel bez zmian. Możesz to zmienić, przechodząc EDGEZEROFILL zamiast EDGENOOP, ale to jeszcze gorsze - piksele wokół krawędzi stają się ustawione na zero i skutecznie znikają. Co powinniśmy zrobić? Moglibyśmy wytrzeć obraz wokół krawędzi przed rozmyciem i przyciąć wynik, ale to po prostu uległo, a poza tym nie dowiedzielibyśmy się niczego. Zamiast tego, napisz odpowiedniego, nieustraszonego, bezsensownego operatora, który nie boi się krawędzi. Nazwijmy go ConvolveFilter, aby odróżnić go od ConvolveOp. Nie będę się zajmował szczegółami źródła w tym artykule - nie ma wystarczająco dużo czasu lub miejsca i mamy o wiele więcej filtrów do napisania, ale można pobrać lub wyświetlić źródło i powinno to być dość oczywiste. Teraz problem kwadratowości: wszystko jest kwadratowe dlatego, że to, co tu robimy, nazywa się rozmytą plamą - nasze jądro ma kształt kwadratu, jak gdyby używano aparatu z kwadratową aperturą. Nawiasem mówiąc, nie pozwól nikomu powiedzieć, że plamy w pudełku są bezużyteczne - w rzeczywistości, jeśli symulujesz cień rzucany przez kwadratowe światło, to dokładnie to, czego chcesz. W każdym razie, theyll przydaje się dalej. Kolejna rzecz: nie denerwuj się - używam terminu "rozmycie", aby odnieść się do kształtu jądra, a nie jego profilu, który zamierzam nazwać filtrem skrzynkowym. Więcej o tym później. Aby uzyskać bardziej realistyczne rozmycie, powinniśmy użyć jądra w kształcie koła. To znacznie lepiej symuluje rzeczywisty aparat. Tak jest dużo lepiej. Cóż, wróćmy do tego później, ale najpierw zamienia się dywersja z powrotem na pole. Rozwiązaliśmy problem z pikselami krawędziowymi, ale nasze rozmycie nadal trwa bardzo powoli, a sytuacja może się tylko pogorszyć. Problem polega na tym, że liczba mnożeń w splotach rośnie jako kwadrat promienia jądra. Z jądrem 100x100 zamierzano zrobić 10000 mnożeń i dodać na piksel (w przybliżeniu). Jak możemy się z tym obejść Okazuje się, że jest więcej sposobów na to, niż na to, że mam czas na napisanie, a nawet na to, żeby się przyjrzeć. Jednym ze sposobów, o których powiem krótko przed zamiataniem pod dywan, jest to, że: Możesz zrobić rozmycie w pudełku, zmniejszając obraz, zacierając go i ponownie zwiększając. Może to być dobre dla twoich celów, i powinieneś o tym pamiętać. Jednym problemem jest to, że nie animuje się bardzo dobrze, ale może nie być dla ciebie problemem. Spójrzmy jeszcze raz na rozmazane pole: okazuje się, że jest kilka naprawdę łatwych sposobów na przyspieszenie tego. Po pierwsze okazuje się, że rozmycie pudła można rozdzielić. Oznacza to, że możemy wykonać rozmycie 2D, wykonując dwie plamy 1D, raz w kierunku poziomym i raz w kierunku pionowym. Jest to znacznie szybsze niż wykonywanie rozmycia 2D, ponieważ czas ten wzrasta proporcjonalnie do rozmiaru jądra, a nie do kwadratu. Po drugie, pomyśl o oknie, które przesuwało się po obrazie. Przesuwając go od lewej do prawej, piksele pojawiają się przy prawej krawędzi i są dodawane do całości, a jednocześnie piksele opuszczają lewą krawędź i są odejmowane od całości. Wszystko, co musimy zrobić, to po prostu dodawać i odejmować piksele wchodzące i wychodzące na każdym kroku zamiast sumowania wszystkich pikseli w oknie. Musimy przechowywać tylko zestaw bieżących sum, które są szerokością lub wysokością jądra. Daje to ogromną poprawę szybkości kosztem konieczności napisania kodu. Na szczęście napisałem kod dla ciebie, więc wygrywasz cały czas. Potrzebujemy dwóch przebiegów, jeden raz, aby rozmycie w poziomie i raz w pionie. Ich kod jest oczywiście zupełnie inny. Ale poczekaj na sztuczkę, którą możemy zrobić, co pozwala nam napisać kod raz. Jeśli piszemy funkcję zamazywania, która powoduje rozmycie w poziomie, ale zapisuje obraz wyjściowy, możemy po prostu wywołać ją dwukrotnie. Pierwsze przejście rozmazuje się w poziomie i transponuje, drugie przejście robi to samo, ale ponieważ obraz jest teraz transponowany, naprawdę robi pionowe rozmycie. Druga transpozycja sprawia, że ​​obraz jest znowu właściwy, a voila - bardzo szybkie rozmycie. Wypróbuj w tym aplecie: A oto kod źródłowy. Być może zauważyliście, że do tej pory używaliśmy tylko promienia liczby całkowitej, co ułatwia ustalenie indeksów tablicy dla rozmycia. Możemy rozszerzyć tę technikę, aby zamazywać subpiksele (to jest nieintegralny promień) po prostu poprzez liniową interpolację między wartościami macierzy. Mój kod źródłowy nie robi tego, ale jest łatwy do dodania. Rozmycie gaussowskie Teraz nadszedł czas, aby rozwiązać problem prędkości i kwadratowych problemów z rozmyciem w tym samym czasie. Aby pozbyć się kwadratowego spojrzenia na rozmycie, potrzebujemy okrągłego jądra. Niestety, sztuczka, której używaliśmy do rozmywania pudełek, nie działa z okręgiem, ale jest luka: jeśli jądro ma właściwy profil - profil Gaussa - możemy wykonać rozmycie 2D, wykonując dwie rozmycia 1D, tak jak zrobiliśmy to z pole rozmycie. Nie jest tak szybki, ponieważ sztuczka z przesuwanym oknem nie działa, ale wciąż jest o wiele szybsza niż w przypadku splotu 2D. Potrzebujemy profilu, który znamy w kształcie dzwonu lub krzywej Gaussa, o którym słyszeliście: Oto kod, który tworzy jądro Gaussa 1D dla danego promienia. Wszystko, co musimy zrobić, to zastosować to dwukrotnie, raz w poziomie i raz w pionie. Jako bonus Ive zawinął go w filtr GaussianFilter, aby był łatwy w użyciu. Właśnie dlatego rozmycie gaussowskie występuje w każdym pakiecie graficznym - jest znacznie szybsze niż inne rodzaje rozmycia. Jedynym problemem jest to, że nie jest to bardzo realistyczne, jeśli chodzi o symulowanie soczewek kamery, ale o tym później. Jeśli chcesz robić takie rzeczy, jak symulowanie cieni, rozmycie gaussowskie, a nawet rozmycie pudła może być w porządku. Jest miejsce na wszystkie te efekty - tylko dlatego, że nie są realistyczne, nie oznacza, że ​​nie są przydatne. Rozmycie gaussowskie jest znacznie szybsze, ale nie jest tak szybkie, jak nasze rozmycie pudła, które wcześniej zrobiliśmy. Gdyby tylko był jakiś sposób na połączenie tych dwóch. Wyobrażam sobie, że już zgadłeś, że może być jeden, więc nie będę trzymał suspensu dłużej: Jeśli wykonasz wiele rozmytych pudełek, wynik będzie wyglądał coraz bardziej jak rozmycie Gaussa. W rzeczywistości możesz udowodnić to matematycznie, jeśli masz wolną chwilę (ale nie mów mi, jak - nie jestem zainteresowany). W praktyce od 3 do 5 pudełkowatych rozmazów wygląda całkiem nieźle. Nie wierz mi na słowo: Aplet z rozmytym okienkiem powyżej ma suwak Iteracji, więc możesz go wypróbować sam. Kanały alfa Szybka dywersja tutaj, aby omówić problem, który często pojawia się: Wyobraź sobie, że chcesz zamazać kształt, który jest na przezroczystym tle. Masz pusty obraz i narysujesz na nim kształt, a następnie zamazuje obraz. Trzymaj się - dlaczego niewyraźny bit wygląda zbyt ciemno Powód jest taki, że zamazaliśmy każdy kanał osobno, ale gdzie kanał alfa jest zerowy (przezroczyste bity), kanały czerwony, zielony i niebieski są zerowe lub czarne. Kiedy robisz rozmycie, czerń miesza się z nieprzezroczystymi bitami i dostajesz ciemny cień. Rozwiązaniem jest przedwczesne powiększenie obrazu alfa przed rozmyciem i niepoprawnie później. Oczywiście, jeśli twoje zdjęcia są już wstępnie pomnożone, jesteś gotowy. Motion Blur Czas na zmianę kierunku. Do tej pory mówiliśmy tylko o jednolitych rozmycie, ale są też inne typy. Poruszenie to rozmycie, które pojawia się, gdy obiekt (lub aparat) porusza się w czasie ekspozycji. Obraz rozmywa się wzdłuż widocznej ścieżki obiektu. Mowa tu o symulowaniu rozmycia ruchu na istniejącym zdjęciu - robienie rozmycia w animacjach to zupełnie inny obszar. Zamazalibyśmy tylko cały obraz - nie próbowalibyśmy zamazywać obiektu na obrazie. Dobrą wiadomością jest to, że już zrobiliśmy proste rozmycie ruchu. Wróć do powyższego apletu okna i ustaw poziomo promień na, powiedzmy 10, i promień pionowy na zero. Daje to ładne poziome rozmycie ruchu. Do niektórych celów może to być wszystko, czego potrzebujesz. Na przykład jednym ze sposobów na uzyskanie szczotkowanej tekstury metalu jest zrobienie obrazu składającego się z losowego szumu i zastosowania rozmycia ruchu. Jeśli chcemy rozmazać w kierunku innym niż poziomy lub pionowy, to rzeczy stają się bardziej skomplikowane. Jedną z technik może być obracanie obrazu, rozmycie, a następnie obrót. Jednak dobrze zrobi się to w sposób trudny i powolny. Musimy wykonać pętlę nad obrazem i dla każdego piksela zsumować wszystkie piksele wzdłuż ścieżki ruchu. W przypadku rozmycia w ruchu prostym oznacza to po prostu linię prostą od piksela, ale możesz podążać za falującą ścieżką, jeśli chcesz symulować drgania aparatu z długimi czasami ekspozycji. Zakręć i powiększ rozmycie Kiedy już dostaniemy kod do poruszania się w ruchu, łatwo go zmodyfikujemy, aby pomalować i obrócić, a nawet kombinację wszystkich trzech. To tylko kwestia podążania właściwą ścieżką dla każdego piksela. W przypadku rozmycia promieniowego, postępuj zgodnie ze ścieżką biegnącą od centrum rozmycia. Aby uzyskać rozmycie w ruchu obrotowym, podążaj styczną ścieżką. Wypróbuj w tym aplecie: Oto kod źródłowy do robienia tych trzech rodzajów rozmycia: Szybsza rozmycie ruchu Może zauważyłeś, że robienie rozmycia w ruchu jest dość powolnym biznesem - wszystkie te sinusy i cosinusy naprawdę spowalniają działanie. Jeśli jednak nie martwiliśmy się o jakość, możemy przyspieszyć ten proces. Wszystko, co musimy zrobić, to połączyć spore przekształcone wersje obrazu w sprytny sposób. Sprytnym elementem jest to, że możemy wykonać 1-pikselowe rozmycie ruchu, uśredniając obraz i ten sam obraz przetłumaczony na jeden piksel. Możemy zrobić rozmycie 2-pikselowe, powtarzając to z 1-pikselowymi rozmytymi obrazami. Powtarzając to możemy zrobić rozmycie N-pikselowe w log2 (N), co jest o wiele lepsze niż robienie tego w sposób twardy i powolny. Powielanie i wirowanie można przeprowadzać przez skalowanie i obracanie zamiast tłumaczenia. Jeden filtr zrobi wszystkie trzy za pomocą AffineTransform. Wypróbuj w tym aplecie: Przeniesienie domen Istnieje jeszcze inny sposób na robienie takich rozmytych ruchów: Pamiętaj, że powiedziałem, że możesz wykonywać liniowe rozmycie ruchu, obracając obraz, wykonując poziome pole rozmycia i obracając się z powrotem. Cóż, to samo dotyczy zoom i spin zacierają się, chyba że potrzebujesz czegoś bardziej skomplikowanego niż rotacja. To, czego potrzebujesz, to transformacja polarna. Po przekształceniu obrazu rozmycie w poziomym polu jest wirowaniem po przekształceniu, a rozmycie w pionowym polu powoduje rozmycie powiększenia. Jednym szczegółem jest to, że potrzebujesz specjalnego poziomego rozmycia w pudełku, które owija się na krawędziach, w przeciwnym razie otrzymasz ostrą pionową linię na rozmytym obrazie, gdzie kąt obrotu powinien się zawijać. Rozmycie za pomocą transformaty Fouriera Rozmycie gaussowskie jest bardzo dobre, gdy chcesz uzyskać efekt rozmycia Gaussa, ale co zrobić, jeśli chcesz uzyskać odpowiednie rozmycie soczewek, które symuluje rzeczywistą aperturę aparatu Oglądaj dowolny film lub program telewizyjny przez jakiś czas, zwłaszcza coś, co można zrobić w nocy przy świetle w tle, a zobaczysz, że rzeczy, które są nieostre, tworzą kształty dysku, a może pięciokąty. Istnieje również zjawisko zwane kwitnieniem, w którym jasne części obrazu zmywają obraz, stając się jeszcze jaśniejsze w porównaniu do pozostałych. Te kształty nazywają się Bokeh. Niektórzy ludzie to uwielbiają, a niektórzy go nienawidzą. Nie obchodzi nas, czy ludzie to kochają, czy go nienawidzą, chcemy tylko to odtworzyć. Nie dostaniesz tych kształtów dysku z rozmyciem Gaussa - jest zbyt rozmyty na krawędziach. To, co musisz zrobić, to użyć ładnego, ostrego jądra splotu w kształcie otworu aparatu. Problemem, który napotkasz tutaj, jest to, że wszystkie te sztuczki do zrobienia z oddzielnymi jądrami, iterowanymi rozmytymi polami i tym podobnymi nie działają tutaj - nie ma oddzielnych ziaren, które dadzą ci pentagon (no, prawdopodobnie - nie jestem żadnym matematykiem) - wróciły do stary problem z czasem rozmycia, będącym kwadratem promienia rozmycia. Nie obawiaj się, możemy zamienić ciężkie matematyczne pistolety na problem. Nie wiem, jak działają ciężkie działa, ale mogę je wycelować. Ciężkie działa to transformaty Fouriera. Nie wiem, jak działają, ponieważ nie słuchałem na wykładach uniwersyteckich, ale istnieje ogromna ilość na ten temat, który można znaleźć w Internecie, chociaż praktycznie nic praktycznego (tj. Z kodem źródłowym) na temat zatarcia. W przypadku transformacji Fouriera można uzyskać rozmycie, które nie jest zależne od promienia rozmycia (w praktyce radzenie sobie z krawędziami obrazu oznacza, że ​​nie jest to prawdą). Niestety oznacza to, że w małym promieniu jest powolny, ale naprawdę wygrywasz z dużym promieniem. Jednym ze sposobów radzenia sobie z tym jest użycie prostego splotu dla małych promieni i przejście do transformacji Fouriera po osiągnięciu punktu przecięcia w czasie, zakładając, że wykonałeś eksperymenty, aby ustalić, gdzie to jest. Ale bądź ostrożny, jeśli animujesz rozmycie, musisz upewnić się, że nie dostałeś żadnych widocznych artefaktów w punkcie, w którym przełączasz algorytm - oko jest naprawdę dobre w wykrywaniu tych. Z tego powodu możesz preferować stosowanie jednego algorytmu dla całej animacji. W przypadku obrazów nieruchomych nikt nie zauważy. Naprawdę. Czy to naprawdę wygląda inaczej Z pewnością uda nam się uciec rozmyciem Gaussa Cóż, oto przykład, który pomoże ci w podjęciu decyzji. Zasada działania nie jest zbyt trudna, chociaż wydaje się być magiczna. To, co robimy, to pobranie obrazu i jądra i wykonanie na nich transformaty Fouriera. Następnie pomnożymy dwa razem i odwrócimy transformację z powrotem. Jest to dokładnie to samo, co wykonywanie długiego splotu powyżej (z wyjątkiem błędów zaokrąglania). Nie musisz właściwie wiedzieć, co robi transformata Fouriera, aby to zaimplementować, ale w każdym razie, to, co robi, to przekształcenie twojego obrazu w przestrzeń częstotliwości - wynikowy obraz jest dziwnie wyglądającą reprezentacją przestrzennych częstotliwości w obrazie. Odwrotność oczywiście zmienia się z powrotem w kosmos. er, przestrzeń. Pomyśl o tym jak o graficznym korekcie obrazów. Możesz pomyśleć o zamazaniu obrazu jako usunięciu z niego wysokich częstotliwości, aby to, w jaki sposób przekształciły się Fouriera w obraz. Wdrożenie tego jest dość proste, ale trzeba się martwić wieloma nieprzyjemnymi szczegółami. Przede wszystkim potrzebujemy pewnych funkcji do transformacji i jej odwrotności. Można je znaleźć w klasie FFT. Nie jest to w żadnym wypadku superoptymalizowana implementacja - można znaleźć wiele z tych gdzie indziej w Internecie. Następnie musimy przekonwertować jądro na obraz o rozmiarze takim samym jak rozmazany obraz (jestem pewien, że są sposoby na uniknięcie tego, ale nie znam wystarczającej matematyki - jeśli tylko słuchałem tych wykładów). Musimy również wydzielić nasz obraz źródłowy przez promień rozmycia, powielając piksele krawędziowe, ponieważ trudno jest uzyskać FFT, aby poradził sobie z takimi krawędziami. Teraz FFT działa na liczbach zespolonych, więc musimy skopiować obraz i jądro do tablic float. Możemy zrobić tutaj trik - nasze obrazy mają cztery kanały (alfa, czerwony, zielony i niebieski), więc musimy zrobić cztery transformacje plus jeden dla jądra, co daje pięć, ale ponieważ używaliśmy liczb zespolonych, możemy zrobić dwie transformacje naraz przez wstawienie jednego kanału w rzeczywistej części tablicy i jednego kanału w części urojonej. Teraz wszystko staje się proste, po prostu przekształcaj obraz i jądro, łącz je razem i transformuj odwrotnie, a my mamy swój obraz z powrotem, ale w połączeniu z jądrem. Ostatnim drobnym szczegółem jest to, że proces transformacji zamienia się w ćwiartki obrazu, więc musimy odrzucić. Pozostaje tylko jeden mały szczegół: FFT działa tylko na obrazach o sile 2 w każdym kierunku. Musimy dodać dwa razy większy promień rozmycia niż szerokość i wysokość, znaleźć kolejną najwyższą moc 2 i uczynić nasze tablice takim rozmiarem. W przypadku dużych obrazów ma to kilka problemów: Jednym z nich było zużywanie dużej ilości pamięci. Pamiętaj, że mamy nasze obrazy w tablicach float i potrzebujemy 6 z tych tablic, z których każda jest 4 razy większa od rozmiaru obrazu, gdy została rozszerzona do potęgi dwóch. Twoja wirtualna maszyna Java może złożyć na ciebie skargę, jeśli spróbujesz tego na dużym obrazie (wiem, że próbowałem). Drugi problem jest związany: rzeczy stają się wolniejsze w przypadku dużych obrazów z powodu problemów z pamięcią podręczną. Odpowiedzią jest podzielenie obrazu na płytki i rozmycie każdej płytki osobno. Wybór dobrego rozmiaru płytki to problem z badaniem opcji (np. Nie miałem ochoty eksperymentować zbyt wiele), ale jest trudny - musimy pokrywać płytki przez promień rozmycia, więc jeśli wybieramy rozmiar płytki o rozmiarze 256 z promieniem rozmycia 127 , weź tylko zamazuj 4 piksele z każdą płytką. Wypróbuj w tym aplecie: Threshold Blurs Coś, co jest często poszukiwane, to rozmycie, które rozmywa części obrazu, które są bardzo podobne, ale zachowują ostre krawędzie. Jest to cyfrowy krem ​​do zmarszczek i można to zobaczyć na dowolnym plakacie filmowym, jaki kiedykolwiek wydrukowano - twarze gwiazd mają te paskudne skazy, które są wyprasowane bez widocznego rozmycia obrazu. Często jest to tak przesadzone, że aktorzy wyglądają jak figurki z wosku lub generowane komputerowo postacie. Sposób, w jaki to robimy, to zwykłe splatanie, ale liczymy tylko w otaczających pikselach, które są podobne do piksela docelowego. W szczególności mamy próg i uwzględniamy tylko piksel w splotach, jeśli różni się on od środkowego piksela o mniej niż próg. Niestety, skróty, które zrobiliśmy powyżej, nie będą tutaj działać, ponieważ musimy uwzględnić inny zestaw otaczających pikseli dla każdego docelowego piksela, więc ponownie powróciliśmy do pełnego splotu. Teraz, chociaż jest to niezwykle wątpliwe, to całkiem dobrze działa, aby nadal wykonywać dwa skręty 1D dla rozmycia Gaussa, które jest szybsze niż wykonanie pełnego splotu 2D, więc to, co zrobiłem tutaj. Możesz zmodyfikować źródło, aby wykonać całą czynność. Wypróbuj w tym aplecie: Zmienne rozmycie Do tej pory rozmawialiśmy tylko o jednolitych rozmycie - gdzie promień rozmycia jest taki sam w każdym punkcie. Dla niektórych celów przyjemnie jest mieć rozmycie, które ma inny promień w każdym punkcie obrazu. Jednym z przykładów jest symulowanie głębi ostrości: Możesz zrobić zdjęcie, które jest skupione na całym obszarze i zastosować do niego rozmycie zmienne, aby części wyglądały na nieostre. Rzeczywista głębia ostrości jest bardziej skomplikowana niż ta, ponieważ obiekt, który znajduje się za innym obiektem, nie powinien otrzymywać żadnych plam od obiektu z przodu, ale dobrze to zignoruj ​​i pozostaw to profesjonalistom. Teraz nasze fantazyjne sztuczki nie pomogą nam tutaj zbyt wiele, ponieważ wszystko wymaga wstępnego obliczenia jądra lub polega na tym, że promień rozmycia jest taki sam na obrazie i na pierwszy rzut oka wygląda na to, że nie mamy innego wyjścia, jak tylko wrócić do pełnego splotu. każdy piksel, tylko tym razem jest znacznie gorszy, ponieważ jądro mogło się zmienić z poprzedniego piksela. Jednak nie wszystko jest stracone. Zapamiętaj tę sztuczkę z rozmytymi ramkami, które właśnie dodaliśmy w pikselach, kiedy weszły do ​​jądra i odjęły je po ich odejściu Wygląda na to, że to nie będzie działać w przypadku zmiennej promusu, ponieważ śr musi utrzymywać sumy dla każdego możliwego promienia, ale tam jest modyfikacja możemy wykonać trik, który pozwala nam magicznie wyciągnąć sumy dla dowolnego promienia za pomocą tylko jednego odejmowania. To, co robimy, jest wstępnym przetwarzaniem obrazu i zastąpieniem każdego piksela sumą wszystkich pikseli po lewej stronie. W ten sposób, gdy chcemy znaleźć sumę wszystkich pikseli pomiędzy dwoma punktami w linii skanowania, wystarczy odjąć pierwszą z drugiej. Umożliwia to szybkie rozmycie zmiennych przy użyciu zmodyfikowanej wersji powyższego kodu zamazywania. Radzenie sobie z krawędziami jest nieco bardziej skomplikowane, ponieważ po prostu odjęcie sumy nie działa dla pikseli poza krawędzią, ale jest to drobny szczegół. Potrzebujemy również nieco więcej miejsca do przechowywania, ponieważ sumy przekroczą maksymalną wartość piksela - potrzebujemy użyć int na kanał zamiast przechowywania czterech kanałów w jednej int. Cóż, OK, ale jest to rozmycie Gaussa (ish) Nie jest to co robić z tym rozmyciem soczewki o zmiennym promieniu Niestety, nie masz szczęścia tutaj. Nie twierdzę, że nie jest to super szybki sposób robienia tego, ale o ile wiem, będziesz musiał zrobić całą splot. Wypróbuj go w tym aplecie, który rozmazuje się bardziej, gdy poruszasz się w prawo: Ostrzenie przez rozmycie Możesz użyć rozmycia, aby wyostrzyć obraz, a także zamazać go za pomocą techniki zwanej maskowaniem nieostrości. To, co robisz, to zrobienie zdjęcia i odjęcie zamazanej wersji, upewniając się, że zrekompensujesz utratę jasności. Brzmi to jak magia, ale to naprawdę działa: porównaj to zdjęcie z oryginałem. Wypróbuj w tym aplecie: Jeśli odjęcie zamazanej wersji obrazu od niego wyostrza, to co robi to jak zawsze, nie musisz zgadywać - jestem tu po to, aby Cię poinformować. To, co otrzymujesz, jest rodzajem świecącego efektu, który może wyglądać całkiem ładnie, lub całkiem tandetnie w zależności od twojego punktu widzenia. Różnicowanie ilości rozmycia dodanego zmienia efekt świecącego. Efekt ten jest bardzo często używany w telewizji w przypadku marzeń o sennym wyglądzie. Wypróbuj w tym aplecie: Tworzenie cieni Tworzenie cienia to tylko kwestia stworzenia obrazu, który wygląda jak sylwetka zacienionego obiektu, zamazuje go, ewentualnie zniekształca lub przesuwa, a także wkleja oryginalny obraz na wierzch. Ponieważ jest to bardzo popularna rzecz, którą należy zrobić, powinien istnieć filtr, aby to zrobić, I oto jest. Jest to bardzo uproszczona implementacja - po prostu zaciera cień i rysuje oryginalny obraz na wierzchu. W praktyce lepiej nie zamazywać pikseli, które są całkowicie ukryte przez obiekt. Casting Rays Możemy zrobić tę samą sztuczkę, aby promienie światła wydawały się wychodzić z obiektu, tylko tym razem powodując, że kolor cienia jest biały i za pomocą rozmycia powiększenia zamiast zwykłego rozmycia, a następnie dodając wynik na wierzchu oryginału. Promienie często wyglądają lepiej, jeśli rzuca się je tylko z jasnych części obrazu, więc filtr ma próg, który można ustawić, aby ograniczyć promienie do jasnych obszarów. Jest to dobry efekt do animacji: spraw, aby środek promieni poruszał się po obrazie, a efekt ruchu źródła światła znajduje się za obrazem. Wniosek Cóż, to jest to, a nawet nie wspomniałem o innych metodach zamazywania, takich jak filtry IIR, filtry rekurencyjne i wszystkie inne nieprzyjemne rzeczy. Mam nadzieję, że wyjdzie ci z tego coś pożytecznego, nawet jeśli jest to tylko palące pragnienie kupienia zielonego atramentu i napisanie do mnie listu. Na koniec możesz zauważyć, że powyższe źródło jest oparte na innych klasach. Nie martw się, oto one: Lodes Computer Graphics Tutorial Filtrowanie obrazu Spis treści Wprowadzenie Filtrowanie obrazu umożliwia stosowanie różnych efektów na zdjęciach. Opisany tu rodzaj filtrowania obrazu wykorzystuje filtr 2D podobny do tego, który znajduje się w programie Paint Shop Pro jako filtr zdefiniowany przez użytkownika, a w programie Photoshop jako filtr niestandardowy. Konwersja Sztuczką w filtrowaniu obrazu jest posiadanie matrycy filtra 2D i obrazu 2D. Następnie, dla każdego piksela obrazu, weź sumę produktów. Każdy produkt jest wartością koloru bieżącego piksela lub sąsiada, z odpowiednią wartością macierzy filtra. Środek matrycy filtra należy pomnożyć z bieżącym pikselem, a pozostałe elementy macierzy filtra odpowiednimi sąsiednimi pikselami. Ta operacja, w której bierzesz sumę produktów elementów z dwóch funkcji 2D, w których jedna z dwóch funkcji przesuwa się po każdym elemencie innej funkcji, nazywa się Konwolucji lub Korelacji. Różnica między Konwolucją a Korelacją polega na tym, że w przypadku Konwolucji musisz odzwierciedlać matrycę filtra, ale zwykle jest ona symetryczna, więc nie ma różnicy. Filtry ze splotem są stosunkowo proste. Bardziej złożone filtry, które mogą korzystać z bardziej fantazyjnych funkcji, również istnieją i mogą robić o wiele bardziej skomplikowane rzeczy (na przykład filtr z kolorowym ołówkiem w Photoshopie), ale takie filtry nie są tutaj omawiane. Konwersja 2D wymaga 4-podwójnej pętli, więc nie jest zbyt szybka, chyba że używasz małych filtrów. Tutaj zwykle używa się filtrów 3x3 lub 5x5. Istnieje kilka reguł dotyczących filtra: jego rozmiar musi być nierównomierny, tak aby zawierał środek, na przykład 3x3, 5x5 i 7x7. Nie musi, ale suma wszystkich elementów filtru powinna wynosić 1, jeśli chcesz, aby wynikowy obraz miał taką samą jasność jak oryginał. Jeśli suma elementów jest większa niż 1, wynikiem będzie jaśniejszy obraz, a jeśli jest mniejszy niż 1, ciemniejszy obraz. Jeśli suma wynosi 0, wynikowy obraz nie musi być całkowicie czarny, ale będzie bardzo ciemny. Obraz ma skończone wymiary, a jeśli na przykład obliczasz piksel po lewej stronie, nie ma już pikseli po lewej stronie, podczas gdy są one wymagane do splotu. Możesz tutaj użyć wartości 0 lub zawinąć się na drugą stronę obrazu. W tym samouczku wybierane jest zawijanie, ponieważ można je łatwo wykonać za pomocą podziału modulo. Wynikowe wartości pikseli po zastosowaniu filtru mogą być ujemne lub większe niż 255, jeśli tak się stanie, można je obciąć, aby wartości mniejsze niż 0 były wartość 0 i wartości większe niż 255 są ustawione na 255. W przypadku wartości ujemnych można również użyć wartości bezwzględnej. W domenie Fouriera lub w domenie częstotliwości operacja splotu staje się zamiast niej mnożeniem, które jest szybsze. W domenie Fouriera można zastosować znacznie mocniejsze i większe filtry, szczególnie w przypadku szybkiej transformaty Fouriera. Więcej na ten temat znajduje się w artykule Transformacja Fouriera. W tym artykule przyjrzyjmy się kilku bardzo typowym małym filtrom, takim jak rozmycie, wykrywanie krawędzi i wytłoczenia. Filtry obrazu nie są jeszcze możliwe do zastosowania w aplikacjach i grach w czasie rzeczywistym, ale są przydatne w przetwarzaniu obrazów. Cyfrowe filtry audio i elektroniczne również działają w trybie splotu, ale w trybie 1D. Oto kod, który posłuży do wypróbowania różnych filtrów. Oprócz stosowania matrycy filtra ma ona również współczynnik mnożnikowy i odchylenie. Po zastosowaniu filtru współczynnik zostanie pomnożony przez wynik, a następnie dodany do niego błąd. Więc jeśli masz filtr z elementem 0.25, ale współczynnik jest ustawiony na 2, wszystkie elementy filtra są w teorii pomnożone przez dwa tak, że element 0.25 jest faktycznie 0.5. Odchylenie może być użyte, jeśli chcesz, aby wynikowy obraz był jaśniejszy. Wynik jednego piksela jest przechowywany w pływających kolorach czerwonym, zielonym i niebieskim, przed przekształceniem go w wartość całkowitą w buforze wyników. Samo obliczenie filtra to 4-podwójna pętla, która musi przejść przez każdy piksel obrazu, a następnie przez każdy element matrycy filtra. Obraz imageX i imageY są obliczane tak, że dla środkowego elementu filtra będzie to x, y, ale dla pozostałych elementów będzie to piksel z obrazu na lewo, na prawo, na górę lub dół x, y. Jego modulo jest podzielone przez szerokość (w) lub wysokość (h) obrazu, dzięki czemu piksele poza obrazem będą zawijane. Przed dzieleniem modulo dodawane są również w lub h, ponieważ podział modulo nie działa poprawnie dla wartości ujemnych. Teraz piksel (-1, -1) będzie poprawnie stał się pikselem (w-1, h-1). Jeśli chcesz zamiast wartości bezwzględnej użyć wartości mniejszej od zera, użyj tego kodu: Analiza szeregów czasowych tsa statsmodels. tsa zawiera klasy modeli i funkcje przydatne do analizy szeregów czasowych. Obejmuje to obecnie jednowymiarowe modele autoregresyjne (AR), wektorowe modele autoregresyjne (VAR) i jednowymiarowe autoregresyjne modele średniej ruchomej (ARMA). Obejmuje również statystykę opisową dla szeregów czasowych, na przykład autokorelację, funkcję częściowej autokorelacji i periodogram, a także odpowiednie teoretyczne właściwości ARMA lub powiązanych procesów. It also includes methods to work with autoregressive and moving average lag-polynomials. Additionally, related statistical tests and some useful helper functions are available. Estimation is either done by exact or conditional Maximum Likelihood or conditional least-squares, either using Kalman Filter or direct filters. Currently, functions and classes have to be imported from the corresponding module, but the main classes will be made available in the statsmodels. tsa namespace. The module structure is within statsmodels. tsa is stattools. empirical properties and tests, acf, pacf, granger-causality, adf unit root test, ljung-box test and others. armodel. univariate autoregressive process, estimation with conditional and exact maximum likelihood and conditional least-squares arimamodel. univariate ARMA process, estimation with conditional and exact maximum likelihood and conditional least-squares vectorar, var. vector autoregressive process (VAR) estimation models, impulse response analysis, forecast error variance decompositions, and data visualization tools kalmanf. estimation classes for ARMA and other models with exact MLE using Kalman Filter armaprocess. properties of arma processes with given parameters, this includes tools to convert between ARMA, MA and AR representation as well as acf, pacf, spectral density, impulse response function and similar sandbox. tsa. fftarma. similar to armaprocess but working in frequency domain tsatools. additional helper functions, to create arrays of lagged variables, construct regressors for trend, detrend and similar. filters. helper function for filtering time series Some additional functions that are also useful for time series analysis are in other parts of statsmodels, for example additional statistical tests. Some related functions are also available in matplotlib, nitime, and scikits. talkbox. Those functions are designed more for the use in signal processing where longer time series are available and work more often in the frequency domain. Descriptive Statistics and Tests stattools. acovf (x, unbiased, demean, fft)

No comments:

Post a Comment