Pýt(hr)ame sa s Pythonom (2)

150

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.

Dobrý článok? Chceš dostávať ďalšie?

Už viac ako 6 200 ITečkárov dostáva správy e-mailom. Nemusíš sa báť, nie každé ráno. Len občasne.

Súhlasím so spracovaním mojich osobných údajov. ( Viac informácií. )

Tvoj email neposkytneme 3tím stranám. Posielame naňho len informácie z robime.it. Kedykoľvek sa môžeš odhlásiť.