Wyzwania leniwca - ImageMagick
21.12.2012 | aktual.: 25.12.2012 07:09
Na przestrzeni lat w moim domu zgromadzona została całkiem pokaźna kolekcja zdjęć rodzinnych: świątecznych, narodzinowych, wycieczkowych…. Do wyboru, do koloru. Wiele z nich nieudanych, źle wykadrowanych lub z obciętymi głowami, jednak wszystkie niepowtarzalne na swój sposób. Wielokrotnie siadywało się w gronie najbliższych przeglądając co niektóre.
Postarzałem się, niektóre postaci już poznikały, ale pamiątki wciąż przypominają o wielu sytuacjach oraz tym co było. Któregoś dnia postanowiłem jednak, że czas dotrzymać kroku postępowi techniki i należałoby przekształcić fotki na postać cyfrową.
Zabawę czas zacząć
Pierwszym problemem, jakże oczywistym, jest zaplecze techniczne. Z racji nieposiadania skanera zastanawiałem się nad skorzystaniem z usług firm zajmujących się dygitalizacją starych fotografii.
Niestety, poszukiwania ujawniły, że wiele z nich pracuje tylko na kliszach, a te które przetworzą również odbitki - żądają bajońskich sum za swoje usługi. Po sprawdzeniu dokładnej liczby zdjęć i przeliczeniu kosztów okazało się jednak, że musiałbym wydać kilkaset złotych na swój zamiar. Na taki wydatek nie mogłem sobie pozwolić.
Postanowiłem więc kupić skaner dla siebie. Po przejrzeniu wielu testów i opinii zdecydowałem się na zakup sprzętu z niższej półki. Wydając ok. 300zł parametry powinny być wystarczające do archiwizacji. Z racji tego, że z biegiem czasu negatywy gdzieś przepadły, rezygnując z przystawek mogłem zaoszczędzić kilkadziesiąt złotych.
Wybór padł na skaner EPSON Perfection V33.
Ready, set, go!
Oprogramowanie dostarczone do tego urządzenia prezentuje się całkiem przyzwoicie: szereg profili do wybrania i ustawienia, konfigurowanie przycisków zewnętrznych oraz prosty edytor skanów. Wszystko to sprawiło, że pierwsze wrażenie było nader przyzwoite. Sam edytor umożliwia też wstępne podzielenie skanowanego obrazu na części, ich obracanie i korektę. Edytor ten okazał się również przeszkodą na drodze do mojego celu.
Po kilkudziesięciu minutach zabawy i chwili obliczeń wyszło na to, że już samo zeskanowanie fotek będzie nie lada udręką. Ponieważ jestem raczej leniwą osobą, stwierdziłem, że obróbkę zostawię „na zaś” i najpierw po prostu zeskanuję i krzywo wytnę wszystko jak leci - po kilka fotek na raz. W końcu od czego są gimpy i inne takie?
Zatem po dwóch tygodniach i łącznie przesiedzianych ok. 42 godzinach, mogłem uśmiechnąć się do skanera i odstawić na półkę, by zbierał kurz.
- Ilość skanów: ~600
- Maksymalny skan: 7450x4963 (17,1MB)
- Minimalny skan: 1667x2357 (1,65MB)
- Średni czas skanowania: 4 minuty / 3 fotki
Jakie toto brzydkie
Pierwsze oględziny uświadomiły mi, że w czasach PRL jakość materiałów fotograficznych była bardzo kiepska bowiem duża część fotografii przekłamywała lub traciła kolory.
Ręczne poprawianie wszystkich nie wchodziło jednak w rachubę, postanowiłem więc odfiltrować najbrzydsze z zebranych i poprawić w nich balans bieli automatycznie.
Dzięki pomocy XnConvert okazało się to bajecznie proste i po prawie pięciu minutach wszystko było gotowe.
Szczęście nie trwało jednak długo i szybkie oględziny ujawniły ok. 50 plików do poprawienia.
- Skanów: 224
- Czas: 285 sek. (~4,8 min)
- Wynik: 50 do poprawy
Szef wszystkich szefów
Przede mną pozostało jeszcze wiele do zrobienia. Musiałem przecież poobracać wszystkie skany i sensownie (czyt. dokładniej) je poprzycinać.
Od samego początku wiedziałem, że XnConvert do tych zadań już się nie nadaje. O ile potrafi on obrócić fotografię wg wyznaczonych parametrów, samemu ich jednak nie określi. Samemu też nie zgadnie w jaki sposób przyciąć fotografie. Do tego potrzebowałem czegoś potężniejszego.
O ImageMagick wiedziałem od dawna. Wiedziałem też jak bardzo rozbudowanym jest narzędziem - śmiało można rzec, że przewyższa fotoszopę pod wieloma względami. Obsługuje ponad setkę formatów obrazów (w tym własny format wektorowy), posiada ponad 270 poleceń konsoli oraz API dla wielu języków programowania (np. Ada, C++, Java…). Nie posiada co prawda interfejsu graficznego, ale i dzięki temu potrafi działać w sposób wyjątkowo szybki. Ba! Posiada nawet obsługę języka skryptów, który pozwala użytkownikom na jeszcze większą kontrolę nad obróbką grafiki.
Wspomnę o bardzo ciekawym artykule nieźle opisujacym zastosowanie aplikacji pochodnej od IM o nazwie GraphicsMagick: http://codeascraft.etsy.com/2010/07/09/batch-processing-millions-of-im...
Obracamy
Programom raczej ciężko określić, który element fotki to tak na prawdę góra i bezsensownym wydaje się zautomatyzowanie tego zadania. Wiem jednak, że programowo można:
- wykryć krawędzie obrazu,
- założyć sobie, że określają one prostokąt,
- obliczyć kąt nachylenia prostokąta do pionu/podstawy
- obrócić obraz w oparciu o dany kąt.
Tego właśnie dokonuje prosty skrypt:
d:\grafa\ImageMagick-6.7.2-8\convert.exe -deskew 40% i:\_photo_\skaner\rodzinne\bw\img090.jpg i:\_photo_\skaner\rodzinne\bw\ok\img090.jpg
gdzie 40% określa stopień wykrywania krawędzi (jest to bodajże procentowa różnica kolorów krawędzi i obrazu, ale pewności nie mam).
- Skanów: ~1900
- Czas przetwarzania: 322 minuty
Tniemy
Kolejnym poleceniem do użycia okazało się trim. Pozwala ono na przycięcie zdjęcia od jego krawędzi aż po faktyczny obraz. W oparciu o pierwsze piksele ImageMagick oszacowuje, które elementy usunąć. Wraz z parametrem fuzz określamy sobie dodatkowo różnicę (odległość) kolorów, które powinien brać pod uwagę.
Zatem dzięki:
d:\grafa\ImageMagick-6.7.2-8\convert.exe -fuzz 20% -trim d:\txt_garbage\_prezentacja\images\04_cut\img062.jpg d:\txt_garbage\_prezentacja\images\04_cut\ok_01\img062.jpg
otrzymujemy w efekcie:
Niestety, część zdjęć po zabawach z balansem posiada nieco zmodyfikowane barwy tła, zatem przed wykonaniem tego polecenia warto dodać do nich białą ramkę do której IM będzie się odnosił:
d:\grafa\ImageMagick-6.7.2-8\convert.exe -bordercolor #FFFFFF -border 10x10 -fuzz 20% -trim d:\txt_garbage\_prezentacja\images\04_cut\img062.jpg d:\txt_garbage\_prezentacja\images\04_cut\ok_02\img062.jpg
- Czas całkowity: ~70 minut
Efekt ostateczny
Czas automatycznej obróbki wyniósł jakieś 392 minuty. Każda z operacji wykonywana była oddzielnie i korciło mnie by sprawdzić, ile czasu można zaoszczędzić wykonując wszystko w jednym kroku. Połączyłem więc skrypty i odpaliłem je ponownie któregoś dnia:
@echo off for %%X in (*.jpg) do ( d:\grafa\ImageMagick-6.7.2-8\convert.exe -deskew 40%% -bordercolor #FFFFFF -border 10x10 -fuzz 40%% -trim d:\grafa\images\skan\%%~X d:\grafa\images\skan\final\%%~X" )
Zaowocowało to wynikiem 339 minut.
Finałowy plik BAT (z pomiarem czasu):
@echo off call :StartTimer for %%X in (*.jpg) do ( d:\grafa\ImageMagick-6.7.2-8\convert.exe -deskew 40%% -bordercolor #FFFFFF -border 10x10 -fuzz 40%% -trim d:\grafa\images\skan\%%~X d:\grafa\images\skan\ok\%%~X" ) call :StopTimer call :DisplayTimerResult goto :EOF :StartTimer :: Store start time set StartTIME=%TIME% for /f "usebackq tokens=1-4 delims=:., " %%f in (`echo %StartTIME: =0%`) do set /a Start100S=1%%f*360000+1%%g*6000+1% %h*100+1%%i-36610100 goto :EOF :StopTimer :: Get the end time set StopTIME=%TIME% for /f "usebackq tokens=1-4 delims=:., " %%f in (`echo %StopTIME: =0%`) do set /a Stop100S=1%%f*360000+1%%g*6000+1% %h*100+1%%i-36610100 :: Test midnight rollover. If so, add 1 day=8640000 1/100ths secs if %Stop100S% LSS %Start100S% set /a Stop100S+=8640000 set /a TookTime=%Stop100S%-%Start100S% set TookTimePadded=0%TookTime% goto :EOF :DisplayTimerResult :: Show timer start/stop/delta echo Started: %StartTime% echo Stopped: %StopTime% echo Elapsed: %TookTime:~0,-2%.%TookTimePadded:~-2% seconds goto :EOF
Co by tu jeszcze napisać?
Ostatnią rzeczą, która pozostała do zabawy ręcznej było pogrupowanie zasobów do ostatecznego poodwracania o ±90 i 180 stopni. To na szczęście trwało około kolejnej godziny.
Warto by jeszcze dodać znaczniki EXIF/XMP do wszystkiego i zmagazynować na nośnikach wszelakich, ale o tym w jednym z następnych odcinków.