如何迭代pygame 3d surfarray并更改像素的个别颜色(如果它们小于特定值)?

时间:2017-08-14 21:42:33

标签: python arrays loops pygame pygame-surface

我正在尝试迭代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

2 个答案:

答案 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,则对应于蓝色的每个的第三个条目进行比较。如果不是这种情况,则重置所有颜色值。