Changeset - 5f61b4d8cab9
[Not reviewed]
default
0 3 0
Laman - 10 years ago 2015-08-31 22:23:32

proper Grid initialization
added special methods to EPoint
added Grid construction and presentation to GUI
3 files changed with 119 insertions and 59 deletions:
0 comments (0 inline, 0 general)
src/epoint.py
Show inline comments
 
@@ -6,6 +6,15 @@ class EPoint:
 
  def __init__(self,x,y):
 
    self.x=x
 
    self.y=y
 
    
 
  def fromTuple(tup): return EPoint(tup[0],tup[1])
 
  
 
  def fromProjective(point):
 
    if point.item(0)==0: return None
 
    return EPoint(point.item(1)/point.item(0),point.item(2)/point.item(0))
 
    
 
  def toProjective(self):
 
    return (1,self.x,self.y)
 
  
 
  def dist(self,a):
 
    return math.sqrt((self.x-a.x)**2+(self.y-a.y)**2)
 
@@ -13,8 +22,48 @@ class EPoint:
 
  def __add__(self,a):
 
    return EPoint(self.x+a.x,self.y+a.y)
 
    
 
  def __sub__(self,a):
 
    return EPoint(self.x-a.x,self.y-a.y)
 
    
 
  def __mul__(self,k):
 
    return EPoint(self.x*k,self.y*k)
 
    
 
  def __rmul__(self,k):
 
    return self*k
 
    
 
  def __truediv__(self,k):
 
    return EPoint(self.x/k,self.y/k)
 
    
 
  def __str__(self): return "({0},{1})".format(self.x,self.y)
 
  def __repr__(self): return "EPoint({0},{1})".format(self.x,self.y)
 
  def __floordiv__(self,k):
 
    return EPoint(self.x//k,self.y//k)
 
    
 
  def __iadd__(self,a):
 
    self.x+=a.x
 
    self.y+=a.y
 
    return self
 
    
 
  def __isub__(self,a):
 
    self.x-=a.x
 
    self.y-=a.y
 
    return self
 
  
 
  def __imul__(self,k):
 
    self.x*=k
 
    self.y*=k
 
    return self
 
    
 
  def __itruediv__(self,k):
 
    self.x/=k
 
    self.y/=k
 
    return self
 
    
 
  def __ifloordiv__(self,k):
 
    self.x//=k
 
    self.y//=k
 
    return self
 
    
 
  def __neg__(self):
 
    return EPoint(-self.x,-self.y)
 
    
 
  def __str__(self): return "({0},{1})".format(round(self.x,3),round(self.y,3))
 
  def __repr__(self): return "EPoint({0},{1})".format(round(self.x,3),round(self.y,3))
src/grid.py
Show inline comments
 
import numpy
 
from epoint import *
 
 
 
## Multiplicates the vector as to set the first nonzero coordinate to 1.
 
def canonize(v):
 
  if v.item(0)!=0: factor=v.item(0)
 
  elif v.item(1)!=0: factor=v.item(1)
 
  elif v.item(2)!=0: factor=v.item(2)
 
  else: factor=1
 
  return v/factor
 
  return [x/factor for x in v]
 
## Projective transformation of a point with a matrix A.
 
#  
 
#  Takes a point as a horizontal vector and multiplies it transposed with A from left.
 
#  
 
#  @return transformed point as a numpy.array
 
def transformPoint(point,A):
 
  return (A*numpy.matrix(point).transpose()).getA1()
 
 
def transformPoint(point,A):
 
  # print('#68',numpy.asarray(([1]+point)*A))
 
  x=canonize((A*numpy.matrix([1]+point).transpose()).getA1())
 
  return x[1:]
 
 
class Grid:
 
  
 
  ## Creates a Grid from the provided Corners object.
 
  #  
 
  #  Finds the vanishing points of the board lines (corner points define perspectively transformed parallel lines). The vanishing points define the image horizon.
 
  #  
 
  #  The horizon can be used to construct a matrix for affine rectification of the image (restoring parallel lines parallelism). We transform the corner points by this matrix,
 
  #  interpolate them to get proper intersections' coordinates and then transform these back to get their placement at the original image.
 
  #  
 
  #  The result is stored in grid.intersections, a boardSize*boardSize list with [row][column] coordinates.
 
  #  
 
  #  @param corners a properly initialized Corners object. !! Needs a check for the proper initialization.
 
  def __init__(self,corners):
 
    # ab
 
    # cd
 
    a,b,c,d=corners
 
    # ad
 
    # bc
 
    a,b,c,d=[c.toProjective() for c in corners.corners]
 
    
 
    p1=numpy.cross(a,b)
 
    p2=numpy.cross(c,d)
 
    vanish1=numpy.cross(p1,p2)
 
    
 
    print('#16',p1,p2,vanish1)
 
    
 
    p3=numpy.cross(a,c)
 
    p4=numpy.cross(b,d)
 
    vanish2=numpy.cross(p3,p4)
 
    # !! 32 bit int can overflow. keeping it reasonably small. might want to use a cleaner solution
 
    vanish1=EPoint.fromProjective(vanish1).toProjective()
 
    
 
    print('#32',p3,p4,vanish2)
 
    
 
    horizon=canonize(numpy.cross(vanish1,vanish2))
 
    p3=numpy.cross(a,d)
 
    p4=numpy.cross(b,c)
 
    vanish2=numpy.cross(p3,p4)
 
    vanish2=EPoint.fromProjective(vanish2).toProjective()
 
    
 
    # horizon.x+=10
 
    # horizon[1]+=10
 
    
 
    print('#48',horizon)
 
    horizon=numpy.cross(vanish1,vanish2)
 
 
    horizon=EPoint.fromProjective(horizon).toProjective()
 
    
 
    rectiMatrix=numpy.matrix([horizon,[0,1,0],[0,0,1]])
 
    rectiMatrixInv=numpy.linalg.inv(rectiMatrix)
 
    
 
    print('#64',rectiMatrixInv)
 
    print('#72',transformPoint([0,0],rectiMatrixInv))
 
    
 
    self.intersections=[[[c,r] for c in range(3)] for r in range(3)]
 
    self.intersections=[[transformPoint(point,rectiMatrixInv) for point in line] for line in self.intersections]
 
    
 
    
 
    # b1=canonize(numpy.cross(horizon,p1))
 
    # b2=canonize(numpy.cross(horizon,p2))
 
    # b3=canonize(numpy.cross(horizon,p3))
 
    # b4=canonize(numpy.cross(horizon,p4))
 
    
 
    # print('#64',b1,b2,b3,b4)
 
    affineCorners=[EPoint.fromProjective(transformPoint(x,rectiMatrix)) for x in (a,b,c,d)]
 
    x=[affineCorners[0]-affineCorners[3],affineCorners[1]-affineCorners[2],affineCorners[0]-affineCorners[1],affineCorners[3]-affineCorners[2]]
 
    
 
    # self.intersections=[]
 
    # boardSize=4
 
    # for r in range(boardSize):
 
      # self.intersections.append([None]*boardSize)
 
      # rowLine=numpy.cross(((b1*r+b2*(boardSize-1-r)) / (boardSize-1)), vanish1)
 
      # print('#80',rowLine)
 
      # for c in range(boardSize):
 
        # colLine=numpy.cross(((b3*c+b4*(boardSize-1-c)) / (boardSize-1)), vanish2)
 
        # print('#88',colLine)
 
        # self.intersections[r][c]=numpy.cross(rowLine,colLine)
 
        
 
# x=Grid([Vector3(1,0,10),Vector3(1,10,10),Vector3(1,0,0),Vector3(1,10,0)])
 
x=Grid([[1,0,10],[1,7,7],[1,0,0],[1,10,0]])
 
for line in x.intersections:
 
  print('#96',line)
 
    self.intersections=[]
 
    boardSize=19
 
    for r in range(boardSize):
 
      self.intersections.append([None]*boardSize)
 
      rowStart=(affineCorners[0]*(boardSize-1-r)+affineCorners[1]*r) / (boardSize-1)
 
      rowEnd=(affineCorners[3]*(boardSize-1-r)+affineCorners[2]*r) / (boardSize-1)
 
      
 
      for c in range(boardSize):
 
        affineIntersection=(rowStart*(boardSize-1-c)+rowEnd*c) / (boardSize-1)
 
        self.intersections[r][c]=EPoint.fromProjective(transformPoint(affineIntersection.toProjective(),rectiMatrixInv))
 
 
 
 
# from corners import Corners
 
# corn=Corners()
 
 
# corn.add(106,86)
 
# corn.add(57,321)
 
# corn.add(416,320)
 
# corn.add(365,86)
 
# corn.add(365,88)
 
 
# x=Grid(corn)
src/gui.py
Show inline comments
 
@@ -20,7 +20,8 @@ class Application(tk.Frame):
 
    # a captured frame with overlay graphics
 
    self.imgView=tk.Canvas(self)
 
    self.imgView.configure(width=480,height=360)
 
    imgOrig=PIL.Image.open("../images/1.jpg")
 
    imgOrig=PIL.Image.open("../images/7.jpg")
 
    
 
    self.img=ImageTk.PhotoImage(imgOrig.resize((int(self.imgView['width']),int(self.imgView['height'])),resample=PIL.Image.BILINEAR))
 
    
 
    self.imgView.bind('<1>',lambda e: self.addCorner(e.x,e.y))
 
@@ -46,6 +47,16 @@ class Application(tk.Frame):
 
    for corner in self.corners.corners:
 
      self.markPoint(corner.x,corner.y)
 
    
 
    if self.boardGrid!=None:
 
      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')
 
    
 
    self.imgView.grid()
 
    
 
  ## Marks a point at the image with a green cross. Used for corners.
0 comments (0 inline, 0 general)