Changeset - fc8be31ce773
[Not reviewed]
default
0 5 0
Laman - 9 years ago 2015-11-23 22:05:03

added intensity slider
5 files changed with 27 insertions and 16 deletions:
0 comments (0 inline, 0 general)
.hgignore
Show inline comments
 
^src/__pycache__/
 
\ No newline at end of file
 
^src/__pycache__/
 
^\.idea/
 
\ No newline at end of file
readme.md
Show inline comments
 
@@ -7,13 +7,13 @@ Modules:
 
 
  * Video: grabbing still frames from a video file / stream. Planning to use FFmpeg.
 
  * Graphic: extracting game position from an image. Using Pillow.
 
  * Watcher: interpreting sequence of game positions as a sequence of moves.
 
  * Broadcaster: interfacing with a go server.
 
 
Written for Python 3.4.3. Dependencies: Pillow 2.7.0, NumPy 1.9.2. Start gui.py to run.
 
Written for Python 3.5.0. Dependencies: Pillow 2.7.0, NumPy 1.10.0. Start gui.py to run.
 
 
Licensed under GNU GPL v2.0 or later. See license.txt. Relicensing possible, don't hesitate to ask.
 
  
 
 
Graphic
 
-------
src/corners.py
Show inline comments
 
@@ -41,12 +41,15 @@ class Corners:
 
    
 
  ## Order the corners (0,1,2,3) so they make a quadrangle with vertices KLMN in counter-clockwise order, K being in the upper left.
 
  #  
 
  #  For four points ABCD, there are 24 possible permutations corresponding to the desired KLMN.
 
  #  When we relax the condition of K being the upper left one, we get six groups of four equivalent permutations. KLMN ~ LMNK ~ MNKL ~ NKLM.
 
  #  
 
  #  We determine which of the points' triplets are oriented clockwise and which counter-clockwise (minus/plus in the table below)
 
  #  and swap them so that all triangles turn counter-clockwise.
 
  #  
 
  #  xxxx -> KLMN | ABC | ABD | ACD | BCD | index | swap
 
  #  ------------ | :-: | :-: | :-: | :-: | ----: | ----
 
  #  A BCD        |  +  |  +  |  +  |  +  |    15 | 0
 
  #  A BDC        |  +  |  +  |  -  |  -  |    12 | CD
 
  #  A CBD        |  -  |  +  |  +  |  -  |     6 | BC
 
  #  A CDB        |  -  |  -  |  +  |  +  |     3 | AB
 
@@ -66,13 +69,13 @@ class Corners:
 
    acd=Corners._doubleTriangleArea(a,c,d)
 
    bcd=Corners._doubleTriangleArea(b,c,d)
 
    
 
    if any(x==0 for x in (abc,abd,acd,bcd)): return False # collinear degenerate
 
    
 
    swaps=[(1,3),(0,1),(1,2),(0,3),(2,3),(0,0)]
 
    index=(8 if abc>0 else 0)+(4 if abd>0 else 0)+(2 if acd>0 else 0)+(1 if bcd>0 else 0)
 
    index=(8 if abc>0 else 0)|(4 if abd>0 else 0)|(2 if acd>0 else 0)|(1 if bcd>0 else 0)
 
    if index%3!=0: return False # concave degenerate
 
    swap=swaps[index//3]
 
    
 
    self.corners[swap[0]], self.corners[swap[1]] = self.corners[swap[1]], self.corners[swap[0]] # counter-clockwise order
 
    
 
    kIndex=None
 
@@ -85,14 +88,6 @@ class Corners:
 
        kIndex=ii
 
        lowestSlope=slope
 
    
 
    self.corners=self.corners[kIndex:]+self.corners[:kIndex] # rotate the upper left corner to the first place
 
        
 
    return True # success
 
 
# import itertools
 
# points=[(10,8),(8,10),(12,10),(10,12)]
 
# for perm in itertools.permutations(points):
 
  # corn=Corners()
 
  # for p in perm: corn.add(p[0],p[1])
 
  # print(corn.canonizeOrder())
 
  # print(corn.corners)
src/gui.py
Show inline comments
 
@@ -31,12 +31,21 @@ class Application(tk.Frame):
 
    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=lambda x: self.redrawImgView())
 
    self.scaleTresW=tk.Scale(self, orient=tk.HORIZONTAL, length=200, from_=0.0, to=100.0, command=lambda x: self.redrawImgView())
 
    self.scaleTresB.set(30.0)
 
    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():
 
@@ -64,16 +73,18 @@ class Application(tk.Frame):
 
    self.imgView.grid()
 
    
 
    origWidth,origHeight=self.imgOrig.size
 
    widthRatio=origWidth/self.img.width()
 
    heightRatio=origHeight/self.img.height()
 
    sizeCoef=max(widthRatio,heightRatio)
 
    tresB=self.scaleTresB.get()
 
    tresW=self.scaleTresW.get()
 
    
 
    shift=EPoint(origWidth-self.img.width()*sizeCoef,origHeight-self.img.height()*sizeCoef)/2
 
    
 
    self.boardView.redrawState(self.imgOrig,sizeCoef,shift)
 
    self.boardView.redrawState(self.imgOrig,sizeCoef,shift,tresB,tresW)
 
    
 
  ## 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")
 
    
 
@@ -90,14 +101,18 @@ class BoardView(tk.Canvas):
 
    self.configure(width=360,height=360,background="#ffcc00")
 
    
 
    self.drawGrid()
 
    
 
    self.grid()
 
    
 
  def redrawState(self,img,sizeCoef,shift):
 
    self.detector.analyze(img,30,65,sizeCoef,shift)
 
  ## Redraws and reananalyzes the board view.
 
  #
 
  # @param tresB upper intensity treshold for a pixel to be considered black, [0-100]
 
  # @param tresW lower intensity treshold for a pixel to be considered white, [0-100]
 
  def redrawState(self,img,sizeCoef,shift,tresB,tresW):
 
    self.detector.analyze(img,tresB,tresW,sizeCoef,shift)
 
    
 
    for r,row in enumerate(self.detector.board):
 
      for c,point in enumerate(row):
 
        self.drawStone(r,c,point)
 
        
 
    self.grid()
src/image_analyzer.py
Show inline comments
 
@@ -21,14 +21,14 @@ class ImageAnalyzer:
 
        
 
        self.board[r][c]=self.analyzePoint(image,intersection*sizeCoef+shift,stoneWidth,stoneHeight,tresB,tresW)
 
  
 
  def analyzePoint(self,image,imageCoords,stoneWidth,stoneHeight,tresB,tresW):
 
    b=w=e=0
 
    
 
    cmax=max(int(stoneWidth*2//5),2)
 
    rmax=max(int(stoneHeight*2//5),2)
 
    cmax=max(int(stoneWidth*2//7),2) # !! optimal parameters subject to further research
 
    rmax=max(int(stoneHeight*2//7),2)
 
    
 
    for r in range(-rmax,rmax+1):
 
      for c in range(-cmax,cmax+1):
 
        red,green,blue=image.getpixel((imageCoords.x+c,imageCoords.y+r))
 
        
 
        I=(red+green+blue)/255/3
0 comments (0 inline, 0 general)