如果像素小于特定值,如何遍历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?

查看:41
本文介绍了如果像素小于特定值,如何遍历pygame 3d surfarray并更改像素的单独颜色?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to iterate a pygame 3d surfarray, more specifically pygame.surfarray.array3d("your image"). I'm receiving video captured from my webcam then converting them into a 3d array, then displaying it onto my window with this code.

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

My problem is that I'm trying to have my camera only display any pixel which has an amount of blue > 200 (ranging from 0 - 255) and change the color value of all other pixels to 0. I've tried using an if statement for an array but I get an error stating that I should be using the any() or 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

Sorry about some of the indentation errors, I'm not sure how to use the in text code blocks XD

推荐答案

而不是遍历列表解析中的像素(在python中注定是很慢的),然后将该列表结果转换为所需的numpy数组,可以使用numpy的魔法向量化"问题.这很方便,因为 pygame.surfarray.array3d 已经返回了一个numpy数组!

Rather than iterating over the pixels in a list comprehension (which is bound to be slow in python) and then converting that list result into the desired numpy array, we can "vectorize" the problem using the magic of numpy. This is convenient here, since pygame.surfarray.array3d already returns a numpy array!

这是一个可能的解决方案,它需要从磁盘上加载图像(从磁盘加载;我无法让您的代码正常工作,因为它依赖于某些Linux目录,例如/dev/video0 作为网络摄像头输入和 espeak 命令,在Windows中不可用):

Here is a possible solution that takes an image (loaded from disk; I could not get your code to work since it relies on some linux directories like /dev/video0 for the webcam input and the espeak command, which is unavailable in 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答案(在其中添加类型数据应该可以显着提高循环性能).

On my computer, this runs at ~30 fps, which, while not great, should be a significant improvement! The slowness here appears to be due to masked[mask] = [0, 0, 0] in particular. If any numpy experts could chime in, that would be terrific! Otherwise, I can chime in with an additional cython answer instead (where adding type data should significantly improve loop performance).

这篇关于如果像素小于特定值,如何遍历pygame 3d surfarray并更改像素的单独颜色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆