如果像素小于特定值,如何遍历 pygame 3d surfarray 并更改像素的单独颜色?

How to iterate through a pygame 3d surfarray and change the individual color of the pixels if they're less than a specific value?

我正在尝试迭代 pygame 3d surfarray,更具体地说 pygame.surfarray.array3d("your image")。我正在接收从我的网络摄像头捕获的视频,然后将它们转换为 3d 数组,然后使用此代码将其显示到我的 window 上。

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

我所有的代码:

try:
    import pygame
    import pygame.camera
    import pygame.surfarray
    import numpy
    import os
    import sys
    import time
except:
    print("there was an error importing modules...")

os.system("espeak 'there, was, an, error, importing, modules'")
time.sleep(2)

class aaiVision(object):
    def __init__(self,screen,cam,image,imageArr):
        self.screen = screen
        self.cam = cam
        self.image = image
        self.imageArr = imageArr

    def startUp(self):
        os.system("espeak 'eh, eh, i, vision, initializing'")
        pygame.init()
        pygame.camera.init()
        time.sleep(1)
        os.system("espeak 'Vision, initialized'")

        camList = pygame.camera.list_cameras()
        print(camList)
        time.sleep(1)
        os.system("espeak 'cameras, found, %s'" % str(len(camList)))
        time.sleep(1)

        self.screen = pygame.display.set_mode((640,480))
        time.sleep(0.5)
        self.cam = pygame.camera.Camera("/dev/video0",(640,480),"YUV")
        time.sleep(0.5)
        self.cam.start()
        os.system("espeak 'eh, eh, i, vision, online'")

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

  eyesAwake = aaiVision('', '', '', '')

  if __name__ == "__main__":
      eyesAwake.startUp()
      eyesAwake.cameraSee()

抱歉出现了一些缩进错误,我不确定如何使用文本代码块 XD

我不确定是否有效,但请尝试一下

outArr = np.array( [[w if w[2] > 200 else np.zeros(3) for w in h] for h in self.imageArr], dtype='uint8')

想法是三维数组具有三个索引,第一个描述位置的高度,第二个描述位置的宽度,最后一个描述像素的颜色。因此,如果颜色列表的第三个条目(对应于蓝色)大于 200,则比较颜色列表的列表理解。如果不是这种情况,则重置所有颜色值。

与其遍历列表理解中的像素(这在 python 中肯定会很慢),然后将该列表结果转换为所需的 numpy 数组,我们可以 "vectorize" 解决问题使用 numpy 的魔力。这在这里很方便,因为 pygame.surfarray.array3d 已经 returns 一个 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]。如果任何 numpy 专家可以插话,那就太棒了!否则,我可以用一个额外的 cython 答案代替(添加类型数据应该显着提高循环性能)。