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
 
@@ -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
0 comments (0 inline, 0 general)