Mostrar un feed de webcam usando OpenCV y Python


He estado tratando de crear un programa simple con Python que usa OpenCV para obtener una fuente de video de mi webcam y mostrarla en la pantalla.

Sé que estoy allí en parte porque la ventana se crea y la luz en mi webcam se enciende, pero simplemente no parece mostrar nada en la ventana. Espero que alguien pueda explicar lo que estoy haciendo mal.

import cv

cv.NamedWindow("w1", cv.CV_WINDOW_AUTOSIZE)
capture = cv.CaptureFromCAM(0)

def repeat():

    frame = cv.QueryFrame(capture)
    cv.ShowImage("w1", frame)


while True:
    repeat()

En una nota no relacionada, he notado que mi cámara web a veces cambia su número de índice en cv.CaptureFromCAM, y a veces necesito poner 0, 1 o 2 aunque solo tengo una cámara conectada y no la he desenchufado (lo sé porque la luz no se enciende a menos que cambie el índice). ¿Hay alguna manera de conseguir que Python determine el índice correcto?

Author: Peter Mortensen, 2010-04-08

6 answers

Intenta agregar la línea c = cv.WaitKey(10) en la parte inferior de tu método repeat().

Esto espera 10 ms para que el usuario ingrese una clave. Incluso si no estás usando la llave, pon esto. Creo que solo tenía que haber algún retraso, por lo que time.sleep(10) también puede funcionar.

Con respecto al índice de la cámara, podrías hacer algo como esto:

for i in range(3):
    capture = cv.CaptureFromCAM(i)
    if capture: break

Esto encontrará el índice del primer dispositivo de captura "de trabajo", al menos para los índices de 0-2. Es posible que haya varios dispositivos en su computadora reconocida como un dispositivo de captura adecuado. La única forma que conozco de confirmar que tienes la correcta es mirando manualmente tu luz. Tal vez obtener una imagen y comprobar sus propiedades?

Para agregar un mensaje de usuario al proceso, puede vincular una tecla para cambiar cámaras en su bucle de repetición:

import cv

cv.NamedWindow("w1", cv.CV_WINDOW_AUTOSIZE)
camera_index = 0
capture = cv.CaptureFromCAM(camera_index)

def repeat():
    global capture #declare as globals since we are assigning to them now
    global camera_index
    frame = cv.QueryFrame(capture)
    cv.ShowImage("w1", frame)
    c = cv.WaitKey(10)
    if(c=="n"): #in "n" key is pressed while the popup window is in focus
        camera_index += 1 #try the next camera index
        capture = cv.CaptureFromCAM(camera_index)
        if not capture: #if the next camera index didn't work, reset to 0.
            camera_index = 0
            capture = cv.CaptureFromCAM(camera_index)

while True:
    repeat()

Descargo de responsabilidad: No he probado esto, por lo que puede tener errores o simplemente no funciona, pero podría darle al menos una idea de una solución.

 41
Author: Matt Boehm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-01 23:04:09

Una actualización para mostrar cómo hacerlo en las versiones recientes de OpenCV:

import cv2

cv2.namedWindow("preview")
vc = cv2.VideoCapture(0)

if vc.isOpened(): # try to get the first frame
    rval, frame = vc.read()
else:
    rval = False

while rval:
    cv2.imshow("preview", frame)
    rval, frame = vc.read()
    key = cv2.waitKey(20)
    if key == 27: # exit on ESC
        break

cv2.destroyWindow("preview")
vc.release()

Funciona en OpenCV-2.4.2 para mí.

 69
Author: sastanin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-02 06:28:38

Si solo tiene una cámara, o no le importa qué cámara es la correcta, use "-1" como índice. Ie para su ejemplo capture = cv.CaptureFromCAM(-1).

 7
Author: TinBane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-26 13:25:46

Intente lo siguiente. Es simple, pero aún no he descubierto una forma elegante de salir.

import cv2.cv as cv
import time

cv.NamedWindow("camera", 0)

capture = cv.CaptureFromCAM(0)

while True:
    img = cv.QueryFrame(capture)
    cv.ShowImage("camera", img)
    if cv.WaitKey(10) == 27:
        break
cv.DestroyAllWindows()
 1
Author: user808996,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-27 20:28:08

Cambiar import cv a import cv2.cv as cv Ver también el post aquí.

 1
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-28 00:35:06

Al igual que en el opencv-doc puede obtener la transmisión de video de una cámara que está conectada a su computadora siguiendo el código.

import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    # Our operations on the frame come here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # Display the resulting frame
    cv2.imshow('frame',gray)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

Puede cambiar el índice cap = cv2.VideoCapture(0) de 0 a 1 para acceder a la 2ª cámara.
Probado en opencv-3.2.0

 1
Author: Ramesh-X,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-09 17:57:21