diff --git a/exp/stone_detect.py b/exp/stone_detect.py --- a/exp/stone_detect.py +++ b/exp/stone_detect.py @@ -12,7 +12,8 @@ import scipy.ndimage from annotations import DataFile,computeBoundingBox from hough import show -from analyzer.epoint import EPoint +from analyzer.epoint import EPoint,homogenize +from analyzer.grid import transformPoint random.seed(361) @@ -26,6 +27,31 @@ class Line(): def getSortedPoints(self): return tuple(sorted(self.points)) + def computeAngle(self,line): + ab=self.a-self.b + cd=line.a-line.b + alpha=math.atan(ab.y/ab.x) + gamma=math.atan(cd.y/cd.x) + fi=max(alpha,gamma)-min(alpha,gamma) + return min(fi,math.pi-fi) + + def intersect(self,line): + p=self.toProjective() + q=line.toProjective() + return EPoint.fromProjective(np.cross(p,q)) + + def toProjective(self): + return homogenize(np.cross(self.a.toProjective(),self.b.toProjective())) + + def transform(self,matrix): + a=EPoint.fromProjective(transformPoint(self.a.toProjective(),matrix)) + b=EPoint.fromProjective(transformPoint(self.b.toProjective(),matrix)) + if a is None or b is None: return None + return Line(a,b) + + def __str__(self): return "({0},{1})".format(self.a,self.b) + def __repr__(self): return "Line({0},{1})".format(repr(self.a),repr(self.b)) + def kmeans(img): arr=np.reshape(img,(-1,3)).astype(np.float) @@ -94,11 +120,61 @@ def groupLines(points,minCount,tolerance yield ab +def computeRectiMatrix(p,q,r,s): + # p || q, r || s + vanish1=homogenize(np.cross(p.toProjective(),q.toProjective())) + vanish2=homogenize(np.cross(r.toProjective(),s.toProjective())) + horizon=homogenize(np.cross(vanish1,vanish2)) + + return np.matrix([horizon,[0,1,0],[0,0,1]]) + + +def scoreMatrix(matrix,p,r,lines): + p_=p.transform(matrix) + r_=r.transform(matrix) + if p_ is None or r_ is None: + return math.inf + score=0 + for ab in lines: + if ab is p or ab is r: continue + ab_=ab.transform(matrix) + if ab_ is None: + score+=math.pi/2 + continue + alpha=min(ab_.computeAngle(p_), ab_.computeAngle(r_)) + if alpha<=math.pi/30: + score+=alpha + else: score+=math.pi/2 + return score + + +def groupParallels(lines,tolerance,w): + ctrl=False + for (i,p) in enumerate(lines): + for (j,q) in enumerate(lines[i+1:]): + a=p.intersect(q) + if a.y>0 and a.x0 else math.pi/2+alpha,3),repr(line))) + (xa,ya)=line.a + (xb,yb)=line.b + cv.line(linesImg,(int(xa),int(ya)),(int(xb),int(yb)),(255,255,0),1) + res.sort() + # for row in res: print(row) + # linePack=[ + # Line(EPoint(174.457,166.127),EPoint(174.96,27.253)), + # Line(EPoint(191.333,38.075),EPoint(191.485,71.227)), + # Line(EPoint(210.117,167.092),EPoint(205.0,50.0)), + # Line(EPoint(127.7,25.6),EPoint(120.172,179.405)), + # Line(EPoint(127.809,58.481),EPoint(124.324,127.427)), + # Line(EPoint(85.964,191.64),EPoint(97.68,14.477)), + # Line(EPoint(56.447,124.662),EPoint(54.889,137.918)) + # ] + # linePack=[ + # Line(EPoint(56.447,124.662),EPoint(139.695,128.104)), + # Line(EPoint(288.267,74.433),EPoint(191.485,71.227)), + # Line(EPoint(252.926,29.71),EPoint(174.96,27.253)), + # Line(EPoint(274.412,120.07),EPoint(41.065,112.759)), + # Line(EPoint(289.674,108.019),EPoint(26.17,100.538)), + # Line(EPoint(240.702,107.818),EPoint(41.065,112.759)), + # Line(EPoint(174.457,166.127),EPoint(88.192,164.5)) + # ] + # for (i,p) in enumerate(linePack): + # for q in linePack[i+1:]: + # print(p.intersect(q)) + # show(linesImg) + + # parallels=[] + # for (i,ab) in enumerate(lines): + # for cd in lines[i+1:]: + # if ab.computeAngle(cd)>math.pi/4: + # continue + # parallels.append((ab,cd)) + # print("parallel lines candidate pairs:",len(parallels)) + + # parallels=list(groupParallels(lines,50,w)) + # print("parallel triples:",len(parallels)) + # for (p,q,r) in parallels: + # print(p,q,r) + # print(p.intersect(q)) + # print(p.intersect(r)) + # print(q.intersect(r)) + # print() + # matsImg_=np.copy(matsImg) + # for pi in (p,q,r): + # cv.line(matsImg_,(int(pi.a.x),int(pi.a.y)),(int(pi.b.x),int(pi.b.y)),(0,255,255),1) + # show(matsImg_) + + # p=Line(corners[0],corners[1]) + # q=Line(corners[2],corners[3]) + # r=Line(corners[1],corners[2]) + # s=Line(corners[3],corners[0]) + # + # matrix=computeRectiMatrix(p,q,r,s) + # print(matrix) + # for (point,contour) in stoneLocs: + # point_=EPoint.fromProjective(transformPoint(point.toProjective(),matrix)) + # # print(point,"->",point_) + # cv.line(matsImg,(int(point.x),int(point.y)),(int(point_.x),int(point_.y)),(0,255,255),1) + # points1=np.float32([[p.x-x1,p.y-y1] for p in corners]) + # points2=np.float32([[0,0],[0,400],[400,400],[400,0]]) + # print(points1) + # print(points2) + # mat=cv.getPerspectiveTransform(points1,points2) + # print(mat) + # show(rect) + # warped=cv.warpPerspective(rect,matrix,(400,400)) + # show(warped) + + # mats=[] + # for (i,(p,q)) in enumerate(parallels): + # for (r,s) in parallels[i+1:]: + # if p is r or p is s or q is r or q is s: + # continue + # matrix=computeRectiMatrix(p,q,r,s) + # score=scoreMatrix(matrix,p,r,lines) + # mats.append((score,p,q,r,s,matrix)) + # mats.sort(key=lambda x: x[0]) + # for (score,p,q,r,s,matrix) in mats[:4]: + # print(score,p,q,r,s,matrix) + # matsImg_=np.copy(matsImg) + # for ab in (p,q,r,s): + # ((xa,ya),(xb,yb))=(ab.a,ab.b) + # cv.line(matsImg_,(int(xa),int(ya)),(int(xb),int(yb)),(255,255,0),1) + # show(matsImg_) + # for (score,p,q,r,s,matrix) in mats[-4:]: + # print(score,p,q,r,s,matrix) + # matsImg_=np.copy(matsImg) + # for ab in (p,q,r,s): + # ((xa,ya),(xb,yb))=(ab.a,ab.b) + # cv.line(matsImg_,(int(xa),int(ya)),(int(xb),int(yb)),(0,0,255),1) + # show(matsImg_) diff --git a/src/analyzer/epoint.py b/src/analyzer/epoint.py --- a/src/analyzer/epoint.py +++ b/src/analyzer/epoint.py @@ -1,6 +1,12 @@ import math +def homogenize(v): + for k in v: + if k!=0: return v/k + return v + + ## Euclidean 2D plane point: (x,y). class EPoint: def __init__(self,x,y): @@ -21,6 +27,12 @@ class EPoint: def toProjective(self): return (1,self._x,self._y) + def toPolar(self,center): + v=self-center + alpha=math.atan2(v.y,v.x) + k=self.dist(center) + return (alpha,k) + def dist(self,a): return math.sqrt((self._x-a._x)**2+(self._y-a._y)**2)