假设我们想要通过从之前收集的一组图像和标签预测图像标签来驾驶自动驾驶汽车(一个机器学习应用程序)。为此,汽车通过蓝牙串行(rfcomm)连接到主机(装有*NIX的PC ),图像通过IP网络摄像头直接从安卓手机传输,同时,PC正在运行连接这两个功能的程序,在pygame创建的绘图环境中显示捕获的图像,并使用串行将指令发送回汽车。
目前,我已经尝试使用multiprocessing模块来实现这些过程,似乎可以工作,但是当我执行客户端时,绘图函数(if __name__ == '__main__')在getKeyPress()函数结束后工作。
问题是:是否有可能将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})提前谢谢。
发布于 2013-04-12 18:27:50
我的建议是使用单独的线程。
#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()另一种方法是创建两个不同的脚本,并使用套接字处理进程间通信。
发布于 2013-04-10 23:04:11
我个人建议在不使用multiprocessing模块的情况下编写这篇文章:它使用fork(),它对大多数复杂的库具有未指定的效果,比如本例中的pygame。
你应该试着把它写成两个完全不同的程序。它迫使您思考哪些数据需要从一个数据到另一个数据,这既是一件坏事,也是一件好事(因为它可能会澄清一些事情)。您可以使用一些进程间通信工具,如stdin/stdout管道;例如,在一个程序(“主”程序)中,将另一个程序作为子进程启动,如下所示:
popen = subprocess.Popen([sys.executable, '-u', 'my_subproc.py'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE)( -u用于无缓冲。)
然后将数据读/写到父进程中的popen.stdin/popen.stdout,以及子进程中的sys.stdin/sys.stdout。最简单的例子是如果两个进程只需要一个同步信号,例如,父进程在循环中等待子进程说“下一个请”。为此,子进程执行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]:https://stackoverflow.com/questions/15822862
复制相似问题