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<h:	img[y,x]=color
+			else: img[y%h,-x]=color
+
 
 def findPeaks(arr2d): # a naive implementation
 	(h,w)=arr2d.shape