OpenCV Gesichtserkennung

Django, Flask, Bottle, WSGI, CGI…
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ergänzend zu den richtigen Anmerkung von BlackJack: nimm zB Personenpfad. Den hast du doch schon. Und den nicht zu nehmen erklärt auch deinen Fehler.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@DonJuan: Dein Skript ist schwer zu lesen, weil Du verschiedene logische Teile vermischst, Pfad anlegen, Video-Capture, Counter. Der Counter wird erst direkt vor der while-Schleife gebraucht, sollte also erst dort definiert werden.

Es gibt in Python eine Namenskonvention, dass alle Variablen klein_mit_unterstrich geschrieben werden. Abkürzungen sollten vermieden werden. vname -> vorname. Was soll st oder ts bedeuten? Beim Lesen muß man da raten.

Zeiten formatiert man am besten in der Form "%Y-%m-%d_%H-%M-%S", dann lassen sie sich einfach lexikalisch sortieren.

Dass Cascades relativ zum Programmcode liegt (was Du nicht erzwingst) ist für mich noch logisch, die Daten, die Du schreibst, erwartet man aber relativ zum Arbeitsverzeichnis.

os.makedirs kennt ein exist_ok-Argument, das ist sicherer, als zu prüfen, ob das Verzeichnis existiert. Das erste makedirs ist überflüssig, weil es mit dem zweiten automatisch erzeugt wird.

Die meisten der str-Aufrufe sind überflüssig, weil es sowieso schon Strings sind. Besser ist es aber, die Dateinamen per format zu erzeugen:

Code: Alles auswählen

current_time = datetime.datetime.now()
...
        file_name =  os.path.join(Namenpfad, "{} {:%Y-%m-%d_%H-%M-%S} - c {}.jpg".format(name, current_time, counter))
DonJuan
User
Beiträge: 12
Registriert: Donnerstag 15. März 2018, 20:51

Vielen Dank erstmal für die Hilfe. Ich habe es versucht umzusetzen. Wie gesagt ich bin Neuling in diesem Gebiet.
Es funktioniert wieder alles bis auf das er die Datei nicht abspeichert. Ich habe mir mit print() ausgeben lassen:
...\Personen\Max Mustermann\Max Mustermann 2018-08-25_11-40-03 - c 4.jpg

Aber im Ordner ist keine Datei.

Code: Alles auswählen

import cv2
import os
import time
import datetime

vname = input("Bitte Vorname eingeben: ")
nname = input("Bitte Nachname eingeben: ")
name = vname + " " + nname


if not os.path.exists('./Personen/' + name):
    os.makedirs('./Personen/' + name)


face_cascade = cv2.CascadeClassifier('Cascades/haarcascade_frontalface_default.xml')
cam = cv2.VideoCapture(0)



Basispfad = os.path.dirname(os.path.abspath(__file__))
Personenpfad = os.path.join(Basispfad, "Personen")
Namenpfad = os.path.join(Personenpfad, name)


current_time = datetime.datetime.now()

counter = 0

while counter < 5:
    ret, img_frame = cam.read()
    gray = cv2.cvtColor(img_frame,cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)

    for (x,y,w,h) in faces:
        roi_gray = gray[y:y + h, x:x + w]
        roi_color = img_frame[y:y + h, x:x + w]
        cv2.rectangle(gray, (x, y), (x + w, y + h), (255, 0, 0), 2)
        file_name =  os.path.join(Namenpfad, "{} {:%Y-%m-%d_%H-%M-%S} - c {}.jpg".format(name, current_time, counter))
        print(file_name)

        cv2.imwrite(file_name + ".jpg", roi_gray)

        cv2.waitKey(300)
        cv2.imshow('Gesichtsspeicherung',gray)

        counter += 1
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

print ('Gesichtsspeicherung abgeschlossen')

cam.release()
cv2.destroyAllWindows()
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Schau Dir mal an, wie Du an welchen Stellen auf Dateien zugreifst, oder Verzeichnisse erzeugst. Ein Warnhinweis sollte sein, dass Du an verschiedenen Stellen fast gleiche Verzeichnisse zusammenbaust.
DonJuan
User
Beiträge: 12
Registriert: Donnerstag 15. März 2018, 20:51

Ich verstehe momentan nicht woran es liegen könnte...

ich erstelle den Pfad:

Code: Alles auswählen

Namenpfad = os.path.join(Personenpfad, name)
Ausgabe:
...\Personen\Max Mustermann

Dann speichere ich innerhalb dieses Pfads das Bild unter dem Namen: file_name ab, oder habe ich da einen Denkfehler?

Code: Alles auswählen

cv2.imwrite(file_name, roi_gray)
Es tut mir leid das ich da so nach hake, aber ich sitze schon seit heute morgen um 05:00 Uhr an diesem Problem :|
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

meine Gedanken/Fragen dazu:
- im Code oben wird dem Dateinamen zweimal .jpg zugewiesen
- wird das Unterverzeichnis mit dem Personennamen auch erstellt?
- wenn es ein Verzeichnis mit dem Namen der Person gibt, warum wird dem Dateinamen nochmals der Personenname zugewiesen?
- cv2.imwrite() liefert ein Boolean zurück, gib das mal aus, ich vermute False deutet auf einen Fehler beim schreiben
- gib imwrite mal manuell einen Pfadnamen ala imwrite('C:\cv2testdatei.jpg', roi_gray), wird diese Datei geschrieben?
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Habe mal aus Spaß an der Freud opencv installiert und deinen Code in einem Jupyter Notebook ausprobiert.
Der Ordner "Personen" mit Unterordner "Vorname Nachname" wird erstellt.
Die Bilddateien werden problemlos geschrieben, haben aber .jpg.jpg am Ende. Naja, leicht zu ändern.
Das bei dir keine Dateien geschrieben werden, liegt also nicht am Code.
cv2.imwrite() liefert bei mir True zurück, Dateien werden ja auch erstellt. Was gibt es bei dir zurück?
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@DonJuan: Du erzeugst den Pfad './Personen/' + name willst aber in os.path.join(Basispfad, "Personen", name) schreiben. Solange Du den Pfad auf zwei verschiedene Arten zusammensetzt, kann es halt sein, dass zwei verschiedene Orte dabei rauskommen. Die Lösung ist, die Variable »Namenpfad« so zu definieren, wie Du es möchtest (also entweder relativ zum Skript oder zum Arbeitsverzeichnis) und sie überall zu benutzen.


@ThomasL: danke ThomasL, dass Du den OP weiter verwirrst, indem Du schreibst, sein Code wäre richtig, obwohl schon drei andere Leute geduldig versuchen, ihm den Fehler, den er macht zu erklären.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Kann jetzt schlecht Bitte sagen, zu verwirren war ja nicht meine Absicht.
Ich stimme dir zu, mit der Aussage "liegt also nicht am Code" habe ich mich etwas zu weit aufs Glatteis gewagt.
Aus der Tatsache, dass der Code bei mir funktioniert auf Korrektheit in anderen Umgebungen zu schließen,
ist vermessen und da es bei ihm ja nicht läuft sogar falsch.
Da bin ich im Eifer übers Ziel hinaus geschossen.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Vicky
User
Beiträge: 5
Registriert: Mittwoch 20. Februar 2019, 12:50

Hallo, ich bin ganz neu im Forum und glaube, dass meine Frage hier ganz gut reinpasst, auch wenn sie mit der Ursprungsfrage nichts zu tun hat.

Folgender Code greift die Koordinaten des erkannten Bildes ab und macht es unscharf, um es dann anzuzeigen.

roi_color = img_frame[y:y + h, x:x + w]
roi_color = cv2.GaussianBlur(roi_color, (21,21), 0)
cv2.imshow("unscharf", roi_color)

Was ich möchte, ist aber kein neues Fenster, sondern dass direkt im Originalbild das Gesicht unscharf gezeichnet wird. Wie mache ich das?

Vielen Dank im Voraus!
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Vicky: Wie kann eine Frage hier ganz gut reinpassen die nichts mit der ursprünglichen Frage zu tun hat?

Wenn Du `img_frame` ändern möchtest, müsstest Du das Ergebnis von `GaussianBlur` wieder dem Bildausschnitt zuweisen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Vicky
User
Beiträge: 5
Registriert: Mittwoch 20. Februar 2019, 12:50

Super, vielen Dank, hat geklappt! Nächste Challenge: ich möchte das Gesicht nicht verschwommen anzeigen, sondern ein anderes Gesicht vor das Originalgesicht einblenden. Dazu habe ich eine Datei erstellt (sarah_gesicht_klein.jpg), die nur das Gesicht enthält. Es kommt aber ein Value Error could not broadcast input array from shape (594,480,3) into shape (175,175,3). Die Bildgröße der einzufügenden Datei mittels cv2.resize zu verändern bringt nichts, weil die Bezugsgröße sich ständig ändert. Wer weiß eine Lösung? Vielen Dank!

import cv2

video = cv2.VideoCapture(0)
sarah = cv2.imread("sarah_gesicht_klein.jpg")
while True:
check, frame = video.read()
frame = cv2.flip(frame, 1)
result_image = frame.copy()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
classifier = cv2.CascadeClassifier("c:/Users/vw/Kursmaterialien/data/haarcascades/haarcascade_frontalface_alt2.xml")
faces = classifier.detectMultiScale(gray, 1.1, minNeighbors=8)
for x, y, w, h in faces:
roi_color = frame[y:y + h, x:x + w]
result_image[y:y + roi_color.shape[0], x:x + roi_color.shape[1]] = sarah
cv2.imshow("Test", result_image)
key = cv2.waitKey(1)
if key == ord("q"):
break
print(frame)
video.release()
cv2.destroyAllWindows()
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Doch, genau das musst du tun. Für jeden Frame dein Gesicht auf die gewünschte Größe resizen bevor du es einkopierst.
Antworten