2022-11-09 00:11:15 +00:00
|
|
|
import sys
|
|
|
|
import cv2
|
|
|
|
import numpy as np
|
|
|
|
|
2022-11-09 03:47:36 +00:00
|
|
|
def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
|
|
|
|
dim = None
|
|
|
|
(h, w) = image.shape[:2]
|
|
|
|
|
|
|
|
if width is None and height is None:
|
|
|
|
return image
|
|
|
|
|
|
|
|
if width is None:
|
|
|
|
r = height / float(h)
|
|
|
|
dim = (int(w * r), height)
|
|
|
|
else:
|
|
|
|
r = width / float(w)
|
|
|
|
dim = (width, int(h * r))
|
|
|
|
resized = cv2.resize(image, dim, interpolation = inter)
|
|
|
|
|
|
|
|
return resized
|
|
|
|
|
|
|
|
def display (image) :
|
|
|
|
resized = image_resize(image, 800, 800)
|
|
|
|
cv2.imshow('img', resized)
|
|
|
|
|
|
|
|
while True:
|
|
|
|
key = cv2.waitKey(0)
|
|
|
|
if key == 27:
|
|
|
|
cv2.destroyAllWindows()
|
|
|
|
break
|
|
|
|
exit(0)
|
|
|
|
|
2022-11-09 00:11:15 +00:00
|
|
|
if len(sys.argv) < 2:
|
|
|
|
print('Please provide path to image for analysis')
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
if len(sys.argv) < 3:
|
|
|
|
print('Please provide path to template file to create')
|
|
|
|
exit(2)
|
|
|
|
|
|
|
|
scanImage = sys.argv[-2]
|
|
|
|
templateFile = sys.argv[-1]
|
|
|
|
|
|
|
|
print(f'Analyzing {scanImage} and creating {templateFile}')
|
|
|
|
|
2022-11-09 03:47:36 +00:00
|
|
|
img = cv2.imread(scanImage)
|
|
|
|
|
|
|
|
height, width = img.shape[:2]
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
contour_list = []
|
|
|
|
area_list = []
|
|
|
|
for contour in contours:
|
|
|
|
approx = cv2.approxPolyDP(contour, 0.01 * cv2.arcLength(contour, True), True)
|
|
|
|
area = cv2.contourArea(contour)
|
|
|
|
area_list.append(area)
|
|
|
|
contour_list.append(contour)
|
|
|
|
|
|
|
|
maxArea=0
|
|
|
|
maxIndex=0
|
|
|
|
|
|
|
|
for i in range(len(area_list)) :
|
|
|
|
area = area_list[i]
|
|
|
|
if area > maxArea:
|
|
|
|
maxArea = area
|
|
|
|
maxIndex = i
|
|
|
|
|
|
|
|
count = 0
|
|
|
|
hole_punches = []
|
|
|
|
centers = []
|
|
|
|
centersStr = []
|
|
|
|
area_range = 0
|
|
|
|
|
|
|
|
# pretty good
|
|
|
|
# add position constraint
|
|
|
|
|
|
|
|
while count < 6 :
|
|
|
|
area_range+=1
|
|
|
|
for i in range(len(area_list)) :
|
|
|
|
area = area_list[i]
|
|
|
|
if area == maxArea or area * ((100 + area_range) / 100) > maxArea :
|
|
|
|
M = cv2.moments(contour_list[i])
|
|
|
|
cX = int(M["m10"] / M["m00"])
|
|
|
|
cY = int(M["m01"] / M["m00"])
|
|
|
|
strC = f'{cX},{cY}'
|
|
|
|
if strC in centersStr :
|
|
|
|
continue
|
2022-11-09 14:45:07 +00:00
|
|
|
centersStr.append(strC)
|
2022-11-09 03:47:36 +00:00
|
|
|
corners.append((cX, cY))
|
|
|
|
print(f'{cX},{cY}')
|
|
|
|
cv2.circle(img, (cX, cY), 40, (255, 0, 0), -1)
|
|
|
|
hole_punches.append(contour_list[i])
|
|
|
|
count+=1
|
|
|
|
print(f'Found hole punches within {area_range}% of largest')
|
|
|
|
|
|
|
|
|
|
|
|
cv2.drawContours(img, hole_punches, -1, (0, 255, 0), 20)
|
|
|
|
display(img)
|
|
|
|
|