Changeset - 184d592b02dd
[Not reviewed]
default
0 3 0
Laman - 6 years ago 2019-02-22 17:49:44

returning and visualizing detected lines
3 files changed with 42 insertions and 6 deletions:
0 comments (0 inline, 0 general)
exp/board_detect.py
Show inline comments
 
@@ -4,25 +4,25 @@ sys.path.append("../src")
 

	
 
import os
 
import math
 
import random
 
import logging as log
 

	
 
import cv2 as cv
 
import numpy as np
 
import scipy.cluster
 
import scipy.ndimage
 
import scipy.signal
 

	
 
from polar_hough import PolarHough
 
from geometry import Line
 
from annotations import DataFile,computeBoundingBox
 
from hough import show,prepareEdgeImg,HoughTransform
 
from analyzer.epoint import EPoint
 
from analyzer.corners import Corners
 

	
 
random.seed(361)
 
log.basicConfig(level=log.DEBUG,format="%(message)s")
 

	
 

	
 
def kmeans(img):
 
	arr=np.reshape(img,(-1,3)).astype(np.float)
 
	wood=[193,165,116]
 
@@ -102,26 +102,31 @@ class BoardDetector:
 

	
 
		# detect black and white stones
 
		stones=self._detectStones(quantized,black,white)
 

	
 
		# detect lines from edges and stones
 
		edgeImg=prepareEdgeImg(rect)
 
		hough=HoughTransform(edgeImg)
 
		stonesImg=np.zeros((self._rectH,self._rectW),np.uint8)
 
		for (point,c) in stones:
 
			cv.circle(stonesImg,(int(point.x),int(point.y)),2,255,-1)
 
		# cv.drawContours(stonesImg,[c for (point,c) in stones],-1,255,-1)
 
		show(stonesImg,"detected stones")
 
		hough.update(stonesImg,5)
 
		hough.extract()
 
		hough.update(stonesImg,10)
 
		lines=hough.extract()
 

	
 
		linesImg=np.copy(rect)
 
		for line in lines:
 
			self._drawLine(linesImg,line)
 
		show(linesImg,"detected lines")
 

	
 
		# # detect vanishing points of the lines
 
		# imgCenter=EPoint(w//2-x1, h//2-y1)
 
		# (a,b,c,d)=(p-EPoint(x1,y1) for p in self._annotations[filename][0])
 
		# (p,q,r,s)=(Line(a,b),Line(b,c),Line(c,d),Line(d,a))
 
		# v1=p.intersect(r)
 
		# v2=q.intersect(s)
 
		# log.debug("true vanishing points: %s ~ %s, %s ~ %s",v1,v1.toPolar(imgCenter),v2,v2.toPolar(imgCenter))
 
		# vanish=self._detectVanishingPoints(lines,imgCenter,(v1.toPolar(imgCenter),v2.toPolar(imgCenter)))
 
		#
 
		# # rectify the image
 
		# matrix=self._computeTransformationMatrix(vanish,lines)
 
@@ -213,19 +218,37 @@ class BoardDetector:
 
		matrix=cv.getPerspectiveTransform(np.float32(abcd),np.float32(abcd_))
 
		log.debug("transformation matrix: %s",matrix)
 

	
 
		rect=np.copy(self._rect)
 
		for point in (a,b,c,d):
 
			cv.drawMarker(rect,(int(point.x),int(point.y)),(0,255,255),cv.MARKER_TILTED_CROSS)
 
		show(rect)
 
		transformed=cv.warpPerspective(rect,matrix,(self._rectW,self._rectH))
 
		show(transformed)
 

	
 
		return matrix
 

	
 
	def _drawLine(self,img,line):
 
		(h,w)=img.shape[:2]
 
		corners=[EPoint(0,0),EPoint(w,0),EPoint(0,h),EPoint(w,h)] # NW NE SW SE
 
		borders=[
 
			[Line.fromPoints(corners[0],corners[1]), Line.fromPoints(corners[2],corners[3])], # N S
 
			[Line.fromPoints(corners[0],corners[2]), Line.fromPoints(corners[1],corners[3])] # W E
 
		]
 

	
 
		(a,b)=(line.intersect(borders[0][0]), line.intersect(borders[0][1]))
 
		log.debug("%s %s",line,(a,b))
 
		if not a or not b:
 
			(a,b)=(line.intersect(borders[1][0]), line.intersect(borders[1][1]))
 
			log.debug("* %s %s",line,(a,b))
 
		if any(abs(x)>10**5 for x in [*a,*b]):
 
			log.debug("ignored")
 
			return
 
		cv.line(img,(int(a.x),int(a.y)),(int(b.x),int(b.y)),[0,255,0])
 

	
 

	
 
if __name__=="__main__":
 
	detector=BoardDetector(sys.argv[2])
 
	filepath=sys.argv[1]
 
	filename=os.path.basename(filepath)
 
	img=cv.imread(filepath)
 
	detector(img,filename)
exp/geometry.py
Show inline comments
 
@@ -4,25 +4,26 @@ from analyzer.epoint import EPoint
 

	
 

	
 
class Line:
 
	def __init__(self,alpha,d):
 
		self._alpha=alpha
 
		self._d=d
 
		self._sin=math.sin(alpha)
 
		self._cos=math.cos(alpha)
 

	
 
	@staticmethod
 
	def fromNormal(a,b,c):
 
		"""ax + by + c = 0"""
 
		norm=-c/abs(c)*math.sqrt(a**2+b**2)
 
		sign=-c/abs(c) if c!=0 else 1
 
		norm=sign*math.sqrt(a**2+b**2)
 
		(a_,b_,c_)=(a/norm,b/norm,c/norm)
 
		alpha=math.acos(a_) if b_>=0 else 2*math.pi-math.acos(a_)
 
		return Line(alpha,-c_)
 

	
 
	@staticmethod
 
	def fromPoints(a,b):
 
		return Line.fromNormal(a.y-b.y, b.x-a.x, (b.y-a.y)*a.x+(a.x-b.x)*a.y)
 

	
 
	def toNormal(self):
 
		# https://en.wikipedia.org/wiki/Line_(mathematics)#In_normal_form
 
		"""ax + by + c = 0"""
 
		return (self._cos, self._sin, -self._d)
exp/hough.py
Show inline comments
 
import sys
 
sys.path.append("../src")
 

	
 
import math
 
from datetime import datetime
 
import logging as log
 

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

	
 
from geometry import EPoint,Line
 

	
 
DEBUG=True
 

	
 

	
 
class LineBag:
 
	def __init__(self):
 
		self._lines=[]
 

	
 
	def put(self,score,alpha,beta,peaks):
 
		self._lines.append((score,alpha,beta,peaks))
 

	
 
	def pull(self,count):
 
		self._lines.sort(reverse=True)
 
@@ -36,33 +38,43 @@ class HoughTransform:
 
		self._angleBandwidth=30 # degrees
 

	
 
		(h,w)=img.shape[:2]
 
		self._diagLen=int(np.sqrt(h**2+w**2))+1
 
		self._center=(w//2,h//2)
 
		self._acc=np.zeros((180,self._diagLen),dtype=np.int32)
 

	
 
		self.update(img)
 

	
 
	def extract(self):
 
		img=self._createImg()
 
		self.show(img)
 
		(ab,cd)=self._detectLines()
 
		lines=self._detectLines()
 
		res=[]
 
		i=0
 
		for (score,alpha,beta,peaks) in (ab,cd):
 
		for (score,alpha,beta,peaks) in lines:
 
			log.debug("score: %s",score)
 
			log.debug("alpha, beta: %s, %s",alpha,beta)
 
			self._drawLine(img,alpha,beta,peaks,i)
 

	
 
			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))
 
			i+=1
 

	
 
		self.show(img)
 
		return res
 

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