Changeset - 4c1ba49ea859
[Not reviewed]
default
0 5 0
Laman - 8 years ago 2017-04-08 11:42:05

walking through the frames
5 files changed with 24 insertions and 7 deletions:
0 comments (0 inline, 0 general)
src/config.py
Show inline comments
 
import os
 
import logging
 
import json
 

	
 

	
 
logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.DEBUG)
 
with open(os.path.join(os.path.dirname(__file__), "..", "config.json")) as f:
 
	cfgFile=json.load(f)
 

	
 
class misc:
 
	file=cfgFile["misc"]
 
	version=(0,0,0)
 
	defaultImage=file.get("defaultImage", "1.jpg")
 
	defaultImage=file.get("defaultImage", 0)
 

	
 
class gui:
 
	file=cfgFile["gui"]
 
	showBigPoints=file.get("showBigPoints", False)
 
	showGrid=file.get("showGrid", True)
src/core.py
Show inline comments
 
import os
 
import multiprocessing
 
import threading
 
import logging as log
 
import PIL
 
from util import MsgQueue
 
from gui import gui
 
from imageanalyzer import ImageAnalyzer
 
from go import Go
 
import config as cfg
 

	
 

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

	
 
		self._ownMessages=MsgQueue(self._handleEvent)
 
		self._guiMessages=MsgQueue()
 

	
 
		imgPath=os.path.join(os.path.dirname(__file__), "..","images",cfg.misc.defaultImage)
 
		self._imgDir=os.path.join(os.path.dirname(__file__), "..","images")
 
		self._imgs=sorted(os.listdir(self._imgDir))
 
		self._imgIndex=cfg.misc.defaultImage
 
		imgPath=os.path.join(self._imgDir,self._imgs[self._imgIndex])
 
		self._frame=PIL.Image.open(imgPath)
 

	
 
		self._guiProc=multiprocessing.Process(name="gui", target=gui, args=(self._guiMessages,self._ownMessages))
 
		self._guiProc.start()
 
		self._guiMessages.send("setCurrentFrame",(self._frame.copy(),))
 
		self.relativeFrame(0)
 

	
 
	def setCorners(self,corners):
 
		self.detector.setGridCorners(corners)
 
		self.detector.analyze(self._frame)
 
		self._guiMessages.send("setGameState",(self.detector.board,))
 

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

	
 
	def relativeFrame(self,step):
 
		self._imgIndex=(self._imgIndex+step)%len(self._imgs)
 
		imgPath=os.path.join(self._imgDir,self._imgs[self._imgIndex])
 
		self._frame=PIL.Image.open(imgPath)
 
		self._guiMessages.send("setCurrentFrame",(self._frame.copy(),))
 

	
 
	def listen(self):
 
		listenerThread=threading.Thread(target=lambda: self._ownMessages.listen())
 
		listenerThread.start()
 

	
 
	def joinGui(self):
 
		self._guiProc.join()
 
		self._ownMessages.send("!kill")
 

	
 
	def _handleEvent(self,e):
 
		actions={"setCorners":self.setCorners, "setTresholds":self.setTresholds}
 
		actions={
 
			"setCorners": self.setCorners,
 
			"setTresholds": self.setTresholds,
 
			"prevFrame": lambda: self.relativeFrame(-1),
 
			"nextFrame": lambda: self.relativeFrame(1)
 
		}
 
		(actionName,args,kwargs)=e
 

	
 
		return actions[actionName](*args,**kwargs)
 

	
 
core=Core()
 
core.listen()
 
core.joinGui()
 

	
 
"""
 
core
 
====
 
grid
 
go
 
imageAnalyzer
 

	
 

	
 
gui
 
===
 
corners
 

	
 
a) keeps references to important objects and uses them
 
b) gets and sets all relevant data through method calls with core
 

	
 
GUI
src/gui/__init__.py
Show inline comments
 
import threading
 
import tkinter as tk
 
 
import config
 
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.root.columnconfigure(0,weight=1)
 
		self.root.rowconfigure(0,weight=1)
 
 
		self.root.bind("<<redrawImgView>>", lambda e: self.mainWindow.redrawImgView())
 
		self.root.bind("<<receiveState>>", lambda e: print("fired receiveState"))
 
		self.root.bind("<Left>",lambda e: self.sendMsg("prevFrame"))
 
		self.root.bind("<Right>",lambda e: self.sendMsg("nextFrame"))
 
 
	def __call__(self,ownMessages,coreMessages):
 
		self._coreMessages=coreMessages
 
 
		self.listenerThread=threading.Thread(target=lambda: ownMessages.listen(self._handleEvent))
 
		self.listenerThread.start()
 
 
		self.mainWindow.mainloop()
 
 
	def sendMsg(self,actionName,args=tuple(),kwargs=None):
 
		self._coreMessages.send(actionName,args,kwargs)
 
 
	def _handleEvent(self,e):
 
		actions={"setCurrentFrame":self._frameHandler, "setGameState":self._stateHandler}
 
		(actionName,args,kwargs)=e
 
 
		return actions[actionName](*args,**kwargs)
 
 
	def _frameHandler(self,newFrame):
 
		self.mainWindow.setCurrentFrame(newFrame)
 
		self.root.event_generate("<<redrawImgView>>")
 
 
	def _stateHandler(self,gameState):
 
		self.mainWindow.boardView.redrawState(gameState)
src/gui/imgview.py
Show inline comments
 
@@ -10,79 +10,78 @@ import imageanalyzer
 

	
 

	
 
class ImgView(ResizableCanvas):
 
	def __init__(self,master=None,parent=None):
 
		super().__init__(master)
 

	
 
		self._parent=parent
 
		self._corners=Corners()
 
		self._boardGrid=None
 

	
 
		self._img=None
 
		self._tkImg=None
 
		self._imgSizeCoef=1
 

	
 
		self.configure(width=480,height=360)
 
		self.bind('<1>',lambda e: self.addCorner(e.x,e.y))
 

	
 
	## Redraws the current image and its overlay.
 
	def redraw(self):
 
		self.delete("all")
 

	
 
		if self._img:
 
			img=self._img.copy()
 
			img.thumbnail((int(self._width),int(self._height)))
 
			self._tkImg=ImageTk.PhotoImage(img) # just to save the image from the garbage collector
 
			self._tkImg=ImageTk.PhotoImage(img) # just to save the image from garbage collector
 
			self.create_image(self._width//2, self._height//2, anchor="center", image=self._tkImg)
 

	
 
		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.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.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.create_rectangle(r1,c1,r2,c2,outline="#00ffff")
 

	
 
	def setImg(self,img):
 
		w=int(self._width)
 
		h=int(self._height)
 
		wo,ho=img.size # o for original
 
		widthRatio=wo/w
 
		heightRatio=ho/h
 
		self._imgSizeCoef=max(widthRatio,heightRatio)
 

	
 
		self._img=img
 
		self.configure(width=wo,height=ho)
 

	
 
	## Stores a grid corner located at x,y coordinates.
 
	def addCorner(self,x,y):
 
		self._corners.add(x,y)
 
		log.debug("click on %d,%d",x,y)
 
		log.debug("sizeCoef: %f",self._imgSizeCoef)
 
		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) for c in self._corners.corners]
 
			self._parent.sendMsg("setCorners",(corners,))
 

	
 
		self.redraw()
 

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

	
 
	def _onResize(self,event):
 
		super()._onResize(event)
 
		self.redraw()
src/gui/mainwindow.py
Show inline comments
 
import tkinter as tk
 
from tkinter import N,S,E,W
 

	
 
from .boardview import BoardView
 
from .imgview import ImgView
 

	
 

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

	
 
		tk.Frame.__init__(self, master)
 
		self.grid(column=0,row=0,sticky=(N,S,E,W))
 
		self._createWidgets()
 

	
 
		self.bind("<Left>",lambda e: self.sendMsg("prevFrame"))
 
		self.bind("<Right>",lambda e: self.sendMsg("nextFrame"))
 

	
 
	def setCurrentFrame(self,frame):
 
		self.imgView.setImg(frame)
 

	
 
	def _createWidgets(self):
 
		# a captured frame with overlay graphics
 
		self._imgWrapper=tk.Frame(self,width=480,height=360)
 
		self.imgView=ImgView(self._imgWrapper,self)
 

	
 
		self._imgWrapper.grid(column=0,row=0,sticky=(N,S,E,W))
 

	
 
		# board with detected stones
 
		self._boardWrapper=tk.Frame(self,width=360,height=360)
 
		self.boardView=BoardView(self._boardWrapper)
 
		self._boardWrapper.grid(column=1,row=0,sticky=(N,S,E,W))
 

	
 
		# 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)
 

	
 
		self.columnconfigure(0,weight=1)
0 comments (0 inline, 0 general)