Python und OpenCV - Personenerkennung

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
behrangc2009
User
Beiträge: 7
Registriert: Freitag 24. Juli 2020, 19:31

Hallo zusammen, ich hoffe es geht Euch gut.

Leider befinde ich mich aktuell bei einem Problem mit Python in Verbindung mit OpenCV und habe die Hoffnung, dass mir hier erfahrene Programmierer weiterhelfen können.

Ich lerne aktuell gerade Python und OpenCV und bin seit mehr als einer Woche dabei einen Code "Human Detection" umzuschreiben. Den Code hänge ich hier als Bild an. Aktuell ist es so, dass der Code meine Webcam startet und das Programm erst mit der Taste Q beendet werden kann.
Da ich Bibliotheken aus OpenCV importiere ist dies nicht der komplette Code, womit die Detektion einer Person stattfindet. Da dieser Code nicht von mir stammt, habe ich das Problem festzustellen, in welchem Code (der importiert wird aus OpenCV) die eigentliche Detektion stattfindet.

Mein Ziel ist es, dass dieser Code umgeändert eine Person detektiert und sobald eine Person detektiert worden ist, das Programm von alleine beendet wird. Vielleicht bilde ich es mir nur ein, aber ich habe das Gefühl das ein erfahrener OpenCV-Programmierer weiterhelfen kann und bestimmt weiß, wo sich die Variable befindet, die verändert werden muss. An dieser Stelle müsste ich dann die Änderung vornehmen, damit das Programm von alleine beendet wird, sobald eine Person detektiert worden ist.

Ich freue mich auf Euer Feedback und bedanke mich im Voraus für eure Unterstützung.

Liebe Grüße
https://s12.directupload.net/images/200724/qxfw74fs.jpg
Zuletzt geändert von behrangc2009 am Freitag 24. Juli 2020, 19:54, insgesamt 1-mal geändert.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Code bitte in Text-Form und den dazugehörigen Tags hier veröffentlichen. Dazu im vollständigen Editor den </>-Knopf bemühen.

Edit: oder einfach den Link zu der Quelle für Deine Code. https://thedatafrog.com/en/articles/hum ... ion-video/

Ich sehe da jetzt nicht, das du eine Woche daran gearbeitet hast. Wieviel Python beherrschst du denn?
behrangc2009
User
Beiträge: 7
Registriert: Freitag 24. Juli 2020, 19:31

Hallo __deets__,

Edit: Richtig, den Code habe ich von dort. Richtig, ich habe keine Erfahrungen mit Python und OpenCV. Ich arbeite seit ca. einer Woche mit Python und OpenCV und versuche den zuständigen Code (der in diesem Code importiert wird) zu finden. Dort findet die Personenerkennung statt. ich habe mir auch diverse YouTube-Videos zum Thema "Human Detection" angesehen. Mit dem "arbeiten" meinte ich natürlich nicht das dieser Code von mir stammt. Ich habe oben geschrieben das der Code nicht von mir ist:)
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich sehe den "umschreiben" Teil nicht.

Wie dem auch sein. Die Kommentare sind doch recht eindeutig:

Code: Alles auswählen

    # detect people in the image
    # returns the bounding boxes for the detected objects
    boxes, weights = hog.detectMultiScale(frame, winStride=(8,8) )
Da wird die Erkennung gemacht. Fuer jeden vermeintlich entdeckten Menschen gibt es eine Box, mit einer Wahrscheinlichkeit, wie sehr da eine Uebereinstimmung ist. Hast du keine Boxen (also eine leere Liste), hast du keine Erkennung.

Womit du jetzt auch dein Abbruchkriterium hast: so lange laufen, bis es Boxen gibt, und dann abbrechen.
behrangc2009
User
Beiträge: 7
Registriert: Freitag 24. Juli 2020, 19:31

Hallo __deets__,

Danke Dir für die Info. Der Code ist entsprecheng geändert und wird auch ausgefürt. Sobald eine person detektiert worden ist, schließt das Webcamfenster, aber Python führt den Code weiterhin im Hintergrund aus. Woran liegt das? :(


# Die Variable, die bestimmt, ob die Schleife laufen soll oder nicht.
detected = False

So sieht nun die While-Schleife aus.
while not detected:
# Capture frame-by-frame
ret, frame = cap.read()

# resizing for faster detection
frame = cv2.resize(frame, (640, 480))
# using a greyscale picture, also for faster detection
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)

# detect people in the image
# returns the bounding boxes for the detected objects
boxes, weights = hog.detectMultiScale(frame, winStride=(8, 8))

boxes = np.array([[x, y, x + w, y + h] for (x, y, w, h) in boxes])
# falls die Boxen leer sind, wird keine Box angezeigt. Falls doch wird die Variable auf True gesetzt und abgebrochen.
if boxes.size != 0:
detected = True

for (xA, yA, xB, yB) in boxes:
# display the detected boxes in the colour picture
cv2.rectangle(frame, (xA, yA), (xB, yB),
(0, 255, 0), 2)

# Write the output video
out.write(frame.astype('uint8'))
# Display the resulting frame
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break

# When everything done, release the capture
cap.release()
# and release the output
out.release()
# finally, close the window
cv2.destroyAllWindows()
cv2.waitKey(1)

sys.exit(0)
Benutzeravatar
pintman
User
Beiträge: 39
Registriert: Freitag 2. Dezember 2005, 20:43
Kontaktdaten:

Formatiere doch bitte noch deinen Quelltext mit dem </>-Button im Editor, damit er für uns besser lesbar ist.
behrangc2009
User
Beiträge: 7
Registriert: Freitag 24. Juli 2020, 19:31

Tut mir Leid, daran habe ich gar nicht mehr gedacht:( Kann leider den Beitrag von vorhin nicht mehr bearbeiten. Hier der Code. Mittlerweile habe ich den Übeltäter gefunden. Ich weiß aber nicht, wie ich das Problem beheben soll. hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())

Wenn ich diesen Befehl deaktiviere, erfolgt keine Personenerkennung. Klammere ich auch hog = cv2.HOGDescriptor() aus bzw. setze den Befehl als Kommentar, läuft der Code problemlos durch und wird auch beendet. Wenn beide Befehle aktiv sind: Startet die Webcam, Personerkennung findet statt, Webcam-Fenster schließt, Video der Webcam wird abgespeichert, aber der Code läuft im Hintergrund noch weiter...

Code: Alles auswählen

import numpy as np
import cv2
import sys
# initialize the HOG descriptor/person detector
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())

cv2.startWindowThread()

# open webcam video stream
cap = cv2.VideoCapture(0)

# the output will be written to output.avi
out = cv2.VideoWriter(
    'output.avi',
    cv2.VideoWriter_fourcc(*'MJPG'),
    15.,
    (640, 480))
    
# Die Variable, die bestimmt, ob die Schleife laufen soll oder nicht.
detected = False

while not detected:
# Capture frame-by-frame
ret, frame = cap.read()

# resizing for faster detection
frame = cv2.resize(frame, (640, 480))
# using a greyscale picture, also for faster detection
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)

# detect people in the image
# returns the bounding boxes for the detected objects
boxes, weights = hog.detectMultiScale(frame, winStride=(8, 8))

boxes = np.array([[x, y, x + w, y + h] for (x, y, w, h) in boxes])
# falls die Boxen leer sind, wird keine Box angezeigt. Falls doch wird die Variable auf True gesetzt und abgebrochen.
if boxes.size != 0:
detected = True

for (xA, yA, xB, yB) in boxes:
# display the detected boxes in the colour picture
cv2.rectangle(frame, (xA, yA), (xB, yB),
(0, 255, 0), 2)

# Write the output video
out.write(frame.astype('uint8'))
# Display the resulting frame
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break

# When everything done, release the capture
cap.release()
# and release the output
out.release()
# finally, close the window
cv2.destroyAllWindows()
cv2.waitKey(1)

sys.exit(0)
behrangc2009
User
Beiträge: 7
Registriert: Freitag 24. Juli 2020, 19:31

Hallo zusammen,

also ich habe den bestehenden komplett über Bord geworfen und der Code funktioniert jetzt auch, aber entspricht noch nicht ganz meiner Vorstellung.

Der Code greift auf eine MKV-Datei zu (Video das währendessen von Kinovea aufgenommen wird) und versucht da nach besten Wissen und Gewissen eine Person zu erkennen. Das führt der Code auch aus. Natürlich dauert es eine gewisse Zeit, da die Aufnahme paar Sekunden vorher startet und anschließend der Python Code, der zu Beginn auf die MKV-Datei zugreift.

Nun ist es so, dass ich es nicht schaffe mein Abbruchkriterium zu realisieren. Der Code soll sobald eine Person im Video erkannt wird beendet werden. Ich habe versucht ein break einzubauen (Im Code kenntlich), aber dies führt nicht zum Erfolg. Stattdessen hängt sich Python auf und im Fenster, in dem eigtl. vorher das Video angezeigt und die Personenerkennung stattfindet, ist nicht zu sehen und es lädt und lädt. Was mache ich falsch? Bitte beachtet, dass eine Liveaufnahme nicht möglich ist zum aktuellen Zeitpunkt. Wenn ich eine Aufnahme über ein externes Programm starte und mit Python ebenfalls einen Livestream, gibt mir Python eine Fehlermeldung zurück, da ich mit einer Webcam nur für ein "Programm" quasi Zugriff habe. Dafür habe ich keine Lösung gefunden, daher sah ich nur die Lösung mit dem Verändern des Codes.

Code: Alles auswählen

import cv2
import glob
import os

#Vorgabe fuer Stammverzeichnis und Auswahl aktuellster Datei
parent_dir = r"C:\Users\Behra\PycharmProjects\OpencvPython"
files_path = os.path.join(parent_dir, '*.mkv')
files = sorted(glob.iglob(files_path), key=os.path.getctime, reverse=True)
latest_mkv_file = files[0]

#Algorithmus f�r FaceDetection
faceCascade = cv2.CascadeClassifier('face_detector.xml')

#Videofile wird der Capture-Prozedur �bergeben
video_capture = cv2.VideoCapture(latest_mkv_file)

#While-Schleife liest Frame fuer Frame ein
while True:
    # Capture frame-by-frame
    ret, frame = video_capture.read()

    #F�r den Algorithmus ist jedes Frame zwecks Analyse in Graustufen umzuwandeln
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(30, 30),
        flags=cv2.CASCADE_SCALE_IMAGE
    )
    #Test, ob Grau-Umwandlung funktioniert
    #cv2.imshow('gray', gray)
    # Zeichne jeweils ein gr�nes Rechteck um erkannte Gesichter
    x = None
    for (x, y, w, h) in faces:
        cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
        break <<<<<<<<<<< Dieses Break führt leider zu dem oben beschriebenen Problem..

    # Zeige das Ergebnis
    cv2.imshow('Video', frame)

# hier wird am Schluss alles geordnet aufgel�st
video_capture.release()
cv2.destroyAllWindows()
Ich hoffe auf Eure Hilfe und Euer Feedback von erfahreneren Python-Programmieren..

Liebe Grüße
Benutzeravatar
pintman
User
Beiträge: 39
Registriert: Freitag 2. Dezember 2005, 20:43
Kontaktdaten:

Das break beendet nur die Schleife, in der es sich direkt befindet. In diesem Falle also die for-Schleife.

Du könntest eine Variable person_erkannt mit False initialisieren und diese mit while prüfen. Beim Erkennen einer Person wird person_erkannt auf True gesetzt und damit die while-Schleife beendet.
behrangc2009
User
Beiträge: 7
Registriert: Freitag 24. Juli 2020, 19:31

@pintman: Lieben Dank für die schnelle Rückmeldung und den Tipp:)

Kurze Rückfrage: Meinst Du eine neue While-Schleife?
Benutzeravatar
pintman
User
Beiträge: 39
Registriert: Freitag 2. Dezember 2005, 20:43
Kontaktdaten:

Die bestehende while-Schleife kann weiterhin dafür verwendet werden. Etwa so

Code: Alles auswählen

person_erkannt = False
while not person_erkannt:
    ....
    if erkenne_person():
        person_erkannt = True

Benutzeravatar
__blackjack__
User
Beiträge: 13927
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Da eine neue Variable einzuführen ist unnötig, denn an der Stelle wo das ``person_erkannt = True`` steht, kann man ja einfach ein ``break`` setzen. Das geht im vorliegenden Code ja nur nicht weil statt eines ``if`` da eine ``for``-Schleife steht die gar keine Schleife ist weil sie grundsätzlich beim ersten Durchlauf abgebrochen wird.
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
behrangc2009
User
Beiträge: 7
Registriert: Freitag 24. Juli 2020, 19:31

@blackjack

Die For-Schleife wird genutzt, damit jeweils ein grünes Rechteck um erkannte Gesichter gezeichnet wird. Und sobald eine Person erkannt wird, soll der Code beendet sein und das klappt leider nicht. Die Personenerkennung selbst findet ja im Code viel früher statt faces = faceCascade.detectMultiScale(
Hier wird die Personenerkennung durchgeführt und im Ordner mit dem Python Code befindet sich noch eine facedetector.xml-Datei.

Und diesen vorgefertigten Algorithmus verwende ich:

Code: Alles auswählen

 #Algorithmus für FaceDetection
faceCascade = cv2.CascadeClassifier('face_detector.xml')
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das hat __blackjack__ schon verstanden. Was du nicht verstanden hast ist seine Anmerkung: der original Code hat alle erkannten Menschen markiert. Das tut er mit einer Schleife. Weil es mehrere sein können. Du willst aber nur wissen, ob keiner oder mehrere Menschen erkannt wurden. Die for Schleife muss als weg. Und durch eine if-Anfrage ersetzt werden. Und DIE führt dann das Break für die while schleife aus.
Antworten