1

以前に収集した一連の画像とラベルから画像ラベルを予測することで、自動運転車を運転したいとします (機械学習アプリケーション)。このタスクでは、車は Bluetooth シリアル (rfcomm) 経由でホスト コンピュータ (*NIX を搭載した PC) に接続され、画像は IP Webcam を使用して Android フォンから直接ストリーミングされます。その間、PC はこれをリンクするプログラムを実行しています。で作成された描画環境でキャプチャした画像を表示し、pygameシリアルを使用して指示を車に送り返す 2 つの機能。

今のところ、multiprocessingモジュールを使ってそれらの処理を実装しようとしたところ、動作しているように見えましたが、クライアントを実行すると、関数の終了後に描画関数 ( if __name__ == '__main__') が動作しgetKeyPress()ます。

問題は、プログラムが 2 つの独立したプロセスで動作するように、 で if __name__ == '__main__'宣言されたプロセスと で囲まれた描画関数を並列化または同期することは可能ですか?getKyPress()

これまでに実装されたコードは次のとおりです。

import urllib
import time
import os
import sys
import serial
import signal
import multiprocessing 
import numpy as np
import scipy
import scipy.io as sio
import matplotlib.image as mpimg
from pygame.locals import *


PORT = '/dev/rfcomm0'
SPEED = 115200

ser = serial.Serial(PORT)

status = False
move = None
targets = []
inputs = []
tic = False



def getKeyPress():
    import pygame
    pygame.init()
    global targets
    global status
    while not status:
          pygame.event.pump()
          keys = pygame.key.get_pressed()
          targets, status = processOutputs(targets, keys)
    targets = np.array(targets)
    targets = flattenMatrix(targets)
    sio.savemat('targets.mat', {'targets':targets})       


def rgb2gray(rgb):
    r, g, b = np.rollaxis(rgb[...,:3], axis = -1)
    return 0.299 * r + 0.587 * g + 0.114 * b

def processImages(inputX, inputs):
    inputX = flattenMatrix(inputX)
    if len(inputs) == 0:
       inputs = inputX
    elif inputs.shape[1] >= 1:
       inputs = np.hstack((inputs, inputX))
    return inputs

def flattenMatrix(mat):
    mat = mat.flatten(1)
    mat = mat.reshape((len(mat), 1))
    return mat

def send_command(val):
    connection = serial.Serial( PORT,
                                SPEED,
                                timeout=0,
                                stopbits=serial.STOPBITS_TWO
                                )
    connection.write(val)
    connection.close()

def processOutputs(targets, keys):
    global move
    global status
    global tic
    status = False
    keypress = ['K_p', 'K_UP', 'K_LEFT', 'K_DOWN', 'K_RIGHT']
    labels = [1, 2, 3, 4, 5]
    commands = ['p', 'w', 'r', 'j', 's']
    text = ['S', 'Up', 'Left', 'Down', 'Right']
    if keys[K_q]:
       status = True
       return targets, status            
    else:
       for i, j, k, g in zip(keypress, labels, commands, text):
           cmd = compile('cond = keys['+i+']', '<string>', 'exec')
           exec cmd
           if cond:
              move = g
              targets.append(j)
              send_command(k)
              break
    send_command('p')
    return targets, status


targetProcess = multiprocessing.Process(target=getKeyPress)
targetProcess.daemon = True
targetProcess.start()

if __name__ == '__main__': 
   import pygame
   pygame.init()
   w = 288
   h = 352
   size=(w,h)
   screen = pygame.display.set_mode(size)
   c = pygame.time.Clock() # create a clock object for timing
   pygame.display.set_caption('Driver')
   ubuntu = pygame.font.match_font('Ubuntu')
   font = pygame.font.Font(ubuntu, 13)
   inputs = []
   try:
     while not status:
           urllib.urlretrieve("http://192.168.0.10:8080/shot.jpg", "input.jpg")
           try:
             inputX = mpimg.imread('input.jpg')
           except IOError:
             status = True
           inputX = rgb2gray(inputX)/255
           out = inputX.copy()
           out = scipy.misc.imresize(out, (352, 288), interp='bicubic', mode=None)
           scipy.misc.imsave('input.png', out)
           inputs = processImages(inputX, inputs)
           print inputs.shape[1]
           img=pygame.image.load('input.png')
           screen.blit(img,(0,0))
           pygame.display.flip() 
           c.tick(1)
           if move != None:
              text = font.render(move, False, (255, 128, 255), (0, 0, 0))
              textRect = text.get_rect()
              textRect.centerx = 20 #screen.get_rect().centerx
              textRect.centery = 20 #screen.get_rect().centery
              screen.blit(text, textRect)
              pygame.display.update()
           if status:
              targetProcess.join()
              sio.savemat('inputs.mat', {'inputs':inputs})
   except KeyboardInterrupt:
     targetProcess.join()
     sio.savemat('inputs.mat', {'inputs':inputs})

   targetProcess.join()
   sio.savemat('inputs.mat', {'inputs':inputs})

前もって感謝します。

4

2 に答える 2

1

multiprocessingモジュールを使用せずにこれを書くことを個人的にお勧めしfork()ますpygame

これは、2 つの完全に別個のプログラムとして作成するようにしてください。あるデータから別のデータに移動する必要があるデータについて考える必要があります。stdin/stdout パイプなどのプロセス間通信機能を使用できます。たとえば、1 つのプログラム (「メイン」プログラム) で、次のようにサブプロセスとして他のプログラムを開始します。

popen = subprocess.Popen([sys.executable, '-u', 'my_subproc.py'],
                         stdin=subprocess.PIPE, stdout=subprocess.PIPE)

(-uは unbuffered 用です。)

次に、親プロセスの popen.stdin/popen.stdout とサブプロセスの sys.stdin/sys.stdout にデータを読み書きします。最も単純な例は、2 つのプロセスが同期信号のみを必要とする場合です。たとえば、親プロセスは、サブプロセスが「next please」と言うのをループで待機します。これを行うには、サブプロセスがprint 'next please'行い、親プロセスが行いpopen.stdin.readline()ます。(出力はサブプロセスの sys.stdin に送られます。)

無関係の小さなメモ:

keypress = ['K_p', ...]
...
cmd = compile('cond = keys['+i+']', '<string>', 'exec')
exec cmd
if cond:

これは非常に重いコードのように見えます:

keypress = [K_p, ...]     # not strings, directly the values
...
if keys[i]:
于 2013-04-10T15:04:10.783 に答える
0

私の提案は、別々のスレッドを使用することです。

#At the beginning
import threading

#Instead of def getKeyPress()
class getKeyPress(threading.Thread):
    def run(self):
        import pygame
        pygame.init()
        global targets
        global status
        while not status:
               pygame.event.pump()
               keys = pygame.key.get_pressed()
               targets, status = processOutputs(targets, keys)
        targets = np.array(targets)
        targets = flattenMatrix(targets)
        sio.savemat('targets.mat', {'targets':targets}) 

#Instead of 
#targetProcess = multiprocessing.Process(target=getKeyPress)
#targetProcess.daemon = True
#targetProcess.start()  
gkp = getKeyPress()
gkp.start()

別の方法は、2 つの異なるスクリプトを作成し、ソケットを使用してプロセス間通信を処理することです。

于 2013-04-12T10:27:50.490 に答える