Detekcja twarzy w PHP

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:

haarcascade_frontalface_alt2.xml - jest algorytmem dla biblioteki OpenCV który w przypadku tego zdjęcia sprawdzał się najlepiej:


W wyniku otrzymałem:

# 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:

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:

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.