diff --git a/src/grid.py b/src/grid.py --- a/src/grid.py +++ b/src/grid.py @@ -1,74 +1,74 @@ 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)