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()