# HG changeset patch # User Laman # Date 2019-02-08 13:31:14 # Node ID 1ceee1fdf122fd9ba6c0205d07b9807a0e094d81 # Parent 6d4447a2e0509128d3567db00bff34d823890f71 computing and visualising grid parameters diff --git a/exp/hough.py b/exp/hough.py --- a/exp/hough.py +++ b/exp/hough.py @@ -7,6 +7,7 @@ from datetime import datetime import logging as log import numpy as np +import scipy.optimize import cv2 as cv from annotations import DataFile,computeBoundingBox @@ -15,33 +16,40 @@ from analyzer.epoint import EPoint class HoughTransform: def __init__(self,img): + self._angleBandwidth=30 # degrees + (h,w)=img.shape[:2] - diagLen=np.sqrt(h**2+w**2) + self._diagLen=int(np.sqrt(h**2+w**2))+1 self._center=(w//2,h//2) - self._acc=np.zeros((360,int(diagLen//2)+1),dtype=np.int32) + self._acc=np.zeros((180,self._diagLen),dtype=np.int32) self.update(img) def extract(self): - maxVal=self._acc.max() - arr=np.expand_dims(np.uint8(255*self._acc//maxVal),axis=2) - img=np.concatenate((arr,arr,arr),axis=2) + shift=self._diagLen//2 peaks=sorted(list(findPeaks(self._acc)),key=lambda rc: self._acc[rc],reverse=True)[:2*19] + peaks=[(alpha,d-shift) for (alpha,d) in peaks] peaks=self._filterClose(peaks) - peaks=[(alpha,d) if alpha<180 else (alpha-180,-d) for (alpha,d) in peaks] peaks.sort(key=lambda rc: rc[0]) log.debug("detected peaks: %s",peaks) - self._detectDominantAngles(peaks) - show(img,"Hough transform accumulator") + (alpha,beta)=self._detectDominantAngles(peaks) + + img=self._createImg() + doublePeaks=peaks+[(alpha+180,-d) for (alpha,d) in peaks] + params=self._computeGridParams([(gamma,d+shift) for (gamma,d) in doublePeaks if alpha<=gamma<=alpha+self._angleBandwidth]) + self._drawGridCurve(img,params,0) + params=self._computeGridParams([(gamma,d+shift) for (gamma,d) in doublePeaks if beta<=gamma<=beta+self._angleBandwidth]) + self._drawGridCurve(img,params,1) + self.show(img) def update(self,img,weight=1): start=datetime.now().timestamp() for (r,row) in enumerate(img): for (c,pix) in enumerate(row): if pix==0: continue - for alphaDeg in range(0,360): - d=self._computeDist(c,r,alphaDeg) - if d>=0: self._acc[(alphaDeg,d)]+=weight + for alphaDeg in range(0,180): + d=self._computeDist(c,r,alphaDeg)+self._diagLen//2 + self._acc[(alphaDeg,d)]+=weight log.debug("Hough updated in %s s",round(datetime.now().timestamp()-start,3)) def _computeDist(self,x,y,alphaDeg): @@ -49,9 +57,12 @@ class HoughTransform: (x0,y0)=self._center (dx,dy)=(x-x0,y-y0) d=dx*math.cos(alphaRad)+dy*math.sin(alphaRad) - return int(d) + return round(d) def _filterClose(self,peaks): # a naive implementation + """Discard points with Euclidean distance on the original image lower than 10. + From such pairs keep only the one with a higher value in the accumulator. + This can delete a series of points. If a-b and b-c are close and a>b>c, only a is kept.""" minDist=10 center=EPoint(*self._center) res=[] @@ -70,7 +81,7 @@ class HoughTransform: def _detectDominantAngles(self,peaks): angles=[alpha for (alpha,d) in peaks] n=len(angles) - bandwidth=30 + bandwidth=self._angleBandwidth k1=0 k2=1 histogram=[] @@ -87,6 +98,46 @@ class HoughTransform: log.debug("dominant angles: %s, %s",alpha,beta) return (alpha[0],beta[0]) + def _computeGridParams(self,lines): + log.debug("computing grid parameters for: %s",lines) + angles=[alpha for (alpha,d) in lines] + dists=[d for (alpha,d) in lines] + curve=lambda x,a,b,c,d: a*x**3+b*x**2+c*x+d + (params,cov)=scipy.optimize.curve_fit(curve,dists,angles) + log.debug("result: %s",params) + return params + + def show(self,img=None): + if img is None: img=self._createImg() + + show(img,"Hough transform accumulator") + + def _createImg(self): + maxVal=self._acc.max() + arr=np.expand_dims(np.uint8(255*self._acc//maxVal),axis=2) + img=np.concatenate((arr,arr,arr),axis=2) + + (h,w)=img.shape[:2] + + for x in range(0,w,4): # y axis + img[h//2,x]=[255,255,255] + for y in range(0,h,4): + img[y,w//2]=[255,255,255] + + return img + + def _drawGridCurve(self,img,params,colorKey=0): + colors=[[0,255,255],[255,0,255],[255,255,0]] + color=colors[colorKey] + (a,b,c,d)=params + (h,w)=img.shape[:2] + curve=lambda x: a*x**3+b*x**2+c*x+d + for x in range(0,w,3): + y=int(curve(x)) + if y<0 or y>=2*h: continue + if y