我正在尝试迭代pygame 3d surfarray,更具体地说是pygame.surfarray.array3d("your image")
。我正在接收从我的网络摄像头捕获的视频,然后将它们转换为3d数组,然后使用此代码将其显示在我的窗口上。
def cameraSee(self):
while True:
self.cam.query_image()
self.image = self.cam.get_image()
self.imageArr = pygame.surfarray.array3d(self.image)
pygame.surfarray.blit_array(self.screen,self.imageArr)
os.system("clear")
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
我的问题是我试图让我的相机只显示任何具有蓝色>的像素。 200(范围从0到255)并将所有其他像素的颜色值更改为0.我尝试对数组使用if语句但是我收到一条错误,指出我应该使用any()
或{ {1}}。
我的所有代码:
all()
对于一些缩进错误感到抱歉,我不知道如何使用in文本代码块XD
答案 0 :(得分:2)
不是迭代列表推导中的像素(在python中速度很慢),然后将该列表结果转换为所需的numpy数组,我们可以" vectorize"使用numpy魔法的问题。这很方便,因为pygame.surfarray.array3d
已经返回一个numpy数组!
这是一个可能采用图像的解决方案(从磁盘加载;我无法让你的代码工作,因为它依赖于某些Linux目录,如/dev/video0
,用于网络摄像头输入和espeak
命令,在Windows中不可用):
import numpy as np
import pygame
import sys
if __name__ == "__main__":
pygame.init()
screen = pygame.display.set_mode((800, 600))
img = pygame.image.load("test.jpg").convert_alpha()
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
data = pygame.surfarray.array3d(img)
mask = data[..., 2] < 200 #mark all super-NOT-blue pixels as True (select the OPPOSITE!)
masked = data.copy() #make a copy of the original image data
masked[mask] = [0, 0, 0] #set any of the True pixels to black (rgb: 0, 0, 0)
out = pygame.surfarray.make_surface(masked) #convert the numpy array back to a surface
screen.blit(out, (0, 0))
pygame.display.update()
print clock.get_fps()
clock.tick(60)
在我的电脑上,这个速度约为30 fps,虽然不是很好,但应该是一项重大改进!这里的缓慢似乎是由masked[mask] = [0, 0, 0]
特别造成的。如果任何笨拙的专家可以插话,这将是非常棒的!否则,我可以使用额外的cython答案(其中添加类型数据应该显着改善循环性能)。
答案 1 :(得分:0)
我不确定它是否有效,但请尝试一下
outArr = np.array( [[w if w[2] > 200 else np.zeros(3) for w in h] for h in self.imageArr], dtype='uint8')
这个想法是三维数组有三个索引,第一个描述位置的高度,第二个描述它的宽度,最后一个描述像素的颜色。因此,对颜色列表进行列表理解,如果大于200,则对应于蓝色的每个的第三个条目进行比较。如果不是这种情况,则重置所有颜色值。