使用Python中的CV2和Pyglet捕获Webcam图像

时间:2015-06-24 14:57:29

标签: python opencv video numpy pyglet

我正在使用Python的CV2(OpenCV)和Pyglet Python库来创建一个小应用程序,它将显示来自网络摄像头的实时视频并覆盖一些文本或静态图像。我已经使用CV2创建了一个应用程序,它只是在一个框架中显示网络摄像头图像,但现在我想在pyglet窗口中获取该框架。

到目前为止,这是我拼凑的东西:

import pyglet
from pyglet.window import key
import cv2
import numpy


window = pyglet.window.Window()

camera=cv2.VideoCapture(0)

def getCamFrame(color,camera):
    retval,frame=camera.read()
    if not color:
        frame=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
    frame=numpy.rot90(frame)
    return frame


frame=getCamFrame(True,camera)
video = pyglet.resource.media(frame, streaming=True)

@window.event
def on_key_press(symbol, modifiers):
    if symbol == key.ESCAPE:
        print 'Application Exited with Key Press'
        window.close()

@window.event
def on_draw():
    window.clear()
    video.blit(10,10)

pyglet.app.run()

运行时,我收到以下错误:

Traceback, line 20 in <module>
  video = pyglet.resource.media(frame, streaming=True)
TypeError: unhashable type: 'numpy.ndarray'

我也对其他可以让我在实时视频上显示文字的选项持开放态度。我最初使用pygame,但最后,我需要多个监视器支持,这就是我使用pyglet的原因。

4 个答案:

答案 0 :(得分:0)

您的方法存在许多问题,但最棘手的是将numpy数组转换为纹理。我使用下面的方法,我在其他地方的SO上发现了这种方法。简而言之,您必须利用pyglet.gl公开的 ctypes 类型和结构来生成GLubytes数组,然后将图像的内容(一个numpy数组)放入其中。然后,因为你有一个数组的数组,你必须通过指定像素格式和音高来指定Pyglet应该如何制作图像pImage

如果您让下面的示例有效,那么您应该能够pImg每次拨打on_draw时更新,您应该完成。

import pyglet
from pyglet.gl import *
from pyglet.window import key
import cv2
import numpy
import sys

window = pyglet.window.Window()

camera=cv2.VideoCapture(0)

retval,img = camera.read()
sy,sx,number_of_channels = img.shape
number_of_bytes = sy*sx*number_of_channels

img = img.ravel()

image_texture = (GLubyte * number_of_bytes)( *img.astype('uint8') )
# my webcam happens to produce BGR; you may need 'RGB', 'RGBA', etc. instead
pImg = pyglet.image.ImageData(sx,sy,'BGR',
       image_texture,pitch=sx*number_of_channels)

@window.event
def on_key_press(symbol, modifiers):
    if symbol == key.ESCAPE:
        print 'Application Exited with Key Press'
        window.close()

@window.event
def on_draw():
    window.clear()
    pImg.blit(0,0)

pyglet.app.run()

答案 1 :(得分:0)

虽然这有效,但我发现当图像分辨率很高时,从numpy数组加载图像非常慢。 pygarrrayimage是github上的一个python模块,它可以将numpy数组直接加载到视频卡中而无需复制:

https://github.com/motmot/pygarrayimage

这使得我的python应用程序正在加载来自高分辨率视频的图像。查看示例文件夹,了解如何快速将图像blit到屏幕上。

答案 2 :(得分:0)

您可以使用ImageData constructor将每个opencv图像转换为pyglet图像。我们的想法是将opencv图像转换为PIL数组,然后将其转换为字节串,然后作为原始数据传递给构造函数。

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode parent;

    public void traverse() {
        TreeNode current = this.leftMost();
        while (current != null) {
            System.out.println("Current at " + current.val);
            current = current.inOrderNext();
        }
    }

    public TreeNode inOrderNext() {
        if (right != null) {
            return right.leftMost();
        } else {
            TreeNode current = this;
            TreeNode above = this.parent;
            while (true) {
                if (above == null) {
                    return null;
                } else {
                    if (above.left == current) {
                        return above;
                    } else {
                        current = above;
                        above = above.parent;
                    }
                }
            }
        }
    }

    public TreeNode leftMost() {
        TreeNode result = this;
        while (result.left != null) {
            result = result.left;
        }
        return result;
    }

    public static void main(String args[]) {
        TreeNode first = new TreeNode();
        first.val = 4;

        TreeNode second = new TreeNode();
        second.val = 2;
        second.parent = first;
        first.left = second;

        TreeNode third = new TreeNode();
        third.val = 1;
        third.parent = second;
        second.left = third;

        third = new TreeNode();
        third.val = 3;
        third.parent = second;
        second.right = third;

        second = new TreeNode();
        second.val = 6;
        second.parent = first;
        first.right = second;

        third = new TreeNode();
        third.val = 5;
        third.parent = second;
        second.left = third;

        third = new TreeNode();
        third.val = 7;
        third.parent = second;
        second.right = third;

        first.traverse();
    }
}

答案 3 :(得分:0)

import pyglet
import cv2
window = pyglet.window.Window()

video = cv2.VideoCapture(0)
def takepicture(dt):
    num = 0

    ret,frame = video.read()
    cv2.imwrite(str(num)+'.jpg',frame)
    print("Image_Captured")

@window.event
def on_draw():
    window.clear()
    image = pyglet.image.load('0.jpg')
    image.blit(0,0)

pyglet.clock.schedule_interval(takepicture, 0.001)


pyglet.app.run()