Almost blew past a good stopping point.

This script can now, on at least one example. locate the largest contours on the page and then put those contours in an array.
It should also look for the largest, most outlying, to prevent errors in the case of large contours in the image.
They should never go past the holes.

Next step: use this for straightening, which will be good for the image extraction script.
Use them as registration points and then just rotate, shift and "shoot" by cropping at a point relative to the holes.

For calibration/templating, look into pattern matching fiducials after getting hole punch coordinates.
This commit is contained in:
Matt McWilliams 2022-11-08 22:47:36 -05:00
parent e5d9d654ac
commit f103133b9f
1 changed files with 91 additions and 1 deletions

View File

@ -2,6 +2,34 @@ import sys
import cv2
import numpy as np
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)
if len(sys.argv) < 2:
print('Please provide path to image for analysis')
exit(1)
@ -15,4 +43,66 @@ templateFile = sys.argv[-1]
print(f'Analyzing {scanImage} and creating {templateFile}')
#https://stackoverflow.com/questions/51456660/opencv-detecting-drilled-holes
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
centers.appendStr(strC)
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)