import itertools
import math
import logging as log
import numpy as np
import scipy.signal
from geometry import angleDiff
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,trueVs):
vanishingPoints=[]
angles=self._extractAngles(count,tuple(v[0] for v in trueVs))
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,trueAngles):
lens=np.array([0]+list(map(len,self._acc))+[0])
marked=np.copy(lens[1:-1])
for alpha in trueAngles:
key=int(alpha/self._anglePrecision)
marked[key]=-marked[key]-1
log.debug(marked)
(peakKeys,info)=scipy.signal.find_peaks(lens,prominence=0)
res=sorted(zip(info["prominences"],peakKeys),reverse=True)[:k]
res=[((key-1)*self._anglePrecision,prominence) for (prominence,key) in res]
log.debug("(angle, prominence): %s ... %s",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()
log.debug("(length, count): %s",(res*self._lengthPrecision,acc[res]))
return (res*self._lengthPrecision,acc[res])