diff --git a/exp/hough.py b/exp/hough.py
--- a/exp/hough.py
+++ b/exp/hough.py
@@ -1,5 +1,8 @@
 import os
 import sys
+import math
+from datetime import datetime
+import logging as log
 
 import numpy as np
 import cv2 as cv
@@ -7,6 +10,49 @@ import cv2 as cv
 from annotations import DataFile,computeBoundingBox
 
 
+class HoughTransform:
+	def __init__(self,img):
+		(h,w)=img.shape[:2]
+		diagLen=np.sqrt(h**2+w**2)
+		self._center=(w//2,h//2)
+		self._acc=np.zeros((360,int(diagLen//2)+1),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)
+		log.debug(sorted(list(findPeaks(self._acc)),key=lambda rc: self._acc[rc],reverse=True)[:2*19])
+		show(img,"Hough transform accumulator")
+
+	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
+		log.debug("Hough updated in %s s",round(datetime.now().timestamp()-start,3))
+
+	def _computeDist(self,x,y,alphaDeg):
+		alphaRad=alphaDeg*math.pi/180
+		(x0,y0)=self._center
+		(dx,dy)=(x-x0,y-y0)
+		d=dx*math.cos(alphaRad)+dy*math.sin(alphaRad)
+		return int(d)
+
+
+def findPeaks(arr2d): # naive implementation
+	(h,w)=arr2d.shape
+	neighbours=[(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]
+	for r in range(h):
+		for c in range(w):
+			if all(r+dr<0 or r+dr>=h or c+dc<0 or c+dc>=w or arr2d[r,c]>arr2d[r+dr,c+dc] or (i<4 and arr2d[r,c]>=arr2d[r+dr,c+dc]) for (i,(dr,dc)) in enumerate(neighbours)):
+				yield (r,c)
+
+
 def show(img,filename="x"):
 	cv.imshow(filename,img)
 	cv.waitKey(0)
@@ -14,7 +60,6 @@ def show(img,filename="x"):
 
 
 def filterVert(edges):
-	# !! cv.morphologyEx()
 	kernel = np.array([[1,0,1],[1,0,1],[1,0,1]],np.uint8)
 	edges = cv.erode(edges,kernel)
 	kernel=np.array([[0,1,0],[0,1,0],[0,1,0]],np.uint8)
@@ -41,6 +86,15 @@ def filterDiag(edges):
 
 	return edges1+edges2
 
+def prepareEdgeImg(img):
+	gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
+	show(gray,"greyscale image")
+	edges=cv.Canny(gray,70,130)
+	show(edges,"Canny edge detector")
+	edges=filterHor(edges)+filterVert(edges)+filterDiag(edges)
+	show(edges,"kernel filtered edges")
+	return edges
+
 def houghLines(bwImg):
 	colorImg=cv.cvtColor(bwImg,cv.COLOR_GRAY2BGR)
 	lines = cv.HoughLinesP(bwImg,1,np.pi/180,10,minLineLength=10,maxLineGap=40)
@@ -78,20 +132,7 @@ if __name__=="__main__":
 	# edges=cv.morphologyEx(edges,cv.MORPH_ERODE,kernel)
 	# show(edges)
 	colorEdges=cv.cvtColor(edges,cv.COLOR_GRAY2BGR)
-	# show(blurred)
-	# show(small)
 
-	# lines = cv.HoughLines(edges,1,np.pi/180,200)
-	# if lines is None: lines=[]
-	# for line in lines:
-	# 	rho,theta = line[0]
-	# 	a = np.cos(theta)
-	# 	b = np.sin(theta)
-	# 	x0 = a*rho
-	# 	y0 = b*rho
-	# 	x1 = int(x0 + 1000*(-b))
-	# 	y1 = int(y0 + 1000*(a))
-	# 	x2 = int(x0 - 1000*(-b))
-	# 	y2 = int(y0 - 1000*(a))
-	# 	cv.line(colorEdges,(x1,y1),(x2,y2),(0,0,255),1)
-	houghLines(edges)
+	# houghLines(edges)
+	h=HoughTransform(edges)
+	h.extract()