Changeset - 4b4cae6939e8
[Not reviewed]
default
1 2 3
Laman - 8 years ago 2017-01-07 21:50:10

gui split into more files
5 files changed with 168 insertions and 159 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 imageanalyzer import ImageAnalyzer
 
from go import Go
 

	
 

	
 
class Core:
 
	def __init__(self):
 
		self.grid=None
 
		self.go=Go()
 
		self.detector=ImageAnalyzer()
 
		self.tresW=60.0
 
		self.tresB=30.0
 

	
 
		self._ownMessages=MsgQueue(self._handleEvent)
src/gui/__init__.py
Show inline comments
 
import threading
 
import logging as log
 
import tkinter as tk
 
from PIL import ImageTk
 
import PIL
 
 
import config
 
from epoint import EPoint
 
from corners import Corners
 
import image_analyzer
 
import go
 
from grid import Grid
 
 
 
class MainWindow(tk.Frame):
 
	def __init__(self,parent,master=None):
 
		self.parent=parent
 
		self.corners=Corners()
 
 
		self.currentFrame=None
 
		self._boardGrid=None
 
 
		self.img=None
 
		self._imgSizeCoef=1
 
		self._imgShift=EPoint(0,0)
 
 
		tk.Frame.__init__(self, master)
 
		self.grid(column=0,row=0)
 
		self._createWidgets()
 
 
	def setCurrentFrame(self,frame):
 
		self.currentFrame=frame
 
 
		w=int(self.imgView['width'])
 
		h=int(self.imgView['height'])
 
		self.img=ImageTk.PhotoImage(frame.resize((w,h),resample=PIL.Image.BILINEAR))
 
 
		wo,ho=self.currentFrame.size # o for original
 
		widthRatio=wo/w
 
		heightRatio=ho/h
 
		self._imgSizeCoef=max(widthRatio,heightRatio)
 
		# 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 _createWidgets(self):
 
		# a captured frame with overlay graphics
 
		self.imgView=tk.Canvas(self)
 
		self.imgView.configure(width=480,height=360)
 
 
		self.imgView.bind('<1>',lambda e: self.addCorner(e.x,e.y))
 
 
		self.imgView.grid(column=0,row=0)
 
 
		# board with detected stones
 
		self.boardView=BoardView(self)
 
		self.boardView.grid(column=1,row=0)
 
 
		# more controls below the board
 
		self.scaleTresB=tk.Scale(self, orient=tk.HORIZONTAL, length=200, from_=0.0, to=100.0, command=self.refreshTresholds)
 
		self.scaleTresW=tk.Scale(self, orient=tk.HORIZONTAL, length=200, from_=0.0, to=100.0, command=self.refreshTresholds)
 
		self.scaleTresB.set(30.0) # !! proper defaults
 
		self.scaleTresW.set(60.0)
 
		self.scaleTresB.grid(column=0,row=1,columnspan=2)
 
		self.scaleTresW.grid(column=0,row=2,columnspan=2)
 
 
		# render everything
 
		self.redrawImgView()
 
 
	## Stores a grid corner located at x,y coordinates.
 
	def addCorner(self,x,y):
 
		self.corners.add(x,y)
 
		if self.corners.canonizeOrder():
 
			# transform corners from show coordinates to real coordinates
 
			log.debug(self.corners.corners)
 
			self._boardGrid=Grid(self.corners.corners)
 
			corners=[(c*self._imgSizeCoef+self._imgShift) for c in self.corners.corners]
 
			self.parent.sendMsg("setCorners",(corners,))
 
 
		self.redrawImgView()
 
 
	## Redraws the current image and its overlay.
 
	def redrawImgView(self):
 
		if self.currentFrame and self.img:
 
			self.imgView.create_image(2,2,anchor="nw",image=self.img)
 
 
		for corner in self.corners.corners:
 
			self.markPoint(corner.x,corner.y)
 
 
		if self._boardGrid!=None and config.gui.showGrid:
 
			for r in range(19):
 
				a=self._boardGrid.intersections[r][0]
 
				b=self._boardGrid.intersections[r][-1]
 
				self.imgView.create_line(a.x,a.y,b.x,b.y,fill='#00ff00')
 
			for c in range(19):
 
				a=self._boardGrid.intersections[0][c]
 
				b=self._boardGrid.intersections[-1][c]
 
				self.imgView.create_line(a.x,a.y,b.x,b.y,fill='#00ff00')
 
 
		if self._boardGrid!=None and config.gui.showBigPoints:
 
			for r in range(19):
 
				for c in range(19):
 
					((r1,c1),(r2,c2))=image_analyzer.relevantRect(self._boardGrid.intersections[r][c], *(self._boardGrid.stoneSizeAt(r, c)))
 
					self.imgView.create_rectangle(r1,c1,r2,c2,outline="#00ffff")
 
 
		self.imgView.grid()
 
 
	## Marks a point at the image with a green cross. Used for corners.
 
	def markPoint(self,x,y):
 
		self.imgView.create_line(x-3,y-3,x+4,y+4,fill="#00ff00")
 
		self.imgView.create_line(x-3,y+3,x+4,y-4,fill="#00ff00")
 
 
		self.imgView.grid()
 
 
	def refreshTresholds(self,_):
 
		self.parent.sendMsg("setTresholds",tuple(),{"tresB":self.scaleTresB.get(), "tresW":self.scaleTresW.get()})
 
 
 
## Handles and presents the game state as detected by the program.
 
class BoardView(tk.Canvas):
 
	def __init__(self, master=None):
 
		tk.Canvas.__init__(self, master)
 
		self.configure(width=360,height=360,background="#ffcc00")
 
 
		self.drawGrid()
 
 
		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()
 
 
	def drawGrid(self):
 
		for i in range(19):
 
			self.create_line(18,18*(i+1),360-18,18*(i+1),fill="#000000") # rows
 
			self.create_line(18*(i+1),18,18*(i+1),360-18,fill="#000000") # cols
 
 
		self.drawStars()
 
 
	def drawStars(self):
 
		for r in range(4,19,6):
 
			for c in range(4,19,6):
 
				self.create_oval(r*18-2,c*18-2,r*18+2,c*18+2,fill='#000000')
 
 
	## Draws a stone at provided coordinates.
 
	#
 
	#  For an unknown color draws nothing and returns False.
 
	#
 
	#  @param r row coordinate, [0-18], counted from top
 
	#  @param c column coordinate, [0-18], counted from left
 
	#  @param color color indicator, go.BLACK or go.WHITE
 
	def drawStone(self,r,c,color):
 
		if color==go.BLACK: hexCode='#000000'
 
		elif color==go.WHITE: hexCode='#ffffff'
 
		else: return False
 
		r+=1
 
		c+=1
 
		self.create_oval(c*18-9,r*18-9,c*18+9,r*18+9,fill=hexCode)
 
from .mainwindow import MainWindow
 
from .boardview import BoardView
 
 
 
class GUI:
 
	def __init__(self):
 
		self.root = tk.Tk()
 
		self.root.title("OneEye {0}.{1}.{2}".format(*config.misc.version))
 
 
		self._coreMessages=None
 
 
		self.mainWindow = MainWindow(self,master=self.root)
 
		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,ownMessages,coreMessages):
 
		self._coreMessages=coreMessages
 
 
		self.listenerThread=threading.Thread(target=lambda: ownMessages.listen(self._handleEvent))
 
		self.listenerThread.start()
 
 
		self.mainWindow.mainloop()
 
src/gui/boardview.py
Show inline comments
 
new file 100644
 
import tkinter as tk
 

	
 
import go
 

	
 

	
 
## Handles and presents the game state as detected by the program.
 
class BoardView(tk.Canvas):
 
	def __init__(self, master=None):
 
		tk.Canvas.__init__(self, master)
 
		self.configure(width=360,height=360,background="#ffcc00")
 

	
 
		self.drawGrid()
 

	
 
		self.grid()
 

	
 
	def redrawState(self,gameState):
 
		# !! will need to remove old stones or redraw the widget completely
 
		for r,row in enumerate(gameState):
 
			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
 
			self.create_line(18*(i+1),18,18*(i+1),360-18,fill="#000000") # cols
 

	
 
		self.drawStars()
 

	
 
	def drawStars(self):
 
		for r in range(4,19,6):
 
			for c in range(4,19,6):
 
				self.create_oval(r*18-2,c*18-2,r*18+2,c*18+2,fill='#000000')
 

	
 
	## Draws a stone at provided coordinates.
 
	#
 
	#  For an unknown color draws nothing and returns False.
 
	#
 
	#  @param r row coordinate, [0-18], counted from top
 
	#  @param c column coordinate, [0-18], counted from left
 
	#  @param color color indicator, go.BLACK or go.WHITE
 
	def drawStone(self,r,c,color):
 
		if color==go.BLACK: hexCode='#000000'
 
		elif color==go.WHITE: hexCode='#ffffff'
 
		else: return False
 
		r+=1
 
		c+=1
 
		self.create_oval(c*18-9,r*18-9,c*18+9,r*18+9,fill=hexCode)
src/gui/mainwindow.py
Show inline comments
 
new file 100644
 
import logging as log
 
import tkinter as tk
 

	
 
import PIL
 
from PIL import ImageTk
 

	
 
import config
 
import imageanalyzer
 
from corners import Corners
 
from epoint import EPoint
 
from grid import Grid
 
from .boardview import BoardView
 

	
 

	
 
class MainWindow(tk.Frame):
 
	def __init__(self,parent,master=None):
 
		self.parent=parent
 
		self.corners=Corners()
 

	
 
		self.currentFrame=None
 
		self._boardGrid=None
 

	
 
		self.img=None
 
		self._imgSizeCoef=1
 
		self._imgShift=EPoint(0,0)
 

	
 
		tk.Frame.__init__(self, master)
 
		self.grid(column=0,row=0)
 
		self._createWidgets()
 

	
 
	def setCurrentFrame(self,frame):
 
		self.currentFrame=frame
 

	
 
		w=int(self.imgView['width'])
 
		h=int(self.imgView['height'])
 
		self.img=ImageTk.PhotoImage(frame.resize((w,h),resample=PIL.Image.BILINEAR))
 

	
 
		wo,ho=self.currentFrame.size # o for original
 
		widthRatio=wo/w
 
		heightRatio=ho/h
 
		self._imgSizeCoef=max(widthRatio,heightRatio)
 
		# 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 _createWidgets(self):
 
		# a captured frame with overlay graphics
 
		self.imgView=tk.Canvas(self)
 
		self.imgView.configure(width=480,height=360)
 

	
 
		self.imgView.bind('<1>',lambda e: self.addCorner(e.x,e.y))
 

	
 
		self.imgView.grid(column=0,row=0)
 

	
 
		# board with detected stones
 
		self.boardView= BoardView(self)
 
		self.boardView.grid(column=1,row=0)
 

	
 
		# more controls below the board
 
		self.scaleTresB=tk.Scale(self, orient=tk.HORIZONTAL, length=200, from_=0.0, to=100.0, command=self.refreshTresholds)
 
		self.scaleTresW=tk.Scale(self, orient=tk.HORIZONTAL, length=200, from_=0.0, to=100.0, command=self.refreshTresholds)
 
		self.scaleTresB.set(30.0) # !! proper defaults
 
		self.scaleTresW.set(60.0)
 
		self.scaleTresB.grid(column=0,row=1,columnspan=2)
 
		self.scaleTresW.grid(column=0,row=2,columnspan=2)
 

	
 
		# render everything
 
		self.redrawImgView()
 

	
 
	## Stores a grid corner located at x,y coordinates.
 
	def addCorner(self,x,y):
 
		self.corners.add(x,y)
 
		if self.corners.canonizeOrder():
 
			# transform corners from show coordinates to real coordinates
 
			log.debug(self.corners.corners)
 
			self._boardGrid=Grid(self.corners.corners)
 
			corners=[(c*self._imgSizeCoef+self._imgShift) for c in self.corners.corners]
 
			self.parent.sendMsg("setCorners",(corners,))
 

	
 
		self.redrawImgView()
 

	
 
	## Redraws the current image and its overlay.
 
	def redrawImgView(self):
 
		if self.currentFrame and self.img:
 
			self.imgView.create_image(2,2,anchor="nw",image=self.img)
 

	
 
		for corner in self.corners.corners:
 
			self.markPoint(corner.x,corner.y)
 

	
 
		if self._boardGrid!=None and config.gui.showGrid:
 
			for r in range(19):
 
				a=self._boardGrid.intersections[r][0]
 
				b=self._boardGrid.intersections[r][-1]
 
				self.imgView.create_line(a.x,a.y,b.x,b.y,fill='#00ff00')
 
			for c in range(19):
 
				a=self._boardGrid.intersections[0][c]
 
				b=self._boardGrid.intersections[-1][c]
 
				self.imgView.create_line(a.x,a.y,b.x,b.y,fill='#00ff00')
 

	
 
		if self._boardGrid!=None and config.gui.showBigPoints:
 
			for r in range(19):
 
				for c in range(19):
 
					((r1,c1),(r2,c2))=imageanalyzer.relevantRect(self._boardGrid.intersections[r][c], *(self._boardGrid.stoneSizeAt(r, c)))
 
					self.imgView.create_rectangle(r1,c1,r2,c2,outline="#00ffff")
 

	
 
		self.imgView.grid()
 

	
 
	## Marks a point at the image with a green cross. Used for corners.
 
	def markPoint(self,x,y):
 
		self.imgView.create_line(x-3,y-3,x+4,y+4,fill="#00ff00")
 
		self.imgView.create_line(x-3,y+3,x+4,y-4,fill="#00ff00")
 

	
 
		self.imgView.grid()
 

	
 
	def refreshTresholds(self,_):
 
		self.parent.sendMsg("setTresholds",tuple(),{"tresB":self.scaleTresB.get(), "tresW":self.scaleTresW.get()})
src/imageanalyzer.py
Show inline comments
 
file renamed from src/image_analyzer.py to src/imageanalyzer.py
0 comments (0 inline, 0 general)