OpenCV- wykrywanie stanu oczu, część 1
Dziś jeden z pierwszych technicznych wpisów na blogu, powstał on w wyniku prac przy jednym z projektów dla klienta. Otóż jednym z wymagań w aplikacji internetowej i mobilnej było zadanie rozpoznawania stanu oczu osoby siedzącej przez komputerem oraz smarfonem. Należało ustalić w czasie rzeczywistym czy użytkownik ma zamknięte czy otwarte oczy i w zależności od automatycznie wykrytego stanu podjąć stosowną akcję.
Ponadto podsystem rozpoznawania powinien być wystawiony jako REST API i umożliwiać komunikację zarówno z aplikacją mobilną jak i z serwisem internetowym. Cały serwer API wykonaliśmy w frameworku Flask Python a do manipulowania obrazem zdecydowaliśmy się na wykorzystanie biblioteki OpenCV.
Wyszczególniliśmy kilka etapów procesu klasyfikacji:
- wydzielenie obszaru twarzy
- wydzielenie obszaru każdego z oczu
- detekcję, czy dane oko jest zamknięte czy otwarte.
Przeanalizujmy na przykładowym obrazie poniżej (http://tinyurl.com/ps5lkl9) jak można tego dokonać.
Po pierwsze do wydzielenia obszaru twarzy oraz oczu wykorzystaliśmy dostępne w bibliotece OpenCV kaskady HAAR. Do wykrycia twarzy użyliśmy haarcascade_frontalface_default.xml, a do wykrycia pozycji oczu – haarcascade_eye.xml. Kod na listingu poniżej prezentuje ten etap:
import numpy as np
import cv2
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
image = cv2.imread('image.jpg', 1)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x+w, y+h), (255, 0, 0), 2)
cv2.imshow('Face', image)
if cv2.waitKey(0) & 0xFF == ord('q'):
cv2.destroyAllWindows()
Na początku wczytujemy kaskady oraz tworzymy kopię obrazu z pliku w skali szarości. Następnie używamy na nim kaskady wykrywającej twarz. W pętli for dla wszystkich znalezionych twarzy rysujemy wokół nich prostokąt. Efekt:
Kolejnym krokiem jest wyznaczenie obszaru oczu. Na zaznaczonym obszarze wykorzystamy kaskadę haarcascade_eye. Dla każdej twarzy znalezionej na obrazie, sprawdzamy go kaskadą dla oczu i jeżeli wykryjemy oczy to rysujemy zielone prostokąty dookoła każdego oka.
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x+w, y+h), (255, 0, 0), 2)
roi_gray = gray[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_gray, 1.1, 20)
for (ex,ey,ew,eh) in eyes:
cv2.rectangle(image, (x+ex, y+ey), (x+ex+ew, y+ew+eh), (0, 255, 0), 2)
W efekcie otrzymujemy obraz taki jak poniżej.
Pierwsza część zadania za nami udało nam się wykryć na zdjęciu oboje oczu, jednak wciąż pozostaje kwestia detekcji ich stanu. Do tego stworzyliśmy własne rozwiązanie bazujące ma metodach uczenia maszynowego. Wykorzystaliśmy w tym celu jeden z wiodących algorytmów klasyfikacji – Support Vector Machines (SVM). O trenowaniu i wykorzystaniu własnego SVM’a napiszę w kolejnej części tego artykułu.



