Линия симметрии треугольника под углом - PullRequest
0 голосов
/ 30 октября 2019

Как лучше всего нарисовать линию симметрии треугольника (под углом) в Python 3.X с использованием OpenCV?

enter image description here

Я использовал Угловой Детектор Харриса, чтобы найти вершину треугольника:

image = cv2.imread('triangle.jpg')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
corners = cv2.cornerHarris(gray,2,5,0.04)
corners = cv2.dilate(corners,None)
image[corners>0.01*corners.max()]=[0,255,0]

1 Ответ

1 голос
/ 30 октября 2019

У меня была та же идея, что и в комментарии fmw42 , поэтому здесь приводится версия этой идеи. Я предполагаю, что на изображении присутствует только один (более или менее совершенный) равнобедренный треугольник .

Выполнены следующие шаги:

  1. Найдитекрайние внешние контуры на изображении, преобразованном в оттенках серого, см. cv2.findContours и RetrievalModes.
  2. Найдите вершины треугольника, используя cv2.minEnclosingTriangle.
  3. (Необязательно) Уточните найденные вершины, найдя ближайшие точки в исходном найденном контуре. См. Следующий пример кода, почему это может иметь значение.
  4. Рассчитать все длины ребер. «Верхняя» вершина - это та, которая имеет наименьшее количество уникальных длин ребер.
  5. Вычислите среднюю точку на основании и проведите линию от «верхней» вершины до этой точки.

Вот код:

import cv2
import numpy as np

# Some dummy image
img = cv2.fillPoly(img=np.zeros((500, 500, 3), np.uint8),
                   pts=np.array([[[200, 100], [400, 200], [300, 300]]]),
                   color=(0, 0, 255))

# Find only external contours in grayscale converted image
contours, _ = cv2.findContours(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# Find triangle vertices of minimum area enclosing contour
_, triangle = cv2.minEnclosingTriangle(contours[0])
pts = np.int32(np.squeeze(np.round(triangle)))
print('\nminEnclosingTriangle: \n', pts)

# Refine/improve triangle vertices (if wanted)
idx = [np.argmin(np.linalg.norm(contours[0] - pt, axis=2)) for pt in pts]
pts = np.int32(np.squeeze(contours[0][idx]))
print('\nRefined: \n', pts)

# Find index of "top" vertex by finding unique edge lengths; "top" has less than the two base vertices
idx = np.argmin([np.size(np.unique(np.linalg.norm(pts - pt, axis=1))) for pt in pts])
top = pts[idx]

# Find mid point of the base vertices
base = np.array([pts[i] for i in np.arange(3) if i != idx])
base_mid = np.int32(np.round(np.mean(base, axis=0)))

# Draw angle bisector line
img = cv2.line(img, tuple(top), tuple(base_mid) , (0, 255, 0), 2)

cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

И вот выходы для моего фиктивного примера:

minEnclosingTriangle: 
 [[199  99]
 [300 300]
 [400 200]]

Refined: 
 [[200 100]
 [300 300]
 [400 200]]

Output

Обратите внимание, что для неидеальных равнобедренных треугольников могут потребоваться некоторые модификации, например, вместо нахождения уникальных краевых длин, может потребоваться установить порог, чтобы краевые длины в пределах некоторого допуска также считались одинаковыми. Это может произойти довольно быстро, особенно если обнаружение контуров не является хорошим из-за - например, интерполированных пикселей от сжатия JPG.

В любом случае - надеюсь, это поможет!

Отказ от ответственности: В настоящее время яИграю со списком Python. Итак, извините, если здесь есть какое-то (неуместное) злоупотребление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...