Changeset - 739df5e211d8
[Not reviewed]
default
0 3 0
Laman - 6 years ago 2019-03-02 14:54:49

fixed Hough transform input/ouput coordinates, fixed lines detection
3 files changed with 64 insertions and 15 deletions:
0 comments (0 inline, 0 general)
exp/geometry.py
Show inline comments
 
@@ -41,8 +41,24 @@ class Line:
 
		(a,b,c)=self.toNormal()
 
		return abs(a*point.x+b*point.y+c) # a**2 + b**2 == 1 for Hesse normal form
 

	
 
	def __str__(self): return "({0},{1})".format(self._alpha,self._d)
 
	def __repr__(self): return "Line({0},{1})".format(repr(self._alpha),repr(self._d))
 
	def shiftBasis(self,newBasis):
 
		(a,b,c)=self.toNormal()
 
		if a!=0:
 
			point=EPoint(-c/a,0)
 
		else:
 
			point=EPoint(0,-c/b)
 
		(x_,y_)=point-newBasis
 
		c_=-a*x_-b*y_
 
		return Line.fromNormal(a,b,c_)
 

	
 
	@property
 
	def alpha(self): return self._alpha
 

	
 
	@property
 
	def d(self): return self._d
 

	
 
	def __str__(self): return "Line({0},{1})".format(round(self._alpha,3),round(self._d))
 
	def __repr__(self): return "Line({0},{1})".format(self._alpha,self._d)
 

	
 

	
 
def angleDiff(alpha,beta):
exp/hough.py
Show inline comments
 
@@ -34,6 +34,10 @@ class LineBag:
 

	
 

	
 
class HoughTransform:
 
	"""Find line sequences with Hough transform.
 

	
 
	Uses usual image coordinates on input and output, with [0,0] in the upper left corner and [height-1,width-1] in the lower right.
 
	However, internally it uses the usual cartesian coordinates, centered at the image center. [-w/2,-h/2] in the upper left and [w/2,h/2] in the lower right."""
 
	def __init__(self,img):
 
		self._angleBandwidth=30 # degrees
 

	
 
@@ -58,10 +62,8 @@ class HoughTransform:
 
			keys=self._readLineKeys(alpha,beta)
 
			for k in peaks:
 
				(alphaDeg,d)=keys[k]
 
				alphaRad=alphaDeg*math.pi/180
 
				baseLine=Line(alphaRad,0)
 
				dd=baseLine.distanceTo(EPoint(*self._center)) # to shift d from the center to 0,0
 
				res.append(Line(alphaRad, dd+d-self._diagLen//2))
 
				line=Line(alphaDeg*math.pi/180,d-self._diagLen//2)
 
				res.append(self._transformOutput(line))
 
			i+=1
 

	
 
		self.show(img)
 
@@ -77,17 +79,21 @@ class HoughTransform:
 
					self._acc[(alphaDeg,d)]+=weight
 
		log.debug("Hough updated in %s s",round(datetime.now().timestamp()-start,3))
 

	
 
	def show(self,img=None):
 
		if img is None: img=self._createImg()
 
		show(img,"Hough transform accumulator")
 

	
 
	def _computeDist(self,x,y,alphaDeg):
 
		alphaRad=alphaDeg*math.pi/180
 
		(x0,y0)=self._center
 
		(dx,dy)=(x-x0,y-y0)
 
		(dx,dy)=(x-x0,y0-y)
 
		d=dx*math.cos(alphaRad)+dy*math.sin(alphaRad)
 
		return round(d)
 

	
 
	def _detectLines(self):
 
		bag=LineBag()
 
		for alpha in range(0,180,2):
 
			for beta in range(max(alpha-60,0),alpha+60,2):
 
		for alpha in range(0,180+60,2):
 
			for beta in range(max(alpha-60,0),min(alpha+60,180+60),2):
 
				accLine=[self._acc[key] for key in self._readLineKeys(alpha,beta)]
 
				(peaks,props)=scipy.signal.find_peaks(accLine,prominence=0)
 
				(prominences,peaks)=zip(*sorted(zip(props["prominences"],peaks),reverse=True)[:19])
 
@@ -99,16 +105,19 @@ class HoughTransform:
 
		res=[]
 
		for i in range(n+1):
 
			k=round((alpha*(n-i)+beta*i)/n)
 
			if k<0 or k>=180:
 
			if k>=180:
 
				k=k%180
 
				i=n+1-i
 
				i=n-i
 
			res.append((k,i))
 
		return res
 

	
 
	def show(self,img=None):
 
		if img is None: img=self._createImg()
 

	
 
		show(img,"Hough transform accumulator")
 
	def _transformOutput(self,line):
 
		(x,y)=self._center
 
		basis=EPoint(-x,y)
 
		shiftedLine=line.shiftBasis(basis)
 
		reflectedLine=Line(math.pi*2-shiftedLine.alpha,shiftedLine.d)
 
		log.debug("%s -> %s",line,reflectedLine)
 
		return reflectedLine
 

	
 
	def _createImg(self):
 
		maxVal=self._acc.max()
exp/tests/test_geometry.py
Show inline comments
 
@@ -65,3 +65,27 @@ class TestLine(TestCase):
 
		self.assertAlmostEqual(r.distanceTo(a),1)
 
		self.assertAlmostEqual(r.distanceTo(b),1)
 
		self.assertAlmostEqual(r.distanceTo(c),0)
 

	
 
	def testShiftBasis(self):
 
		newBasis=EPoint(-200,150)
 
		r=Line(0,-100)
 
		r_=r.shiftBasis(newBasis)
 
		self.assertAlmostEqual(r_._alpha,0)
 
		self.assertAlmostEqual(r_._d,100)
 

	
 
		s=Line(0,100)
 
		s_=s.shiftBasis(newBasis)
 
		self.assertAlmostEqual(s_._alpha,0)
 
		self.assertAlmostEqual(s_._d,300)
 

	
 
		newBasis=EPoint(-100,100)
 
		diag=100*math.sqrt(2)
 
		p=Line(math.pi*3/4,diag/2)
 
		p_=p.shiftBasis(newBasis)
 
		self.assertAlmostEqual(p_._alpha,math.pi*7/4)
 
		self.assertAlmostEqual(p_._d,diag/2)
 

	
 
		q=Line(math.pi*3/4,-diag/2)
 
		q_=q.shiftBasis(newBasis)
 
		self.assertAlmostEqual(q_._alpha,math.pi*7/4)
 
		self.assertAlmostEqual(q_._d,3/2*diag)
0 comments (0 inline, 0 general)