2022-11-24 16:22:03 +00:00
|
|
|
import sys
|
|
|
|
import cv2
|
|
|
|
import numpy as np
|
|
|
|
import math
|
|
|
|
from os.path import exists, basename
|
|
|
|
from common import image_resize, display, normalize_angle
|
2022-11-25 00:41:01 +00:00
|
|
|
from json import load
|
2022-11-24 16:22:03 +00:00
|
|
|
|
|
|
|
#clockwise from top left
|
2022-11-25 00:41:01 +00:00
|
|
|
order = [ 0, 2, 3, 5, 4, 1 ]
|
|
|
|
matchMethods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
|
|
|
|
'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
|
2022-11-24 16:22:03 +00:00
|
|
|
|
|
|
|
def read_text (textPath) :
|
|
|
|
holePunches = {}
|
2022-11-25 00:41:01 +00:00
|
|
|
with open(textPath) as json:
|
|
|
|
holePunches = load(json)
|
2022-11-24 16:22:03 +00:00
|
|
|
return holePunches
|
|
|
|
|
|
|
|
#
|
|
|
|
# CALIBRATE
|
|
|
|
#
|
|
|
|
|
|
|
|
if len(sys.argv) < 2:
|
|
|
|
print('Please provide path of normalized scan to calibrate to')
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
if len(sys.argv) < 3:
|
|
|
|
print('Please provide path to output svg template')
|
|
|
|
exit(2)
|
|
|
|
|
|
|
|
normalImage = sys.argv[-2]
|
|
|
|
|
|
|
|
if not exists(normalImage) :
|
|
|
|
print('Normalized scan does not exist, please provide one that does')
|
|
|
|
exit(2)
|
|
|
|
|
2022-11-25 00:41:01 +00:00
|
|
|
normalText = normalImage + '.json'
|
2022-11-24 16:22:03 +00:00
|
|
|
|
|
|
|
if not exists(normalText) :
|
|
|
|
print('Corresponding normalized scan text does not exist, please generate one')
|
|
|
|
exit(3)
|
|
|
|
|
|
|
|
outputTmpl = sys.argv[-1]
|
|
|
|
|
|
|
|
print(f'Calibrating to scan {basename(normalImage)}')
|
|
|
|
|
2023-01-30 03:53:51 +00:00
|
|
|
registrationMark = cv2.imread('./registrationMark.png', 0)
|
2022-11-25 00:41:01 +00:00
|
|
|
w, h = registrationMark.shape[:2]
|
2022-11-24 16:22:03 +00:00
|
|
|
holePunches = read_text(normalText)
|
|
|
|
original = cv2.imread(normalImage)
|
|
|
|
img = original.copy()
|
|
|
|
height, width = img.shape[:2]
|
|
|
|
orientation = height > width
|
|
|
|
|
|
|
|
if not orientation :
|
|
|
|
print(f'Scan is not in portrait mode, exiting...')
|
|
|
|
exit(3)
|
|
|
|
|
2022-11-25 00:41:01 +00:00
|
|
|
print(holePunches)
|
|
|
|
|
2023-01-30 03:53:51 +00:00
|
|
|
def get_distance(ref, point):
|
|
|
|
# print('ref: {} , point: {}'.format(ref, point))
|
|
|
|
x1, y1 = ref[0], ref[1]
|
|
|
|
x2, y2 = point[0], point[1]
|
|
|
|
return math.hypot(x2 - x1, y2 - y1)
|
|
|
|
|
|
|
|
def group_points(points):
|
|
|
|
groups = {}
|
|
|
|
groupnum = 0
|
|
|
|
while len(points) > 1:
|
|
|
|
groupnum += 1
|
|
|
|
key = str(groupnum)
|
|
|
|
groups[key] = []
|
|
|
|
ref = points.pop(0)
|
|
|
|
for i, point in enumerate(points):
|
|
|
|
d = get_distance(ref, point)
|
|
|
|
if d < 30:
|
|
|
|
groups[key].append(points[i])
|
|
|
|
points[i] = None
|
|
|
|
points = list(filter(lambda x: x is not None, points))
|
|
|
|
# perform average operation on each group
|
|
|
|
return list([[int(np.mean(list([x[0] for x in groups[arr]]))), int(np.mean(list([x[1] for x in groups[arr]])))] for arr in groups])
|
|
|
|
|
|
|
|
def find_in_half (half) :
|
|
|
|
halfGray = cv2.cvtColor(half, cv2.COLOR_BGR2GRAY)
|
|
|
|
res = cv2.matchTemplate(halfGray, registrationMark, cv2.TM_CCOEFF_NORMED)
|
|
|
|
threshold = 0.7
|
|
|
|
loc = np.where( res >= threshold)
|
|
|
|
for pt in zip(*loc[::-1]):
|
|
|
|
cv2.rectangle(half, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
|
|
|
|
#display(half)
|
|
|
|
return list(zip(*loc[::-1]))
|
|
|
|
|
|
|
|
topHalf = img[holePunches['0']['y']-round(height*0.05):holePunches['1']['y']+round(height*0.1), holePunches['0']['x']:holePunches['2']['x']]
|
|
|
|
topHalfPts = find_in_half(topHalf)
|
|
|
|
thpts = group_points(topHalfPts)
|
|
|
|
for pt in thpts :
|
2022-11-25 00:41:01 +00:00
|
|
|
print(f'{pt[0]},{pt[1]}')
|
|
|
|
|
2023-01-30 03:53:51 +00:00
|
|
|
bottomHalf = img[holePunches['4']['y']-round(height*0.1):holePunches['5']['y']+round(height*0.05), holePunches['3']['x']:holePunches['4']['x']]
|
|
|
|
bottomHalfPts = find_in_half(bottomHalf)
|
|
|
|
bhpts = group_points(bottomHalfPts)
|
|
|
|
for pt in bhpts :
|
|
|
|
print(f'{pt[0]},{pt[1]}')
|
|
|
|
display(bottomHalf)
|
|
|
|
|