Вот один из способов использования сопоставления форм в Python / OpenCV.
- Считывание двух входных изображений и вычисление их центров
- Обрезка обоих изображений до некоторого общего размера относительно их центров
- Преобразовать их в серый
- Do Otsu thresholding
- Применить морфологическое разрушение к рисованной фигуре, чтобы сделать линии примерно такими же толстыми, как и в изображении, созданном компьютером
- Выполните сопоставление формы и получите 3 различных метрических c расстояния.
Компьютерная фигура:
![enter image description here](https://i.stack.imgur.com/kN3g5.jpg)
Нарисовано от руки рисунок:
![enter image description here](https://i.stack.imgur.com/B6NBb.jpg)
import cv2
import numpy as np
# read computer generated figure and find center
img1 = cv2.imread('computer_figure.jpg')
hh1, ww1 = img1.shape[:2]
cx1 = ww1 // 2
cy1 = hh1 // 2
# read hand drawn figure and find center
img2 = cv2.imread('drawn_figure.jpg')
hh2, ww2 = img2.shape[:2]
cx2 = ww2 // 2
cy2 = hh2 // 2
# specify crop size and crop both images
wd = 1450
ht = 1450
xoff = wd // 2
yoff = ht // 2
img1_crop = img1[cy1-yoff:cy1+yoff, cx1-xoff:cx1+xoff]
img2_crop = img2[cy2-yoff:cy2+yoff, cx2-xoff:cx2+xoff]
# convert to grayscale
gray1 = cv2.cvtColor(img1_crop,cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2_crop,cv2.COLOR_BGR2GRAY)
# threshold
thresh1 = cv2.threshold(gray1, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
thresh2 = cv2.threshold(gray2, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
# erode thresh2 to get black lines approx as thick as thresh1
# apply close and open morphology to fill tiny black and white holes and save as mask
kernel = np.ones((13,13), np.uint8)
thresh2 = cv2.morphologyEx(thresh2, cv2.MORPH_ERODE, kernel)
# do shape matching (the smaller the distance the better the match)
distance1 = cv2.matchShapes(thresh1, thresh2, cv2.CONTOURS_MATCH_I1, 0)
distance2 = cv2.matchShapes(thresh1, thresh2, cv2.CONTOURS_MATCH_I2, 0)
distance3 = cv2.matchShapes(thresh1, thresh2, cv2.CONTOURS_MATCH_I3, 0)
print("distance 1:",distance1)
print("distance 2:",distance2)
print("distance 3:",distance3)
print("")
#distance 1: 0.00019690372821457025
#distance 2: 0.001971857215556483
#distance 3: 0.0006233041352955213
# compare to mis-match with pure white image
thresh3 = np.full_like(thresh1, 255)
distance1 = cv2.matchShapes(thresh3, thresh2, cv2.CONTOURS_MATCH_I1, 0)
distance2 = cv2.matchShapes(thresh3, thresh2, cv2.CONTOURS_MATCH_I2, 0)
distance3 = cv2.matchShapes(thresh3, thresh2, cv2.CONTOURS_MATCH_I3, 0)
print("distance 1:",distance1)
print("distance 2:",distance2)
print("distance 3:",distance3)
print("")
#distance 1: 0.0019009881608588741
#distance 2: 0.019164295934527953
#distance 3: 0.006017629998960382
# compare to total mis-match of pure white image with pure black image
thresh4 = np.zeros_like(thresh1)
distance1 = cv2.matchShapes(thresh3, thresh4, cv2.CONTOURS_MATCH_I1, 0)
distance2 = cv2.matchShapes(thresh3, thresh4, cv2.CONTOURS_MATCH_I2, 0)
distance3 = cv2.matchShapes(thresh3, thresh4, cv2.CONTOURS_MATCH_I3, 0)
print("distance 1:",distance1)
print("distance 2:",distance2)
print("distance 3:",distance3)
print("")
#distance 1: 1.7976931348623157e+308
#distance 2: 1.7976931348623157e+308
#distance 3: 1.7976931348623157e+308
# save cropped image
cv2.imwrite('drawn_figure_thresh.jpg',thresh1)
cv2.imwrite('computer_figure_thresh.jpg',thresh2)
# show the images
cv2.imshow("crop1", img1_crop)
cv2.imshow("crop2", img2_crop)
cv2.imshow("thresh1", thresh1)
cv2.imshow("thresh2", thresh2)
cv2.waitKey(0)
cv2.destroyAllWindows()
Рисунок с пороговым значением на компьютере:
![enter image description here](https://i.stack.imgur.com/hcQ3c.jpg)
Рисованные с пороговым и эродированным рисунком:
![enter image description here](https://i.stack.imgur.com/iK4iK.jpg)
Полученные результаты перечислены в коде выше
Метрики расстояний см. https://www.learnopencv.com/shape-matching-using-hu-moments-c-python/