Changeset - 40cc3b625eb2
[Not reviewed]
default
0 2 0
Laman - 6 years ago 2019-01-22 11:18:50

work on polar hough
2 files changed with 86 insertions and 90 deletions:
0 comments (0 inline, 0 general)
exp/stone_detect.py
Show inline comments
 
import sys
 
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
 
from analyzer.epoint import EPoint,homogenize
 
from analyzer.grid import transformPoint
 

	
 
random.seed(361)
 

	
 

	
 
class Line():
 
	def __init__(self,a,b):
 
		self.a=a
 
@@ -44,24 +46,80 @@ class Line():
 
		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))
 

	
 

	
 
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)
 
	print(colors)
 
	(centers,distortion)=scipy.cluster.vq.kmeans(arr,colors)
 
	print("k-means centers:",centers)
 
	return centers
 

	
 

	
 
def quantize(img,centers):
 
	origShape=img.shape
 
	data=np.reshape(img,(-1,3))
 
@@ -181,27 +239,27 @@ if __name__=="__main__":
 
	print("x3,x4,y3,y4:",x3,x4,y3,y4)
 
	rect=img[y3:y4,x3:x4,:]
 
	centers=kmeans(rect)
 
	print("x1,x2,y1,y2:",(x1,x2,y1,y2))
 
	img[y1:y2,x1:x2,:]=quantize(img[y1:y2,x1:x2,:],centers)
 
	print("image quantized")
 

	
 
	rect=img[y1:y2,x1:x2]
 
	unit=np.array([1,1,1],dtype=np.uint8)
 
	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)
 
	show(maskW,filename)
 
	stones=cv.bitwise_or(maskB,maskW)
 
	show(stones)
 

	
 
	stoneDims=(w/19,h/19)
 
	print("stone dims:",tuple(x/2 for x in stoneDims),"-",stoneDims)
 

	
 
	(contours,hierarchy)=cv.findContours(stones,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE)
 
	stoneLocs=filterStones(contours,stones,stoneDims)
 
@@ -232,101 +290,31 @@ if __name__=="__main__":
 

	
 
	print("valid lines:",len(lineDict))
 
	lines=sorted(lineDict.values(), key=lambda ab: len(ab.points), reverse=True)
 
	res=[]
 
	for line in lines:
 
		v=line.b-line.a
 
		alpha=math.atan(v.y/v.x)
 
		res.append((round(math.pi/2-alpha if alpha>0 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_)
 
	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))
src/analyzer/epoint.py
Show inline comments
 
@@ -15,30 +15,38 @@ class EPoint:
 

	
 
	@property
 
	def x(self): return self._x
 
	
 
	@property
 
	def y(self): return self._y
 

	
 
	@staticmethod
 
	def fromProjective(point):
 
		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)
 

	
 
	def dist(self,a):
 
		return math.sqrt((self._x-a._x)**2+(self._y-a._y)**2)
 

	
 
	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)
 

	
0 comments (0 inline, 0 general)