【问题标题】: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 并更改像素的单个颜色?
【发布时间】:2017-08-14 21:42:32
【问题描述】:

我正在尝试迭代一个 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()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()

抱歉有些缩进错误,我不知道如何使用 in text 代码块 XD

【问题讨论】:

  • 你从哪里得到一个错误,指出我应该使用any()all()?请edit您的问题并包括完整的追溯导致发生这种情况的位置。您可能无法正确缩进代码,因为您使用的是制表符而不是空格。

标签: python arrays loops pygame pygame-surface


【解决方案1】:

与其在列表解析中迭代像素(这在 python 中肯定会很慢),然后将该列表结果转换为所需的 numpy 数组,我们可以使用 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]。如果有任何 numpy 专家可以插话,那就太棒了!否则,我可以加入一个额外的 cython 答案(添加类型数据应该会显着提高循环性能)。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-13
      • 2011-01-19
      • 1970-01-01
      • 1970-01-01
      • 2020-07-09
      相关资源
      最近更新 更多