【问题标题】:Displaying a webcam feed using OpenCV and Python使用 OpenCV 和 Python 显示网络摄像头源
【发布时间】:2011-02-05 18:28:17
【问题描述】:

我一直在尝试使用 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 确定正确的索引?

【问题讨论】:

    标签: python opencv webcam


    【解决方案1】:

    显示如何在最新版本的 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。

    【讨论】:

    • 谢谢。一个建议:在while循环之后,添加:cv2.destroyWindow("preview")
    • 另一个建议:在while循环之后,添加vc.release()。否则你不能在不终止进程的情况下再次运行它,因为句柄仍然打开。
    • +1:谢谢!立即在 linux 上工作,(python 2.7,apt-get 安装的所有软件包)!
    【解决方案2】:

    尝试在 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()
    

    免责声明:我尚未对此进行测试,因此它可能存在错误或无法正常工作,但至少可以让您了解解决方法。

    【讨论】:

    • 一小行代码就大功告成了!非常感谢。但是相机索引代码不起作用,它在索引 0 处看到的任何设备仍然返回 true 并中断 for 循环。这一定是为什么我有这么多例子都只是显示黑屏的原因。有什么方法可以确定索引 0 处的内容以便我可以将其关闭?或者将网络摄像头更改为 0?
    • 嗯,我不确定是否有简单的方法可以做到这一点。您可以编写更复杂的代码来查询帧,并通过随机抽取其中的几个像素来检查帧是否“全黑”,而不是仅仅验证捕获不是 Nonetype。我认为最好只提供一个提示,显示一个框架并询问用户是想要这个相机还是尝试下一个。
    • 如果您考虑使用用户输入来更改相机,请查看我上面的编辑。
    • 我收到一个错误,因为找不到 highgui。我尝试了'import highgui'和其他方法但没有运气。我在 Mac 上通过自制软件安装了 opencv
    • @rtacconi 将该行替换为c = cv.WaitKey(10)
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      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

      【讨论】:

        【解决方案5】:

        试试下面的。很简单,但我还没想出优雅的退出方式。

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

        【讨论】:

          【解决方案6】:

          import cv 更改为 import cv2.cv as cv 另见帖子here

          【讨论】:

            猜你喜欢
            • 2020-03-06
            • 2012-06-16
            • 1970-01-01
            • 2015-04-24
            • 2017-05-28
            • 1970-01-01
            • 1970-01-01
            • 2012-08-08
            相关资源
            最近更新 更多