使用OpenCV和Python显示网络摄像头视频流

59

我一直在尝试使用Python编写一个简单的程序,利用OpenCV从我的网络摄像头获取视频并在屏幕上显示。

我知道我已经有了一部分进展,因为窗口已经创建并且我的网络摄像头上的灯光闪烁,但它似乎没有在窗口中显示任何内容。希望有人能解释我做错了什么。

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

顺便提一下,我注意到我的网络摄像头有时会在cv.CaptureFromCAM中更改其索引号,有时我需要输入0、1或2,即使我只连接了一个相机并且没有拔掉它(我知道这一点是因为灯不亮,除非我更改索引)。有办法让Python确定正确的索引吗?

6个回答

83

以下是最近版本的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()

对我来说,在OpenCV-2.4.2中可以工作。


5
谢谢。一个建议:在while循环后面添加以下内容:cv2.destroyWindow("preview") - Luke
9
另一个建议:在 while 循环后添加 vc.release()。否则,由于句柄仍然打开,您无法再次运行它而不终止进程。 - Jay Borseth
+1:谢谢!在Linux上工作得很好,(Python 2.7,所有包都是通过apt-get安装的),立即就可以使用! - Valentin H

42
尝试在repeat()方法的底部添加一行c = cv.WaitKey(10),它会等待用户输入一个按键,至少等待10毫秒。即使您根本没有使用该键,也请将其放入其中。我认为只需要一些延迟,所以time.sleep(10)也可以。
关于相机索引,您可以这样做:
for i in range(3):
    capture = cv.CaptureFromCAM(i)
    if capture: break

这将找到第一个“working”捕获设备的索引,至少在0-2的索引中。 你的电脑可能有多个被识别为合适的捕获设备的设备。 我所知道的唯一确认你拥有正确设备的方法是手动观察光线。 也许获取图像并检查其属性?
要向过程添加用户提示,您可以将密钥绑定到重复循环中切换相机:
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()

免责声明:我没有测试过这个方法,它可能存在缺陷或者不能正常工作,但是可能会给你提供一个解决问题的思路。


如果您考虑使用用户输入来更改相机,请查看我上面的编辑。 - Matt Boehm
我遇到了一个错误,因为找不到highgui。我尝试了“import highgui”和其他方法,但都没有成功。我在Mac上通过Homebrew安装了OpenCV。 - rtacconi
2
请将该行代码替换为 c = cv.WaitKey(10) - Amit Kotlovski
OP,你是不是想说:for i in range(3): capture = cv.CaptureFromCAM(i)。(0 改成了 i) - AlcubierreDrive
即使使用WaitKey,我在这里仍然有一个黑色图像。在配备iSight、OS X 10.8和Homebrew的最新openCV的MacBook上... - Antonvh
显示剩余2条评论

8
如果你只有一台相机,或者你不关心哪一个相机是正确的,则使用“-1”作为索引。例如,在你的例子中,capture = cv.CaptureFromCAM(-1)

2

如同在opencv-doc中所示,你可以通过以下代码从连接到计算机的相机获取视频流。

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

您可以将cap = cv2.VideoCapture(0)中的索引从0更改为1,以访问第二个相机。
opencv-3.2.0中测试通过。


1
尝试以下操作。这很简单,但我还没有找到一个优雅的退出方式。
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

import cv 更改为 import cv2.cv as cv 另请参阅此处的帖子 here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接