2016-08-05 15 views
4

Dlib hat eine sehr praktische, schnelle und effiziente Objekterkennungsroutine, und ich wollte ein cooles Face-Tracking-Beispiel ähnlich dem Beispiel here machen.Was ist falsch mit dieser Webcam Gesichtserkennung?

OpenCV, das weit verbreitet ist, hat VideoCapture-Modul, das ziemlich schnell ist (eine Sekunde zum Schnappschuss verglichen mit 1 Sekunde oder mehr für den Aufruf eines Programms, das die Webcam weckt und ein Bild holt). Ich habe das zum Python-Gesichtserkennungs-Beispiel in Dlib hinzugefügt.

Wenn Sie die OpenCV VideoCapture-Ausgabe direkt anzeigen und verarbeiten, sieht das seltsam aus, weil OpenCV offenbar BGR statt RGB-Reihenfolge speichert. Danach Einstellung, es funktioniert, aber langsam:

from __future__ import division 
import sys 

import dlib 
from skimage import io 


detector = dlib.get_frontal_face_detector() 
win = dlib.image_window() 

if len(sys.argv[1:]) == 0: 
    from cv2 import VideoCapture 
    from time import time 

    cam = VideoCapture(0) #set the port of the camera as before 

    while True: 
     start = time() 
     retval, image = cam.read() #return a True bolean and and the image if all go right 

     for row in image: 
      for px in row: 
       #rgb expected... but the array is bgr? 
       r = px[2] 
       px[2] = px[0] 
       px[0] = r 
     #import matplotlib.pyplot as plt 
     #plt.imshow(image) 
     #plt.show() 

     print("readimage: " + str(time() - start)) 

     start = time() 
     dets = detector(image, 1) 
     print "your faces: %f" % len(dets) 
     for i, d in enumerate(dets): 
      print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(
       i, d.left(), d.top(), d.right(), d.bottom())) 
      print("from left: {}".format(((d.left() + d.right())/2)/len(image[0]))) 
      print("from top: {}".format(((d.top() + d.bottom())/2) /len(image))) 
     print("process: " + str(time() - start)) 

     start = time() 
     win.clear_overlay() 
     win.set_image(image) 
     win.add_overlay(dets) 

     print("show: " + str(time() - start)) 
     #dlib.hit_enter_to_continue() 



for f in sys.argv[1:]: 
    print("Processing file: {}".format(f)) 
    img = io.imread(f) 
    # The 1 in the second argument indicates that we should upsample the image 
    # 1 time. This will make everything bigger and allow us to detect more 
    # faces. 
    dets = detector(img, 1) 
    print("Number of faces detected: {}".format(len(dets))) 
    for i, d in enumerate(dets): 
     print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(
      i, d.left(), d.top(), d.right(), d.bottom())) 

    win.clear_overlay() 
    win.set_image(img) 
    win.add_overlay(dets) 
    dlib.hit_enter_to_continue() 


# Finally, if you really want to you can ask the detector to tell you the score 
# for each detection. The score is bigger for more confident detections. 
# Also, the idx tells you which of the face sub-detectors matched. This can be 
# used to broadly identify faces in different orientations. 
if (len(sys.argv[1:]) > 0): 
    img = io.imread(sys.argv[1]) 
    dets, scores, idx = detector.run(img, 1) 
    for i, d in enumerate(dets): 
     print("Detection {}, score: {}, face_type:{}".format(
      d, scores[i], idx[i])) 

Vom Ausgang der Zeitpunkte in diesem Programm, es Verarbeitung und packte das Bild scheint jeweils ein Fünftel einer Sekunde nehmen, so könnte man denken, es sollte zeigen Ein oder zwei Updates pro Sekunde - wenn Sie jedoch Ihre Hand heben, wird dies in der Webcam nach ca. 5 Sekunden angezeigt!

Gibt es eine Art internen Cache, der verhindert, dass das neueste Webcam-Bild erfasst wird? Kann ich den Webcam-Eingabeprozess anpassen oder mit mehreren Threads versehen, um die Verzögerung zu beheben? Dies ist auf einem Intel i5 mit 16 GB RAM.

aktualisieren

hier Nach schlägt es die Lese ein Video Frame für Frame packt. Dies würde erklären, dass es das nächste Bild und das nächste Bild aufnimmt, bis es schließlich alle Bilder erfasst, die während der Verarbeitung erfasst wurden. Ich frage mich, ob es eine Option gibt, um die Framerate zu setzen oder setzen Sie Frames und klicken Sie einfach auf ein Bild des Gesichts in der Webcam jetzt auf lesen? http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_gui/py_video_display/py_video_display.html#capture-video-from-camera

+0

Die Zeit wird von dlib benötigt, um das Bild zu erkennen. Sie könnten versuchen, das Bild für eine bessere Leistung auf kleinere Abmessungen zu skalieren. – ZdaR

+0

@ZdaR Danke für den Vorschlag. Bitte führen Sie das Beispiel aus, Sie werden sehen, dass das nur einen Bruchteil einer Sekunde dauert. Warum dauert es fast 5 Sekunden vom Bewegen bis zur Anzeige der Bewegung im Webcam-Fenster (mit vielen Zwischenrahmen, die angezeigt werden, bevor sie aktuell sind?) Das ist die Frage. – NoBugs

+0

Was ist die Kameraauflösung und die Gesichtsgröße? – Evgeniy

Antwort

0

Ich versuchte Multithreading, und es war genauso langsam, dann Multithread nur mit der .read() im Thread, keine Verarbeitung, keine Threadverriegelung, und es funktionierte ziemlich schnell - vielleicht 1 Sekunde oder so der Verzögerung, nicht 3 oder 5. Siehe http://www.pyimagesearch.com/2015/12/21/increasing-webcam-fps-with-python-and-opencv/

from __future__ import division 
import sys 
from time import time, sleep 
import threading 

import dlib 
from skimage import io 


detector = dlib.get_frontal_face_detector() 
win = dlib.image_window() 

class webCamGrabber(threading.Thread): 
    def __init__(self): 
     threading.Thread.__init__(self) 
     #Lock for when you can read/write self.image: 
     #self.imageLock = threading.Lock() 
     self.image = False 

     from cv2 import VideoCapture, cv 
     from time import time 

     self.cam = VideoCapture(0) #set the port of the camera as before 
     #self.cam.set(cv.CV_CAP_PROP_FPS, 1) 


    def run(self): 
     while True: 
      start = time() 
      #self.imageLock.acquire() 
      retval, self.image = self.cam.read() #return a True bolean and and the image if all go right 

      print(type(self.image)) 
      #import matplotlib.pyplot as plt 
      #plt.imshow(image) 
      #plt.show() 

      #print("readimage: " + str(time() - start)) 
      #sleep(0.1) 

if len(sys.argv[1:]) == 0: 

    #Start webcam reader thread: 
    camThread = webCamGrabber() 
    camThread.start() 

    #Setup window for results 
    detector = dlib.get_frontal_face_detector() 
    win = dlib.image_window() 

    while True: 
     #camThread.imageLock.acquire() 
     if camThread.image is not False: 
      print("enter") 
      start = time() 

      myimage = camThread.image 
      for row in myimage: 
       for px in row: 
        #rgb expected... but the array is bgr? 
        r = px[2] 
        px[2] = px[0] 
        px[0] = r 


      dets = detector(myimage, 0) 
      #camThread.imageLock.release() 
      print "your faces: %f" % len(dets) 
      for i, d in enumerate(dets): 
       print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(
        i, d.left(), d.top(), d.right(), d.bottom())) 
       print("from left: {}".format(((d.left() + d.right())/2)/len(camThread.image[0]))) 
       print("from top: {}".format(((d.top() + d.bottom())/2) /len(camThread.image))) 
      print("process: " + str(time() - start)) 

      start = time() 
      win.clear_overlay() 
      win.set_image(myimage) 
      win.add_overlay(dets) 

      print("show: " + str(time() - start)) 
      #dlib.hit_enter_to_continue() 



for f in sys.argv[1:]: 
    print("Processing file: {}".format(f)) 
    img = io.imread(f) 
    # The 1 in the second argument indicates that we should upsample the image 
    # 1 time. This will make everything bigger and allow us to detect more 
    # faces. 
    dets = detector(img, 1) 
    print("Number of faces detected: {}".format(len(dets))) 
    for i, d in enumerate(dets): 
     print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(
      i, d.left(), d.top(), d.right(), d.bottom())) 

    win.clear_overlay() 
    win.set_image(img) 
    win.add_overlay(dets) 
    dlib.hit_enter_to_continue() 


# Finally, if you really want to you can ask the detector to tell you the score 
# for each detection. The score is bigger for more confident detections. 
# Also, the idx tells you which of the face sub-detectors matched. This can be 
# used to broadly identify faces in different orientations. 
if (len(sys.argv[1:]) > 0): 
    img = io.imread(sys.argv[1]) 
    dets, scores, idx = detector.run(img, 1) 
    for i, d in enumerate(dets): 
     print("Detection {}, score: {}, face_type:{}".format(
      d, scores[i], idx[i])) 
0

Wenn Sie einen Rahmen in OpenCV lesen zeigen möchten, können Sie es tun mit Hilfe von cv2.imshow() Funktion, ohne dass von den Farben, um zu ändern. Auf der anderen Seite, wenn Sie immer noch das Bild in matplotlib zeigen wollen, dann vermeiden Sie können nicht die Methoden, wie dies mit:

b,g,r = cv2.split(img) 
img = cv2.merge((b,g,r)) 

Das ist das einzige, was ich Ihnen jetzt helfen =)

+0

Ich denke, dass Dlib das Array in der Reihenfolge benötigt, die es erwartet ... oder es kann nicht richtig erkennen? Wahrscheinlich OK für den HOGS-Algorithmus, da ich die Farbe des Objekts geändert habe und es immer durch die Form OK erkennt. – NoBugs

+0

Nun, sobald alle diese Algorithmen auf Matrizen arbeiten, gibt es keinen Unterschied in der Reihenfolge der Farben. Und auch die Erkennungsalgorithmen nehmen meist Schwarz-Weiß-Fotos auf, was auch ein Plus für alle ist, die keine Probleme mit Farben haben wollen. – Oresto

+0

OpenCV hat auch seine eigenen Erkennungsalgorithmen, die wiederum Schwarz-Weiß-Bilder zur Erkennung verwenden. – Oresto

1

Ich fühle deinen Schmerz. Ich habe vor kurzem mit diesem Webcam-Skript gearbeitet (mehrere Iterationen; wesentlich bearbeitet). Ich habe es wirklich gut gemacht, denke ich. Damit Sie sehen können, was ich getan habe, habe ich einen GitHub Gist mit den Details (Code, HTML Readme-Datei, Beispielausgabe):

https://gist.github.com/victoriastuart/8092a3dd7e97ab57ede7614251bf5cbd

+0

Python3.5 auch. Nett! – NoBugs

1

Vielleicht ist das Problem, dass es einen Schwellenwert gesetzt ist. Wie beschrieben here

dots = detector(frame, 1) 

zu

geändert werden sollte
dots = detector(frame) 

einen Schwellenwert zu vermeiden. Das ist für mich funktioniert, aber zur gleichen Zeit gibt es ein Problem, dass Frames zu schnell verarbeitet werden.

+1

Dies ist KEINE Schwelle. In der Python-API gibt es eine Reihe von Bild-Upscales, bevor der Detektor ausgeführt wird. In diesem speziellen Fall bedeutet "1" "ein Bild einmal hochskalieren". Dies wird natürlich die Verarbeitungszeit erhöhen (aber kleinere Flächen erkennen). –

+0

Vielen Dank für die Klärung, Alexey! – kozlone

Verwandte Themen