diff --git a/fourcell/analyze.py b/fourcell/analyze.py index ac320f4..ab6d260 100644 --- a/fourcell/analyze.py +++ b/fourcell/analyze.py @@ -1,6 +1,7 @@ import sys import cv2 import numpy as np +import math def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA): dim = None @@ -30,6 +31,35 @@ def display (image) : break exit(0) +def get_center (contour) : + M = cv2.moments(contour) + cX = int(M["m10"] / M["m00"]) + cY = int(M["m01"] / M["m00"]) + return cX, cY + +def draw_line (image, hps, a, b) : + print(f'{a} -> {b}') + lA = (hps[a-1]['x'], hps[a-1]['y']) + lB = (hps[b-1]['x'], hps[b-1]['y']) + cv2.line(image, lA, lB, [0, 255, 0], 10) + return (lA, lB) + +def horiz_angle (line) : + deltaY = line[1][1] - line[0][1] #P2_y - P1_y + deltaX = line[1][0] - line[0][0] #P2_x - P1_x + + angleInDegrees = math.degrees(math.atan2(deltaY, deltaX)) + print(angleInDegrees) + return angleInDegrees + +def verts_angle (line) : + deltaY = line[1][1] - line[0][1] #P2_y - P1_y + deltaX = line[1][0] - line[0][0] #P2_x - P1_x + + angleInDegrees = - (math.atan2(deltaX, deltaY) * 180 / math.pi) + print(angleInDegrees) + return angleInDegrees + if len(sys.argv) < 2: print('Please provide path to image for analysis') exit(1) @@ -43,7 +73,8 @@ templateFile = sys.argv[-1] print(f'Analyzing {scanImage} and creating {templateFile}') -img = cv2.imread(scanImage) +orig = cv2.imread(scanImage) +img = orig.copy() height, width = img.shape[:2] orientation = height > width @@ -65,13 +96,9 @@ else : bottom = height * 0.8 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - blur = cv2.medianBlur(gray, 31) - ret, thresh = cv2.threshold(blur, 200, 255, cv2.THRESH_BINARY) - canny = cv2.Canny(thresh, 75, 200) - contours, hierarchy = cv2.findContours(canny, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) contourList = [] @@ -79,9 +106,7 @@ areaList = [] for contour in contours: approx = cv2.approxPolyDP(contour, 0.03 * cv2.arcLength(contour, True), True) if cv2.isContourConvex(approx) : - M = cv2.moments(contour) - cX = int(M["m10"] / M["m00"]) - cY = int(M["m01"] / M["m00"]) + cX, cY = get_center(contour) if (orientation and ( cX < left or cX > right) ) or ( not orientation and ( cY < top or cY > bottom)) : area = cv2.contourArea(contour) areaList.append(area) @@ -90,6 +115,7 @@ for contour in contours: maxArea=0 maxIndex=0 +#reduce to lambda for i in range(len(areaList)) : area = areaList[i] if area > maxArea: @@ -98,9 +124,10 @@ for i in range(len(areaList)) : count = 0 holePunches = [] -centers = [] centersStr = [] areaRange = 0 +topLeft = None +minDist = 1000000 # pretty good # add position constraint @@ -110,21 +137,76 @@ while count < 6 : for i in range(len(areaList)) : area = areaList[i] if area == maxArea or area * ((100 + areaRange) / 100) > maxArea : - M = cv2.moments(contourList[i]) - cX = int(M["m10"] / M["m00"]) - cY = int(M["m01"] / M["m00"]) + cX, cY = get_center(contourList[i]) strC = f'{cX},{cY}' if strC in centersStr : continue centersStr.append(strC) - centers.append((cX, cY)) print(f'{cX},{cY}') - cv2.circle(img, (cX, cY), 40, (255, 0, 0), -1) - holePunches.append(contourList[i]) + #cv2.circle(img, (cX, cY), 40, (255, 0, 0), -1) + hp = { + 'x' : cX, + 'y' : cY, + 'contour' : contourList[i], + 'dist' : math.dist((cX, cY), (0, 0)), + 'order': -1 + } + if hp['dist'] < minDist : + minDist = hp['dist'] + topLeft = hp + holePunches.append(hp) count+=1 + +for hp in holePunches : + hp['dist'] = math.dist( (topLeft['x'], topLeft['y']), (hp['x'], hp['y']) ) + +holePunches = sorted(holePunches, key = lambda hp: hp['dist']) + +i = 0 +for hp in holePunches : + hp['order'] = i + cv2.putText(img, str(i + 1), (hp['x'], hp['y']), cv2.FONT_HERSHEY_SIMPLEX, 20, (0, 0, 255), 5, cv2.LINE_AA, False) + i+=1 + +verts = [] +horiz = [] + + +#across top +horiz.append(horiz_angle(draw_line(img, holePunches, 1, 3))) +#across bottom +horiz.append(horiz_angle(draw_line(img, holePunches, 4, 6))) +#middle +horiz.append(horiz_angle(draw_line(img, holePunches, 2, 5))) + +#top left +verts.append(verts_angle(draw_line(img, holePunches, 1, 2))) +#long left +verts.append(verts_angle(draw_line(img, holePunches, 1, 4))) + +#top right +verts.append(verts_angle(draw_line(img, holePunches, 3, 5))) +#long right +verts.append(verts_angle(draw_line(img, holePunches, 3, 6))) + +#bottom left +verts.append(verts_angle(draw_line(img, holePunches, 2, 4))) +#bottom right +verts.append(verts_angle(draw_line(img, holePunches, 5, 6))) + + +#for v in verts : + #print(v) + +#for h in horiz : +# print(h) +# horiz_angle(h) + print(f'Found hole punches within {areaRange}% of largest') +#print(holePunches) +#cv2.drawContours(img, list(map(lambda hp : hp['contour'], holePunches)), -1, (0, 255, 0), 20) +#cv2.circle(img, (topLeft['x'], topLeft['y']), 50, (0, 0, 255), -1) -cv2.drawContours(img, holePunches, -1, (0, 255, 0), 20) display(img)