У меня есть код, который сравнивает две геометрические фигуры. Я установил порог сравнения 0,1 (вы увидите его ниже в коде), и в принципе результаты более-менее хорошие.
Но бывают случаи, когда встречаются вполне похожие фигуры (но с разными координатами x и y). Например
То есть в принципе фигуры похожи, но что касается координат на листе, то фигуры расположены немного по-другому.
def compare_two_figure(template, figure_for_compare):
template = cv.imread(template, cv.IMREAD_GRAYSCALE)
figure_for_compare = cv.imread(figure_for_compare, cv.IMREAD_GRAYSCALE)
_, thresh_template = cv.threshold(template, 127, 255, 0)
_, thresh_figure_for_compare = cv.threshold(figure_for_compare, 127, 255, 0)
contours_template, _ = cv.findContours(thresh_template, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
particular_contour_template = contours_template[1]
contours_figure_for_compare, _ = cv.findContours(thresh_figure_for_compare, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
particular_contour_figure_for_compare = contours_figure_for_compare[1]
differences = cv.matchShapes(particular_contour_template, particular_contour_figure_for_compare, 1, 0.0)
print(differences)
if differences < 0.1:
return "same"
else:
return "different"
print(compare_two_figure('files/template_14_v2.jpg', 'searching_figure_14.jpg'))
В приведенном выше примере различия = 7,842170693643041.
Как вы понимаете, хотелось бы, чтобы в таких случаях результат был таким, чтобы цифры были идентичными (или почти идентичными). Подскажите, как это можно реализовать?
@Aemyl да, это то же самое. Спасибо
контекст: stackoverflow.com/questions/78705469/…
Формы могут выглядеть одинаково, но одна короче по вертикали. Это тоже не будет соответствовать.
см. документацию https://docs.opencv.org/4.x/d5/d45/tutorial_py_contours_more_functions.html
findContours
и matchShapes
ожидают белый (255) внутри и черный (0) снаружи.
Я преобразовал ваши изображения, используя этот код:
def fill_polygons(template, figure_for_compare):
template = cv.imread(template, cv.IMREAD_GRAYSCALE)
template = 255 - template
figure_for_compare = cv.imread(figure_for_compare, cv.IMREAD_GRAYSCALE)
figure_for_compare = 255 - figure_for_compare
_, thresh_template = cv.threshold(template, 127, 255, 0)
_, thresh_figure_for_compare = cv.threshold(figure_for_compare, 127, 255, 0)
contours_template, _ = cv.findContours(thresh_template, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
particular_contour_template = contours_template[1]
cv.fillPoly(thresh_template, pts=[particular_contour_template], color=(255, 255, 255))
cv.imwrite("/tmp/1a.png", thresh_template)
contours_figure_for_compare, _ = cv.findContours(thresh_figure_for_compare, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
particular_contour_figure_for_compare = contours_figure_for_compare[1]
cv.fillPoly(thresh_figure_for_compare, pts=[particular_contour_figure_for_compare], color=(255, 255, 255))
cv.imwrite("/tmp/2a.png", thresh_figure_for_compare)
fill_polygons('files/template_14_v2.jpg', 'searching_figure_14.jpg')
и с вашей функцией я получаю разницу ~ = 0,45
(Я думаю, что две фигуры, которые у вас есть, не одинаковы, я имею в виду, что вы не просто переместили первую, чтобы получить вторую)
Большое спасибо за внимание к моему вопросу и за решение. Да, я видел эту ссылку, но видимо не внимательно прочитал. Я хотел бы уточнить один момент: ваша функция fill_polygons работает и возвращает два файла 1a.png и 2a.png, а затем я должен передать эти два файла в качестве аргументов в мою функцию Compare_two_figure? Я прав?
Да, ты прав
Не могли бы вы провести рефакторинг своего кода, так как вы дважды определяете переменные contexts_template и unique_contour_template, а после второго определения переменная unique_contour_template нигде не используется. Это немного сбивает с толку.
Готово, удалены лишние строки
Спасибо за помощь. В этом случае ваше решение идеально, но мне кажется, что мне следует поискать другой подход для определения сходства.
Более простой ответ:
изменения в рассматриваемом коде:
Инвертируйте изображения im = 255 - im
Используйте cv.RETR_LIST
вместо cv.RETR_TREE
def compare_two_figure(template, figure_for_compare):
template = cv.imread(template, cv.IMREAD_GRAYSCALE)
template = 255 - template
figure_for_compare = cv.imread(figure_for_compare, cv.IMREAD_GRAYSCALE)
figure_for_compare = 255 - figure_for_compare
_, thresh_template = cv.threshold(template, 127, 255, 0)
_, thresh_figure_for_compare = cv.threshold(figure_for_compare, 127, 255, 0)
contours_template, _ = cv.findContours(thresh_template, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)
particular_contour_template = contours_template[1]
contours_figure_for_compare, _ = cv.findContours(thresh_figure_for_compare, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)
particular_contour_figure_for_compare = contours_figure_for_compare[1]
differences = cv.matchShapes(particular_contour_template, particular_contour_figure_for_compare, 1, 0.0)
print(differences)
if differences < 0.1:
return "same"
else:
return "different"
Я получаю разницу ~= 0,45
вы определяете функцию с именем
compare_two_figure
, но вместо этого вызываетеcompare_two_documents
. Должны ли эти функции быть одинаковыми?