使用OpenCV和Python显示摄像头画面

59 投票
6 回答
136974 浏览
提问于 2025-04-15 21:23

我一直在尝试用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 个回答

8

如果你只有一台摄像头,或者你不在乎哪一台摄像头是正确的,那就用“-1”作为索引。比如在你的例子中,可以这样写:capture = cv.CaptureFromCAM(-1)

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可以正常工作。

42

试着在你的 repeat() 方法的最后加上一行 c = cv.WaitKey(10)

这行代码会让程序等待10毫秒,看看用户是否按下了键。即使你根本不打算用到这个按键,也可以加上这行。我觉得可能需要一些延迟,所以 time.sleep(10) 也许可以达到同样的效果。

关于摄像头的索引,你可以这样做:

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

这段代码会找到第一个“正常工作”的捕捉设备的索引,至少在索引范围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()

免责声明:我没有测试过这个,所以可能会有bug或者根本不工作,但至少可以给你一个解决方法的思路。

撰写回答