Je večer, z televízora sa valí zoznam celebritných tvárí, tak vypínam ho a pokračujem v prísľube prvej časti blogu o hrátkach s Pythonom. Samozrejme tým softvérovým. Rozšírením rozpoznávania tváre o naučené osoby a emócie.
Milí čitatelia, pohodlne sa usaďte k svojim teráriám s Pythonom, počítačom, otvorte si plechovku vašeho obľúbeného nápoja a editor na mieste, kde sme skončili so súborom BezTváre.py v predchádzajúcej časti. Uložte si ho teraz napríklad pod názvom TvojaTvarVyzeraPovedome.py :).
Do našeho programu pridáme ďalšie ingrediencie v podobe knižníc numpy a keras.
# Import knižníc - toto je komentár
import face_recognition
import cv2
import numpy as np
import keras
from keras.models import load_model
Prvá je základným pythonovským balíčkom na vedecké počty. Druhá na prácu s deep learning metódami a modelmi. Použijeme ich na vyhodnocovanie emócií. Ale to až neskôr.
Najprv chcem z našej existujúcej natrénovanej cnn siete zistiť totožnosť neznámej tváre na kamerovom zázname. Teda z niečoho takéhoto:
Získať konkrétnu osobu s menom. Samozrejme po odhalení celej tváre. Ani konvolučná neurónová sieť ju nerozozná na obrázku, kde je zakrytá. Dalo by sa to síce aj s čiastočne odhalenou časťou tváre, rozličným porovnávaním detailov a morfologických tvárových kriviek, ale to by si vyžadovalo trochu zložitejší prístup.
Inicializujeme preto ešte niekoľko samopopisných polí.
face_encodings = []
face_names = []
feelings_faces= []
V rámci dema a súladu s GDPR 🙂 do položky známych tvárí pridám pomocou metód knižnice face_recognition len tú svoju.
# Nahraj známu tvár
brano_image = face_recognition.load_image_file("BranislavMajernik.png")
brano_face_encoding = face_recognition.face_encodings(brano_image)[0]
Zadefinujem
# Zadefinuj polia známych tvárí a ich mená
known_face_encodings = [
brano_face_encoding
]
known_face_names = [
"Branislav M."
]
A pridám do časti kódu, ktorý sme si už vytvorili v predchádzajúcej časti, programovú slučku. V nej porovnávam zobrazenú tvár s tvárou zo zoznamu.
# Nájdi všetky tváre na danom obrázku
face_locations = face_recognition.face_locations(small_frame, model="cnn")
face_encodings = face_recognition.face_encodings(small_frame, face_locations)
for face_encoding in face_encodings:
# Skontroluje, či daná tvár sa podobá na niektorú známu v zozname
matches = face_recognition.compare_faces(known_face_encodings, face_encoding)
name = "Kto je to ???"
# Ak áno, pomenuj ju podľa položky v zozname
if True in matches:
first_match_index = matches.index(True)
name = known_face_names[first_match_index]
face_names.append(name)
Výsledok zobrazím vo frame videa
# Zobraz meno a emóciu vo videu
cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(frame, name, (left - 6, top + 6), font, 1.0, (255, 0, 0), 1)
#cv2.putText(frame, emotion_label, (left - 6, bottom - 6), font, 1.0, (255, 255, 0), 1)
Asi takto
Kód ktorý sme si zatiaľ napísali, ešte neobsahuje emotikon v podobe smajlíka, na predchádzajúcom obrázku v pravom hornom rohu.
Emócie z výrazu tváre nám pomôže identifikovať model z knižnice keras. Vyberiem si ich niekoľko vo formáte hdf5, ktoré mám nahrabané z githubu kerasu v mojom podaresári.
# Zadefinuj emočné modely
model = load_model("../trained_models/emotion_models/keras/model_v6_23.hdf5")
model1 = load_model("../trained_models/emotion_models/keras/fer2013_mini_XCEPTION.102-0.66.hdf5")
model2 = load_model("../trained_models/emotion_models/keras/emotion_model.hdf5")
Môžete si postupne vyskúšať, ktorý ako vystihuje príslušné emočné grimasy. Pridáme emotikony, čo sú .png obrázky v adresári /emojis označené príslušnými menami
EMOTIONS = ['angry', 'disgusted', 'fearful', 'happy', 'sad', 'surprised', 'neutral']
for index, emotion in enumerate(EMOTIONS):
feelings_faces.append(cv2.imread('../emojis/' + emotion + '.png', -1))
Keďže každý keras model pracuje, žiaľ, s iným rámcom, musíme ho opäť zmeniť na požadovaný (48,48). Ak to tak neurobíte, program vám to v runtime chybovej hláške ozrejmí aj s potrebným parametrom. Model1 napríklad vyžaduje (64,64). Áno, nepraktické a spomaľujúce, ale na demo to stačí. Orežme a porovnáme grimasu s modelom.
# zmeň veľkosť obrázku
face_image = cv2.resize(face_image, (48,48))
face_image = cv2.cvtColor(face_image, cv2.COLOR_BGR2GRAY)
face_image = np.reshape(face_image, [1, face_image.shape[0], face_image.shape[1], 1])
# Vyhodnoť typ emócie podľa pripraveného modelu
predicted_class = np.argmax(model.predict(face_image))
Výsledok zapíšeme do videa, alebo zobrazíme ako emotikon. S trochou mágie obrazových masiek opencv knižnice to môže vyzerať takto
# Emotikon (smajlík)
(frh,frw) = frame.shape[:2]
face_icon = feelings_faces[predicted_class]
for c in range(0, 3):
frame[10:130, (frw-130):(frw-10), c] = face_icon[:,:,c] * (face_icon[:, :, 3] / 255.0) + frame[10:130, (frw-130):(frw-10), c] * (1.0 - face_icon[:, :, 3] / 255.0)
A začneme porovnávať výrazy tváre
Funguje? Tak príjemné Pýt(hr)anie. V pokračovaní si ukážeme ukladanie takto získaných záznamov (kto? kedy? s akým emočným nastavením?) do databázy v cloude, kde sa dajú zbierať a následne vyhodnocovať informácie napríklad pre dochádzkový systém alebo ostrahu.