Changeset - 6d4447a2e050
[Not reviewed]
default
0 1 0
Laman - 6 years ago 2019-02-07 11:27:25

filtering close points, detecting dominant angles
1 file changed with 47 insertions and 3 deletions:
0 comments (0 inline, 0 general)
exp/hough.py
Show inline comments
 
import sys
 
sys.path.append("../src")
 

	
 
import os
 
import sys
 
import math
 
from datetime import datetime
 
import logging as log
 

	
 
import numpy as np
 
import cv2 as cv
 

	
 
from annotations import DataFile,computeBoundingBox
 
from analyzer.epoint import EPoint
 

	
 

	
 
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])
 
		peaks=sorted(list(findPeaks(self._acc)),key=lambda rc: self._acc[rc],reverse=True)[:2*19]
 
		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")
 

	
 
	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 _filterClose(self,peaks): # a naive implementation
 
		minDist=10
 
		center=EPoint(*self._center)
 
		res=[]
 
		for (alphaDeg,d) in peaks:
 
			alphaRad=alphaDeg*math.pi/180
 
			point=EPoint.fromPolar((alphaRad,d),center)
 
			ctrl=True
 
			for (betaDeg,e) in peaks:
 
				betaRad=betaDeg*math.pi/180
 
				point_=EPoint.fromPolar((betaRad,e),center)
 
				if point.dist(point_)<minDist and self._acc[(alphaDeg,d)]<self._acc[(betaDeg,e)]:
 
					ctrl=False
 
			if ctrl: res.append((alphaDeg,d))
 
		return res
 

	
 
def findPeaks(arr2d): # naive implementation
 
	def _detectDominantAngles(self,peaks):
 
		angles=[alpha for (alpha,d) in peaks]
 
		n=len(angles)
 
		bandwidth=30
 
		k1=0
 
		k2=1
 
		histogram=[]
 
		while k1<n:
 
			while (k2<n and angles[k1]+bandwidth>angles[k2]) or (k2>=n and angles[k1]+bandwidth>angles[k2%n]+180):
 
				k2+=1
 
			histogram.append((angles[k1],k2-k1))
 
			k1+=1
 
		log.debug("angles histogram: %s",histogram)
 
		dominantAngles=sorted(histogram,key=lambda xy: xy[1],reverse=True)
 
		alpha=dominantAngles[0]
 
		dominantAngles=[beta for beta in dominantAngles if 165>abs(alpha[0]-beta[0])>15]
 
		beta=dominantAngles[0]
 
		log.debug("dominant angles: %s, %s",alpha,beta)
 
		return (alpha[0],beta[0])
 

	
 

	
 
def findPeaks(arr2d): # a 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)
 
	cv.destroyAllWindows()
0 comments (0 inline, 0 general)