Changeset - 1ceee1fdf122
[Not reviewed]
default
0 1 0
Laman - 6 years ago 2019-02-08 13:31:14

computing and visualising grid parameters
1 file changed with 64 insertions and 13 deletions:
0 comments (0 inline, 0 general)
exp/hough.py
Show inline comments
 
@@ -4,57 +4,68 @@ sys.path.append("../src")
 
import os
 
import math
 
from datetime import datetime
 
import logging as log
 

	
 
import numpy as np
 
import scipy.optimize
 
import cv2 as cv
 

	
 
from annotations import DataFile,computeBoundingBox
 
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):
 
		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)
 
		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=[]
 
		for (alphaDeg,d) in peaks:
 
			alphaRad=alphaDeg*math.pi/180
 
			point=EPoint.fromPolar((alphaRad,d),center)
 
@@ -67,13 +78,13 @@ class HoughTransform:
 
			if ctrl: res.append((alphaDeg,d))
 
		return res
 

	
 
	def _detectDominantAngles(self,peaks):
 
		angles=[alpha for (alpha,d) in peaks]
 
		n=len(angles)
 
		bandwidth=30
 
		bandwidth=self._angleBandwidth
 
		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
 
@@ -84,12 +95,52 @@ class HoughTransform:
 
		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 _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
 
	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):
0 comments (0 inline, 0 general)