Zastanawiałeś się kiedyś jak szybko można anonimizować zdjęcia? Jak np. rozmyć obszar zdjęcia na którym jest twarz ludzka, lub zakryć oczy? lub po prostu policzyć ile jest osób na zdjęciu? Rozwiązań jest kilka, ale jeśli chcesz to zrobić wykorzystując narzędzia darmowe i dostępne w postaci źródeł to poniżej umieszczam gotowy przepis.
Co musisz mieć?
- PHP (z modułem gd)
- OpenCV (wraz z zestawem bibliotek i nagłówków)
- facedetect (moduł PHP wykorzystujący bibliotekę OpenCV)
Słowo wyjaśnienia co do OpenCV, jest to zestaw funkcji do obróbki obrazu w czasie rzeczywistym, w całości stworzona jako otwarta, została zapoczątkowana przez Intela. Biblioteka jest wieloplatformowa i można z niej korzystać w systemach Windows, OSX, Linux.
Zaczynamy instalację.
Jeśli posiadasz już PHP z modułem GD to pomiń ten krok, jeśli nie to zainstaluj w pierwszej kolejności. Ja w przykładzie wykorzystuję Ubuntu 10.10,
# apt-get install php5-cli php5-gd php5-dev php-pear
Mając PHP, instalujemy bibliotekę OpenCV wraz z plikami nagłówkowymi (są niezbędne do kompilacji modułu facedetect)
# apt-get install libhighgui-dev libcv-dev libcvaux-dev opencv-doc
Pora na kompilację modułu PHP facedetect, moduł nie posiada swojej paczki dla Ubuntu, więc musimy skompilować go sami ze źródeł:
# wget http://www.xarg.org/download/facedetect-1.0.1.tar.gz
# tar zxvf facedetect-1.0.1.tar.gz
# cd facedetect
# phpize
# ./configure
# make
# make install
Installing shared extensions: /usr/lib/php5/20090626+lfs/
Pobieramy źródła, rozpakowujemy je, wchodzimy do katalogu facedetect, wydajemy polecenie phpize, możemy teraz wykonać ./configure, po sprawdzeniu czy posiadamy wszystkie biblioteki, pliki nagłówkowe, możemy zacząć kompilację, make i make install. W wyniku powinniśmy otrzymać komunikat, że moduł został zainstalowany w katalogu z rozszerzeniami dla PHP.
Mając już skompilowany moduł facedetect, musimy powiedzieć PHP, żeby go ładował, ja stworzyłem plik facedetect.ini w katalogu /etc/php5/conf.d/facedetect.ini który jest dołączony do php.ini
# echo "extension=facedetect.so" > /etc/php5/conf.d/facedetect.ini
ale równie dobrze możesz dopisać linię
extenstion=facedetect.so
bezpośrednio do pliku php.ini.
Po tym, PHP powinno ładować Twój moduł, możesz to sprawdzić uruchamiając php z parametrem -m
# php -m|grep facedetect
facedetect
Biblioteka OpenCV wykorzystuje zestaw gotowych algorytmów do rozpoznawania twarzy, oczy, sylwetki, uszu, wszystkie te pliki zapisane są w katalogu /usr/share/doc/opencv-doc/examples/haarcascades/haarcascades/, musimy je tylko wypakować i skopiować gdzieś bliżej naszego katalogu z naszym kodem.
# cp /usr/share/doc/opencv-doc/examples/haarcascades/haarcascades/* .
# gzip -d *.gz# ls
haarcascade_eye_tree_eyeglasses.xml haarcascade_frontalface_default.xml haarcascade_mcs_eyepair_small.xml haarcascade_mcs_upperbody.xml
haarcascade_eye.xml haarcascade_fullbody.xml haarcascade_mcs_lefteye.xml haarcascade_profileface.xml
haarcascade_frontalface_alt2.xml haarcascade_lefteye_2splits.xml haarcascade_mcs_mouth.xml haarcascade_righteye_2splits.xml
haarcascade_frontalface_alt_tree.xml haarcascade_lowerbody.xml haarcascade_mcs_nose.xml haarcascade_upperbody.xml
haarcascade_frontalface_alt.xml haarcascade_mcs_eyepair_big.xml haarcascade_mcs_righteye.xml
Pora na kod
Zaczniemy od prostego przykładowego kodu, który zwróci nam liczbę rozpoznanych twarzy i poda współrzędne:
0 1 2 3 4 5 6 7 8 9 10 11 |
<?php //face_count() - (int) ile jest obiektów //face_detect() - (array) współrzędne x, y, szerokość, wysokość $ile = face_count('girls.jpg','haarcascade_frontalface_alt2.xml'); $wsp = face_detect('girls.jpg','haarcascade_frontalface_alt2.xml'); echo $ile."n"; print_r($wsp); ?> |
haarcascade_frontalface_alt2.xml - jest algorytmem dla biblioteki OpenCV który w przypadku tego zdjęcia sprawdzał się najlepiej:
# php test.php
3
Array
(
[0] => Array
(
[x] => 155
[y] => 188
[w] => 199
[h] => 199
)[1] => Array
(
[x] => 308
[y] => 139
[w] => 216
[h] => 216
)[2] => Array
(
[x] => 544
[y] => 116
[w] => 259
[h] => 259))
Czyli nasz skrypt znalazł 3 twarze i zwrócił nam współrzędne, spróbujmy teraz oznaczyć znalezione obszary, w tym celu wykorzystamy bibliotekę GD do naniesienia kwadratów na zdjęcie, nasz kod będzie wyglądał tak:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php $im = imagecreatefromjpeg('girls.jpg'); $ord = face_detect('girls.jpg','haarcascade_frontalface_alt2.xml'); $pink = imagecolorallocate($im, 255, 105, 180); if(count($ord) > 0) { foreach ($ord as $arr) { imagerectangle($im,$arr['x'] ,$arr['y'] , $arr['x']+$arr['w'], $arr['y']+$arr['h'], $pink); } } imagejpeg($im, "girls_matched.jpg"); imagedestroy($im); ?> |
Uruchamiam skrypt i otrzymuję nowe zdjęcie "girls_matched.jpg".
Jak widać, zostały znalezione i oznaczone 3 twarze, co można zrobić dalej? można je rozmyć ;-) wykorzystajmy filtr z biblioteki gd, IMG_FILTER_GAUSSIAN_BLUR, kod po modyfikacji wygląda następująco:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php $im = imagecreatefromjpeg('girls.jpg'); $ord = face_detect('girls.jpg','haarcascade_frontalface_alt2.xml'); $pink = imagecolorallocate($im, 255, 105, 180); if(count($ord) > 0) { foreach ($ord as $arr) { $image2 = imagecreatetruecolor($arr['w'], $arr['h']); imagecopy($image2, $im, 0, 0, $arr['x'], $arr['y'], $arr['w'], $arr['h']); for($a=0; $a<100; $a++) { imagefilter($image2, IMG_FILTER_GAUSSIAN_BLUR); } imagecopy($im, $image2, $arr['x'], $arr['y'], 0, 0, $arr['w'], $arr['h']); imagerectangle($im,$arr['x'] ,$arr['y'] , $arr['x']+$arr['w'], $arr['y']+$arr['h'], $pink); } } imagejpeg($im, "girls_matched_anonymous.jpg"); imagedestroy($im); ?> |
Co się zmieniło, dodałem kopiowanie wcześniej znalezionego obszaru do nowego obrazka ($image2) na który nakładam 100 razy filtr GAUSSIAN_BLUR, po czym kopiuję zamazany obszar na oryginalne zdjęcie. Wynik:
Zachęcam do zabawy i testowania różnych algorytmów wyszukiwania, np. samych oczu (haarcascade_eye.xml), reszta jest analogiczna.