Files @ 6d4447a2e050
Branch filter:

Location: OneEye/exp/hough.py - annotation

Laman
filtering close points, detecting dominant angles
6d4447a2e050
6d4447a2e050
6d4447a2e050
6f867d8eac54
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6d4447a2e050
6f867d8eac54
6f867d8eac54
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
ffa9f7f12374
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
6d4447a2e050
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
6f867d8eac54
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
6f867d8eac54
891cf60dcb1e
6f867d8eac54
6f867d8eac54
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
6f867d8eac54
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
891cf60dcb1e
6f867d8eac54
ffa9f7f12374
ffa9f7f12374
ffa9f7f12374
import sys
sys.path.append("../src")

import os
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)
		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 _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()


def filterVert(edges):
	kernel = np.array([[1,0,1],[1,0,1],[1,0,1]],np.uint8)
	edges = cv.erode(edges,kernel)
	kernel=np.array([[0,1,0],[0,1,0],[0,1,0]],np.uint8)
	edges=cv.dilate(edges,kernel)
	return edges

def filterHor(edges):
	kernel = np.array([[1,1,1],[0,0,0],[1,1,1]],np.uint8)
	edges = cv.erode(edges,kernel)
	kernel=np.array([[0,0,0],[1,1,1],[0,0,0]],np.uint8)
	edges=cv.dilate(edges,kernel)
	return edges

def filterDiag(edges):
	kernel = np.array([[0,0,1],[1,0,0],[0,1,0]],np.uint8)
	edges1 = cv.erode(edges,kernel)
	kernel=np.array([[1,0,0],[0,1,0],[0,0,1]],np.uint8)
	edges1=cv.dilate(edges1,kernel)

	kernel = np.array([[0,1,0],[1,0,0],[0,0,1]],np.uint8)
	edges2 = cv.erode(edges,kernel)
	kernel=np.array([[0,0,1],[0,1,0],[1,0,0]],np.uint8)
	edges2=cv.dilate(edges2,kernel)

	return edges1+edges2

def prepareEdgeImg(img):
	gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
	show(gray,"greyscale image")
	edges=cv.Canny(gray,70,130)
	show(edges,"Canny edge detector")
	edges=filterHor(edges)+filterVert(edges)+filterDiag(edges)
	show(edges,"kernel filtered edges")
	return edges

def houghLines(bwImg):
	colorImg=cv.cvtColor(bwImg,cv.COLOR_GRAY2BGR)
	lines = cv.HoughLinesP(bwImg,1,np.pi/180,10,minLineLength=10,maxLineGap=40)
	if lines is None: lines=[]
	for line in lines:
		x1,y1,x2,y2 = line[0]
		cv.line(colorImg,(x1,y1),(x2,y2),(0,255,0),1)

	show(colorImg)


if __name__=="__main__":
	i=sys.argv[1]
	annotations=DataFile("/home/laman/Projekty/python/oneEye/images/annotations.json.gz")
	filename="{0}.jpg".format(i)
	img=cv.imread(os.path.join("/home/laman/Projekty/python/oneEye/images/",filename))
	(x1,y1,x2,y2)=computeBoundingBox(annotations[filename][0])
	img=img[y1:y2, x1:x2, :]
	# blurred=cv.GaussianBlur(img,(5,5),0)
	# small=cv.resize(img,None,fx=0.5,fy=0.5,interpolation=cv.INTER_AREA)
	small=img
	clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
	gray=cv.cvtColor(small,cv.COLOR_BGR2GRAY)
	# gray=clahe.apply(gray)
	show(gray)
	edges=cv.Canny(gray,70,130)
	show(edges)
	edges=filterHor(edges)+filterVert(edges)+filterDiag(edges)
	show(edges)


	# kernel = np.ones((2,2),np.uint8)
	# edges = cv.morphologyEx(edges, cv.MORPH_DILATE, kernel)
	# show(edges)
	# edges=cv.morphologyEx(edges,cv.MORPH_ERODE,kernel)
	# show(edges)
	colorEdges=cv.cvtColor(edges,cv.COLOR_GRAY2BGR)

	# houghLines(edges)
	h=HoughTransform(edges)
	h.extract()