2017-08-14 17 views
0

我試圖迭代一個pygame 3d surfarray,更具體地說pygame.surfarray.array3d("your image")。我正在接收從網絡攝像頭捕獲的視頻,然後將它們轉換成3D數組,然後使用此代碼將其顯示在我的窗口上。如何遍歷pygame 3d surfarray並更改像素的個別顏色,如果它們小於特定值?

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

+1

你從哪裏得到一個錯誤,指出我應該使用'any()'或'all()'?請[編輯]你的問題,幷包括完整的追溯導致發生這種情況。您可能無法正確縮進代碼,因爲您使用製表符而不是空格來執行此操作。 – martineau

回答

2

而不是遍歷列表中理解的像素(其註定是在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]。如果任何一位胖胖的專家都可以參加,那就太棒了!否則,我可以用一個附加的循環回答加入(在添加類型數據的情況下,應該顯着提高循環性能)。

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)進行比較時進行的。如果不是這種情況,則重置所有顏色值。

相關問題