Changeset - 5f4489f36388
[Not reviewed]
default
0 3 1
Laman - 8 years ago 2017-01-07 14:01:04

restored showing the game state, split out message passing
4 files changed with 54 insertions and 63 deletions:
0 comments (0 inline, 0 general)
src/core.py
Show inline comments
 
import multiprocessing
 
import logging as log
 
import PIL
 
from util import MsgQueue
 
from gui import gui
 
from image_analyzer import ImageAnalyzer
 
from go import Go
 
@@ -14,35 +15,28 @@ class Core:
 
		self.tresW=60.0
 
		self.tresB=30.0
 

	
 
		self._msgQueue=multiprocessing.Queue()
 
		self._guiQueue=multiprocessing.Queue()
 
		self._incomingEvent=multiprocessing.Event()
 
		self._guiEvent=multiprocessing.Event()
 
		self._ownMessages=MsgQueue(self._handleEvent)
 
		self._guiMessages=MsgQueue()
 

	
 
		self._frame=PIL.Image.open("../images/7.jpg")
 

	
 
		self._guiProc=multiprocessing.Process(name="gui", target=gui, args=(self._guiQueue,self._guiEvent,self._msgQueue,self._incomingEvent))
 
		self._guiProc=multiprocessing.Process(name="gui", target=gui, args=(self._guiMessages,self._ownMessages))
 
		self._guiProc.start()
 
		self._guiQueue.put(("setCurrentFrame",(self._frame,),dict()))
 
		self._guiEvent.set()
 
		self._guiMessages.send("setCurrentFrame",(self._frame,))
 

	
 
	def setCorners(self,corners):
 
		self.detector.setGridCorners(corners)
 
		self.detector.analyze(self._frame)
 
		for r in self.detector.board: log.info(r)
 
		self._guiMessages.send("setGameState",(self.detector.board,))
 

	
 
	def setTresholds(self,tresB=None,tresW=None):
 
		if tresB is not None: self.tresB=tresB
 
		if tresW is not None: self.tresW=tresW
 
		if self.detector.analyze(self._frame):
 
			self._guiMessages.send("setGameState",(self.detector.board,))
 

	
 
	def listen(self):
 
		while True:
 
			self._incomingEvent.wait()
 
			msg=self._msgQueue.get()
 
			if self._msgQueue.empty():
 
				self._incomingEvent.clear()
 
			log.info(msg)
 
			self._handleEvent(msg)
 
		self._ownMessages.listen()
 

	
 
	def _handleEvent(self,e):
 
		actions={"setCorners":self.setCorners, "setTresholds":self.setTresholds}
src/gui/__init__.py
Show inline comments
 
@@ -19,7 +19,6 @@ class MainWindow(tk.Frame):
 
 
		self.currentFrame=None
 
		self._boardGrid=None
 
		self.gameState=None
 
 
		self.img=None
 
		self._imgSizeCoef=1
 
@@ -43,13 +42,6 @@ class MainWindow(tk.Frame):
 
		# shift compensates possible horizontal or vertical empty margins from unmatching aspect ratios
 
		self._imgShift=EPoint(wo-w*self._imgSizeCoef,ho-h*self._imgSizeCoef)/2
 
 
	def setGameState(self,gameState):
 
		pass
 
 
	def setCallbacks(self,setCorners,setTresholds):
 
		self.cornersCallback=setCorners
 
		self.tresholdsCallback=setTresholds
 
 
	def _createWidgets(self):
 
		# a captured frame with overlay graphics
 
		self.imgView=tk.Canvas(self)
 
@@ -83,9 +75,7 @@ class MainWindow(tk.Frame):
 
			self._boardGrid=Grid(self.corners.corners)
 
			corners=[(c*self._imgSizeCoef+self._imgShift) for c in self.corners.corners]
 
			self.parent.sendMsg("setCorners",(corners,))
 
		# 	self.boardGrid=Grid(self.corners)
 
		# 	self.boardView.setBoardGrid(self.boardGrid)
 
		#
 
 
		self.redrawImgView()
 
 
	## Redraws the current image and its overlay.
 
@@ -128,8 +118,6 @@ class MainWindow(tk.Frame):
 
## Handles and presents the game state as detected by the program.
 
class BoardView(tk.Canvas):
 
	def __init__(self, master=None):
 
		# self.detector=ImageAnalyzer()
 
 
		tk.Canvas.__init__(self, master)
 
		self.configure(width=360,height=360,background="#ffcc00")
 
 
@@ -138,25 +126,13 @@ class BoardView(tk.Canvas):
 
		self.grid()
 
 
	def redrawState(self,gameState):
 
		# !! will need to remove old stones or redraw the element completely
 
		for r,row in enumerate(gameState):
 
			for c,point in enumerate(row):
 
				self.drawStone(r,c,point)
 
 
		self.grid()
 
 
	## Redraws and reananalyzes the board view.
 
	# def redrawState(self,img,sizeCoef,shift):
 
	# 	self.create_rectangle(0,0,360,360,fill="#ffcc00")
 
	# 	self.drawGrid()
 
	#
 
	# 	self.detector.analyze(img,sizeCoef,shift)
 
	#
 
	# 	for r,row in enumerate(self.detector.board):
 
	# 		for c,point in enumerate(row):
 
	# 			self.drawStone(r,c,point)
 
	#
 
	# 	self.grid()
 
 
	def drawGrid(self):
 
		for i in range(19):
 
			self.create_line(18,18*(i+1),360-18,18*(i+1),fill="#000000") # rows
 
@@ -190,38 +166,26 @@ class GUI:
 
		self.root = tk.Tk()
 
		self.root.title("OneEye {0}.{1}.{2}".format(*config.misc.version))
 
 
		self.outcomingQueue=None
 
		self.outcomingEvent=None
 
		self._coreMessages=None
 
 
		self.mainWindow = MainWindow(self,master=self.root)
 
 
		self.root.bind("<<redrawImgView>>", lambda e: self.mainWindow.redrawImgView())
 
		self.root.bind("<<receiveState>>", lambda e: print("fired receiveState"))
 
 
	def __call__(self,incomingQueue,incomingEvent,outcomingQueue,outcomingEvent):
 
		self.outcomingQueue=outcomingQueue
 
		self.outcomingEvent=outcomingEvent
 
	def __call__(self,ownMessages,coreMessages):
 
		self._coreMessages=coreMessages
 
 
		self.listenerThread=threading.Thread(target=lambda: self._listen(incomingQueue,incomingEvent))
 
		self.listenerThread=threading.Thread(target=lambda: ownMessages.listen(self._handleEvent))
 
		self.listenerThread.start()
 
 
		self.mainWindow.mainloop()
 
 
	def sendMsg(self,actionName,args=tuple(),kwargs=dict()):
 
		self.outcomingQueue.put((actionName,args,kwargs))
 
		self.outcomingEvent.set()
 
 
	def _listen(self,incomingQueue,incomingEvent):
 
		while True:
 
			incomingEvent.wait()
 
			msg=incomingQueue.get()
 
			if incomingQueue.empty():
 
				incomingEvent.clear()
 
			log.info(msg)
 
			self._handleEvent(msg)
 
	def sendMsg(self,actionName,args=tuple(),kwargs=None):
 
		self._coreMessages.send(actionName,args,kwargs)
 
 
	def _handleEvent(self,e):
 
		actions={"setCurrentFrame":self._frameHandler}
 
		actions={"setCurrentFrame":self._frameHandler, "setGameState":self._stateHandler}
 
		(actionName,args,kwargs)=e
 
 
		return actions[actionName](*args,**kwargs)
 
@@ -230,7 +194,7 @@ class GUI:
 
		self.mainWindow.setCurrentFrame(newFrame)
 
		self.root.event_generate("<<redrawImgView>>")
 
 
	def _stateHandler(self,e):
 
		pass
 
	def _stateHandler(self,gameState):
 
		self.mainWindow.boardView.redrawState(gameState)
 
 
gui=GUI()
src/image_analyzer.py
Show inline comments
 
@@ -14,7 +14,9 @@ class ImageAnalyzer:
 
 
	# let's not concern ourselves with sizecoef and shift here anymore. we want corners to come already properly recomputed
 
	def analyze(self,image):
 
		if self.grid==None: return False
 
		if self.grid==None:
 
			log.info("ImageAnalyzer.analyze() aborted: no grid available.")
 
			return False
 
 
		for r in range(19):
 
			for c in range(19):
 
@@ -22,6 +24,9 @@ class ImageAnalyzer:
 
 
				self.board[r][c]=self.analyzePoint(image,r,c,intersection,*(self.grid.stoneSizeAt(r,c)))
 
 
		boardStr="\n".join(str(row) for row in self.board)
 
		log.info("board analyzed:\n%s",boardStr)
 
 
	def analyzePoint(self,image,row,col,imageCoords,stoneWidth,stoneHeight):
 
		b=w=e=0
 
src/util.py
Show inline comments
 
new file 100644
 
import multiprocessing
 
import logging as log
 

	
 

	
 
class MsgQueue:
 
	def __init__(self,handler=None):
 
		self._queue=multiprocessing.Queue()
 
		self._event=multiprocessing.Event()
 
		self._handleEvent=handler
 

	
 
	def send(self,actionName,args=tuple(),kwargs=None):
 
		if kwargs is None: kwargs=dict()
 
		self._queue.put((actionName,args,kwargs))
 
		self._event.set()
 

	
 
	def listen(self,handleEvent=None):
 
		if handleEvent is not None: self._handleEvent=handleEvent
 

	
 
		while True:
 
			self._event.wait()
 
			msg=self._queue.get()
 
			if self._queue.empty():
 
				self._event.clear()
 
			log.info(msg)
 
			self._handleEvent(msg)
 

	
 
	def setHandler(self,handler):
 
		self._handleEvent=handler
0 comments (0 inline, 0 general)