2016-08-05 4 views
4

У Dlib есть действительно удобная, быстрая и эффективная процедура обнаружения объектов, и я хотел сделать крутой пример отслеживания лица, подобный примеру here.Что случилось с этим обнаружением лица веб-камеры?

У поддерживаемого устройства OpenCV имеется довольно быстрый модуль VideoCapture (пятая часть секунды для моментального снимка по сравнению с 1 секундой или более для вызова программы, которая пробуждает веб-камеру и извлекает изображение). Я добавил это к примеру Python для детектирования лица в Dlib.

Если вы непосредственно показываете и обрабатываете вывод OpenCV VideoCapture, это выглядит странно, потому что, по-видимому, OpenCV хранит BGR вместо RGB-заказа. После настройки этого, она работает, но медленно:

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])) 

С выхода таймингами в этой программе, кажется, обработки и захвата картины каждый принимает одну пятую секунды, так что вы могли бы подумать, что должно показать один или два обновления в секунду - однако, если вы поднимете руку, она отобразится в режиме просмотра веб-камеры через 5 секунд или около того!

Есть ли какой-то внутренний кеш, чтобы он не захватывал последнее изображение веб-камеры? Могу ли я настроить или многопоточный процесс ввода веб-камеры, чтобы исправить отставание? Это на Intel i5 с 16-гигабайтной оперативной памятью.

Update

Согласно здесь, это предполагает чтение захватывает видео кадр за кадром. Это объясняет, что он захватывает следующий кадр и следующий кадр, пока он, наконец, не догнал все кадры, которые были захвачены во время обработки. Интересно, есть ли опция установить частоту кадров или установить ее для удаления кадров и просто щелкнуть изображение лица в веб-камере сейчас на чтение? http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_gui/py_video_display/py_video_display.html#capture-video-from-camera

+0

Время, затраченное dlib для обнаружения изображения, вы можете попробовать изменить размер изображения на меньшие размеры для лучшей производительности. – ZdaR

+0

@ZdaR Спасибо за предложение. Пожалуйста, запустите пример, вы увидите, что занимает всего одну секунду. Почему требуется переместить почти 5 секунд, чтобы показать перемещение в окне веб-камеры (со многими промежуточными кадрами, показанными до его обновления?) Это вопрос. – NoBugs

+0

Что такое разрешение камеры и размер лица? – Evgeniy

ответ

0

Я пробовал многопоточность, и это было так же медленно, затем я многопользовал только .read() в потоке, без обработки, без блокировки потока, и он работал довольно быстро - может быть, 1 секунда или около того задержки, а не 3 или 5. См. 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

Если вы хотите показать фрейм, прочитанный в OpenCV, вы можете сделать это с помощью функции cv2.imshow() без необходимости изменения порядка цветов. С другой стороны, если вы все еще хотите, чтобы показать картину в Matplotlib, то вы не можете избежать с помощью методов, как это:

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

Это единственное, что я могу помочь вам с сейчас =)

+0

Я думаю, что Dlib может понадобиться массив в том порядке, который он ожидает ... или он может не обнаруживать право? Возможно, ОК для алгоритма HOGS, поскольку я изменил цвет объекта, и он всегда определяет его в форме формы. – NoBugs

+0

хорошо, как только все эти алгоритмы работают на матрицах, нет никакой разницы в том, какой порядок цветов. А также, алгоритмы обнаружения обычно принимают черно-белые фотографии, что также является плюсом для тех, кто не хочет иметь проблемы с цветами. – Oresto

+0

Кроме того, OpenCV имеет свои собственные алгоритмы обнаружения, которые, опять же, используют черно-белые изображения для обнаружения. – Oresto

1

Я чувствую вашу боль. Недавно я работал с этим сценарием веб-камеры (несколько итераций, по существу редактировалось). Думаю, мне понравилось работать. Так что вы можете увидеть, что я сделал, я создал GIST GitHub с деталями (код; HTML ридми файл; выходной образец):

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

+0

Python3.5 тоже. Ницца! – NoBugs

1

Может быть, проблема в том, что существует пороговое значение. Как описано here

dots = detector(frame, 1) 

должен быть изменен на

dots = detector(frame) 

Чтобы избежать порога. Это работает для меня, но в то же время существует проблема, что кадры обрабатываются слишком быстро.

+1

Это не порог. В API-интерфейсе python перед запуском детектора используется ряд улучшений изображения. В этом конкретном случае «1» означает «масштабировать изображение один раз». Это, конечно, увеличит тайминги обработки (но позволит обнаружить меньшие грани). –

+0

Большое спасибо за разъяснение, Алексей! – kozlone

 Смежные вопросы

  • Нет связанных вопросов^_^