# HG changeset patch # User Laman # Date 2019-01-22 11:18:50 # Node ID 40cc3b625eb2d6e3d2a44eda7fdb5cdb5d9844ea # Parent 12717eacf401036ae09046584698ab457ed7f35d work on polar hough diff --git a/exp/stone_detect.py b/exp/stone_detect.py --- a/exp/stone_detect.py +++ b/exp/stone_detect.py @@ -4,11 +4,13 @@ sys.path.append("../src") import os import math import random +import itertools import cv2 as cv import numpy as np import scipy.cluster import scipy.ndimage +import scipy.signal from annotations import DataFile,computeBoundingBox from hough import show @@ -53,6 +55,62 @@ class Line(): def __repr__(self): return "Line({0},{1})".format(repr(self.a),repr(self.b)) +class PolarHough: + # http://www.cis.pku.edu.cn/vision/vpdetection/LiPYZ10isvc.pdf + def __init__(self,anglePrecision,lengthPrecision): + self._anglePrecision=anglePrecision + self._lengthPrecision=lengthPrecision + self._maxLength=4096 + n=math.ceil(2*math.pi/anglePrecision) + self._acc=[[] for i in range(n)] + + def put(self,item): + k=int(item[0]//self._anglePrecision) + self._acc[k].append(item) + + def extract(self,count): + vanishingPoints=[] + angles=self._extractAngles(count) + angles=[alpha for (alpha,prominence) in angles] + bins=self._mapAngles(angles) + for (alpha,bin) in zip(angles,bins): + (length,sampleCount)=self._extractLength([dist for (beta,dist) in bin]) + vanishingPoints.append((alpha,length)) + return vanishingPoints + + def _extractAngles(self,k): + lens=np.array(list(map(len,self._acc))) + print(lens) + (peakKeys,info)=scipy.signal.find_peaks(lens,prominence=0) + res=sorted(zip(info["prominences"],peakKeys),reverse=True)[:k] + res=[(key*self._anglePrecision,prominence) for (prominence,key) in res] + print("(angle, prominence):",res,"...",[alpha/self._anglePrecision for (alpha,_) in res]) + return res + + def _mapAngles(self,angles): + res=[[] for alpha in angles] + for (i,bin) in enumerate(self._acc): + beta=i*self._anglePrecision + key=min(zip(map(lambda alpha: angleDiff(alpha,beta), angles), itertools.count()))[1] + res[key].extend(bin) + return res + + def _extractLength(self,arr): + acc=np.zeros(self._maxLength+1,dtype=np.int32) + for dist in arr: + dist=min(dist,self._maxLength) + acc[int(dist//self._lengthPrecision)]+=1 + res=acc.argmax() + print("(length, count):",(res*self._lengthPrecision,acc[res])) + return (res*self._lengthPrecision,acc[res]) + + +def angleDiff(alpha,beta): + diff=abs(alpha-beta) + if diff>math.pi: diff=2*math.pi-diff + return diff + + def kmeans(img): arr=np.reshape(img,(-1,3)).astype(np.float) colors=np.array([[0,0,0],[255,255,255],[193,165,116]],np.float) @@ -190,9 +248,9 @@ if __name__=="__main__": kernel=np.ones((3,3),np.uint8) maskB=cv.inRange(rect,centers[0]-unit,centers[0]+unit) maskB=cv.morphologyEx(maskB,cv.MORPH_OPEN,kernel,iterations=1) - maskB=cv.erode(maskB,kernel,iterations=2) + maskB=cv.erode(maskB,kernel,iterations=4) maskW=cv.inRange(rect,centers[1]-unit,centers[1]+unit) - maskW=cv.erode(maskW,kernel,iterations=2) + maskW=cv.erode(maskW,kernel,iterations=3) show(img,filename) show(maskB,filename) @@ -241,92 +299,22 @@ if __name__=="__main__": (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_) + show(linesImg) - # 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_) + imgSize=img.shape[:2] + print("image size:",imgSize) + imgCenter=EPoint(imgSize[1]/2,imgSize[0]/2)-EPoint(x1,y1) + polarHough=PolarHough(math.pi/180,10) + for (i,ab) in enumerate(lines): + for cd in lines[i+1:]: + point=ab.intersect(cd) + if 0<=point.x<=w and 0<=point.y<=h: continue + print(point,"->",point.toPolar(imgCenter)) + polarHough.put(point.toPolar(imgCenter)) + vanish=[EPoint.fromPolar(p,imgCenter) for p in polarHough.extract(2)] + print(vanish) + (a,b,c,d)=corners + (p,q,r,s)=(Line(a,b),Line(b,c),Line(c,d),Line(d,a)) + v1=p.intersect(r) + v2=q.intersect(s) + print("true vanishing points:",v1,"~",v1.toPolar(imgCenter),"and",v2,"~",v2.toPolar(imgCenter)) diff --git a/src/analyzer/epoint.py b/src/analyzer/epoint.py --- a/src/analyzer/epoint.py +++ b/src/analyzer/epoint.py @@ -24,12 +24,20 @@ class EPoint: if point.item(0)==0: return None return EPoint(point.item(1)/point.item(0),point.item(2)/point.item(0)) + @staticmethod + def fromPolar(point,center): + (alpha,length)=point + x=math.cos(alpha) + y=math.sin(alpha) + return length*EPoint(x,y)+center + def toProjective(self): return (1,self._x,self._y) def toPolar(self,center): v=self-center alpha=math.atan2(v.y,v.x) + if alpha<0: alpha+=2*math.pi k=self.dist(center) return (alpha,k)