我正在使用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的原因。
答案 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()