Skip to content
This repository has been archived by the owner on Sep 2, 2024. It is now read-only.

Focus Points

Ryan Peach edited this page Oct 27, 2015 · 6 revisions

#Getting Polygons

def findPolys(img): 
 	"""Filters the img, finds the contours, and returns the polys.""" 
 	img = img.copy() 
 	try: 
 		gray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY);		#Convert Image captured from Image Input to GrayScale 
 	except: 
 		gray = img 
 		print "Already Gray." 
 	edges = cv2.Canny(gray, 100 , 200, 3);			#Apply Canny edge detection on the gray image 
 
 
 	find = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # Find contours with hierarchy 
 	heirarchy = find[2][0] 	#the last index is the heirarchy, it is contained within a one value array 
 	contours = find[1]		#The second index is the contour list 
 
 
 	#Return approximate polygons 
 	polys = [] 
 	global DTOL 
 	for c in contours: 
 		temp = cv2.approxPolyDP(np.array(c),DTOL,True) 
 		polys.append(temp[:,0]) 
 	return polys, heirarchy 

#Retrieve Focus Points Focus points are the center of this app's scanning capabilities. They consist of a square box which contain one or two, filled or unfilled convex geometric shapes. They are listed in the "out" and "depth" outputs of this method, and the length of each out corresponds to the polygon shape of the innermost border.

 #Code copied and modified from https://github.com/bharathp666/opencv_qr 
 def findFocusPoints(polys, heirarchy): 
 	"""Returns Border Poly. Checks that the QR info matches the border found.""" 
 	focus, done = [], [] 
 	for i in range(len(polys)): 
 		k, obj = i, [] 
 		if i not in done:		#Check that through navigation you haven't been here before 
 			done.append(i) 
 
 
 			while heirarchy[k][2] != -1: #Navigate the heirarchy 
 				k = heirarchy[k][2] 
 				done.append(k) 
 				obj.append(k) 
 			if heirarchy[k][2] != -1: obj.append(k) #Add the last one 
 

 			#Check if there are enough polys to count as a potential focus point 
 			obj = [polys[x] for x in obj] 
 			if len(obj) >= 5: 
 				focus.append(obj[0:len(obj)]) #Get the last 5 elements and add them as a focus point 
 				continue 
 
 
 	#Filter the focus points for their innermost border 
 	out,depth = [],[] 
 	for f in focus: 
 		i = findInnerBorder(f) #Checks the shapes and looks for a square, returns innermost border 
 		if i>0:					#If found, append to out 
 			out.append(f[i-2]) #Fix this 2
 			depth.append(len(f)-i) 
 
 
 	#Return the borders 
 	return out, depth 

#Classification ##Get Reference Point The reference point has a greater depth than all other points. As such, it can be detected using a simple max/index function:

def getRef(fp,depth):
	i = depth.index(np.max(depth))
	return centroid(fp[i])

##Get Inner Border The inner border is the deepest square polygon within a focus point. One below the inner border is the shape of the polygon itself, and one below that is the region containing the "fill" if the inner region is unfilled. This method also checks that all qualifications are met to be a valid focus point.

def findInnerBorder(cnts):
	"""Checks shape of each contour from last to -5 and finds the first 'square.' Returns 0 if none exists."""
	for x in range(len(cnts)):
		cnt = cnts[-x]
		if cv2.isContourConvex(cnt) and len(cnt)==4 and allSameLength(cnt):
			return -x+3 #Unsure why 3 is needed here...
	else: return 0

##Corners Corners are specific focus points defining the outside border of the scan. They are defined as having square shapes, and being filled. There must be four within an image to qualify a valid scan, one of which must be a reference, which is deeper than the others but may have other polygon shapes(needs to be implemented). They are sorted counter-clockwise from the reference point.

def findCorners(fp):
	"""Classifies squares and selects the four most likely to be corners"""
	#Find all focus points of length four and calculate all of their angles to other fours
	fours = list(filter(lambda z: len(z)==4, fp))
	cents = map(lambda z: tuple(centroid(z)), fours)
	angles = lambda x: [angle(x,y,z) for y in cents for z in cents if x != y and y != z and x != z]

	#Classify corners as having 2 right angles
	out = []
	for c in cents:
		if len(filter(lambda z: np.absolute(z-90.0)<ATOL, angles(c)))>=2 and c not in out:
			out.append(c)

	#Return their centroids
	if len(out)!=4: raise Exception("Corners not Detected!")
	else: print out
	return out

def sortCorners(corners):
	"""Sort edges by distance."""
	cent = centroid(corners) #Get the centroid of the four corners
	polar = map(lambda z: np.angle(complex(*tuple(np.array(z)-np.array(cent))),deg=True),corners) #Get the polar angle from centroid
	sort = sorted(zip(corners,polar), key=lambda x: x[1]) #Sort by the polar coords
	keys = [x for x,y in sort] #Return just the keys

	return keys
Clone this wiki locally