59

I have been trying to create a simple program with Python which uses OpenCV to get a video feed from my webcam and display it on the screen.

I know I am partly there because the window is created and the light on my webcam flicks on, but it just doesn't seem to show anything in the window. Hopefully someone can explain what I'm doing wrong.

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

On an unrelated note, I have noticed that my webcam sometimes changes its index number in cv.CaptureFromCAM, and sometimes I need to put in 0, 1 or 2 even though I only have one camera connected and I haven't unplugged it (I know because the light doesn't come on unless I change the index). Is there a way to get Python to determine the correct index?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mitch
  • 613
  • 2
  • 7
  • 5

6 Answers6

83

An update to show how to do it in the recent versions of 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()

It works in OpenCV-2.4.2 for me.

rayryeng
  • 102,964
  • 22
  • 184
  • 193
sastanin
  • 40,473
  • 13
  • 103
  • 130
  • 5
    Thanks. One suggestion: after the while loop, add: cv2.destroyWindow("preview") – Luke Nov 16 '13 at 03:59
  • 9
    Another suggestion: after the while loop, add vc.release(). Otherwise you can't run it again without killing the process since the handle is still open. – Jay Borseth Feb 17 '14 at 21:57
  • +1: Thanks! worked on linux, (python 2.7, all packages installed by apt-get) instantly! – Valentin H Sep 25 '14 at 08:32
42

Try adding the line c = cv.WaitKey(10) at the bottom of your repeat() method.

This waits for 10 ms for the user to enter a key. Even if you're not using the key at all, put this in. I think there just needed to be some delay, so time.sleep(10) may also work.

In regards to the camera index, you could do something like this:

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

This will find the index of the first "working" capture device, at least for indices from 0-2. It's possible there are multiple devices in your computer recognized as a proper capture device. The only way I know of to confirm you have the right one is manually looking at your light. Maybe get an image and check its properties?

To add a user prompt to the process, you could bind a key to switching cameras in your repeat loop:

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

disclaimer: I haven't tested this so it may have bugs or just not work, but might give you at least an idea of a workaround.

Matt Boehm
  • 1,894
  • 1
  • 18
  • 21
  • that one little line of code worked a treat! thanks so much. however the camera index code didnt work, whatever device it sees at index 0 still returns true and breaks the for loop. this must be why so many examples i have all just show a black screen. is there any way to determine what is at index 0 so that i can turn it off? or alternatively change the webcam to 0? – Mitch Apr 09 '10 at 14:24
  • hmm, I'm not sure if there's an easy way to do this. rather than just verifying that capture is not a Nonetype, you could write more complicated code to query a frame and check if the frame is "all black" by maybe randomly sampling a few pixels therein. I think it may be better to just provide a prompt which shows a frame and asks the user if they want this camera or to try the next one. – Matt Boehm Apr 12 '10 at 16:17
  • Take a look at my edit above if you'd consider using user input to change cameras. – Matt Boehm Apr 12 '10 at 16:30
  • I get an error because highgui is not found. I tried 'import highgui' and other ways without luck. I installed opencv via homebrew on a mac – rtacconi Apr 29 '11 at 11:44
  • 2
    @rtacconi Replace that line with `c = cv.WaitKey(10)` – Amit Kotlovski May 09 '11 at 21:27
  • OP, did you mean: `for i in range(3): capture = cv.CaptureFromCAM(i)`. (i instead of 0) – AlcubierreDrive Jan 30 '12 at 08:44
  • I still have a black image here, even with the WaitKey. On MacBook with isight, OS X 10.8 and that latest openCV from Homebrew... – Antonvh Oct 16 '13 at 16:32
8

If you only have one camera, or you don't care which camera is the correct one, then use "-1" as the index. Ie for your example capture = cv.CaptureFromCAM(-1).

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
TinBane
  • 866
  • 11
  • 19
2

As in the opencv-doc you can get video feed from a camera which is connected to your computer by following code.

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

You can change cap = cv2.VideoCapture(0) index from 0 to 1 to access the 2nd camera.
Tested in opencv-3.2.0

Ramesh-X
  • 4,853
  • 6
  • 46
  • 67
1

change import cv to import cv2.cv as cv See also the post here.

David
  • 15,894
  • 22
  • 55
  • 66
1

Try the following. It is simple, but I haven't figured out a graceful way to exit yet.

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()
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user808996
  • 179
  • 4
  • 15