Как нарисовать линию из двух точек, а затем позволить линии завершить рисование до достижения точки контура с помощью opencv, python?
Я использую opencv и python для программирования, и я пытаюсь нарисовать линию между двумя точками, которые я знаю их координаты, и затем позволить линии завершиться, пока не достигнет конца контура, как показано на рисунке ниже. Контур в моем случае на самом деле изображает лицо, но я привел круг для объяснения. Поэтому я пытаюсь добиться того, чтобы край головы в этой точке пересекался с линией и контуром. Есть ли способ нарисовать линию из двух точек, а затем позволить линии завершить рисование до достижения контура?
1 ответ
Я могу подумать об одном простом методе, который не требует постепенного обновления изображения: на одном пустом изображении нарисуйте длинную линию, продолжающуюся от точки один в направлении точки два, а затем И полученное изображение с изображение одиночного контура нарисовано (заполнено). Это остановит линию в конце контура. Затем вы можете использовать эту маску для рисования линии или получить минимальные / максимальные координаты x, y, если вам нужны координаты линии.
Чтобы пройти пример, сначала мы найдем контур и нарисуем его на чистом изображении:
contours = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[1]
contour_img = np.zeros_like(img)
cv2.fillPoly(contour_img, contours, 255)
Тогда, если у нас есть очки p1
а также p2
найдите направление, в котором они движутся, найдите точку на этом расстоянии и нарисуйте эту линию на новом пустом изображении (здесь я использовал расстояние в 1000 пикселей от p1
):
p1 = (250, 250)
p2 = (235, 210)
theta = np.arctan2(p1[1]-p2[1], p1[0]-p2[0])
endpt_x = int(p1[0] - 1000*np.cos(theta))
endpt_y = int(p1[1] - 1000*np.sin(theta))
line_img = np.zeros_like(img)
cv2.line(line_img, (p1[0], p1[1]), (endpt_x, endpt_y), 255, 2)
Тогда просто cv2.bitwise_and()
два изображения вместе
contour_line_img = cv2.bitwise_and(line_img, contour_img)
Вот изображение, показывающее точки, линию, проходящую за контур, и линию, обрывающуюся на контуре.
Изменить: Обратите внимание, что это будет работать только в том случае, если ваши контуры выпуклые. Если есть какая-либо вогнутость, и линия проходит через эту вогнутую часть, она будет продолжать рисовать с другой стороны. Например, в ответе Глушителя, если обе точки были внутри одного уха и направлены к другому уху, вы бы хотели, чтобы контур остановился, как только он достигнет края, но мой будет продолжать рисовать на другом ухе. Я думаю, что итеративный метод, такой как глушитель, лучше всего подходит для общего случая, но мне нравится простота этого метода, если вы знаете, что у вас выпуклые контуры или если ваши точки будут в месте, где эта проблема не возникнет.
Edit2: кто-то еще в Stack ответил на свой собственный вопрос о классе Line Iterator в Python, создав его: openCV 3.0 python LineIterator