如何用两点画一条线,然后用opencv,python画线直到到达轮廓点?

How to draw a line from two points and then let the line complete drawing until reaching a contour point with opencv, python?

我正在使用opencv和python进行编程,并且尝试在知道其坐标的两个点之间绘制一条线,然后完成该线直到其到达轮廓的尽头,如下图所示。 在我的情况下,轮廓实际上是像脸,但是我在这里提供了一个圆圈用于说明。 因此,我试图实现的目标是使头部的边缘与直线和轮廓线相交。 有没有办法从两个点画一条线,然后让线完成绘图直到到达轮廓?
enter image description here


我可以想到一种简单的方法,它不涉及增量更新图像:在一个空白图像上,绘制一条从第一点向第二点方向延伸的长线,然后将得到的图像与绘制(填充)的单个轮廓的图像。这将使线条停在轮廓的末端。然后,您可以使用该蒙版绘制线条,或者如果需要线条的坐标,则获得最小/最大x,y坐标。

为了遍历一个示例,首先我们将找到轮廓并将其绘制在空白图像上:

1
2
3
contours = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[1]
contour_img = np.zeros_like(img)
cv2.fillPoly(contour_img, contours, 255)

然后,如果我们有点p1p2,请找到它们的前进方向,并在该距离内找到一个较远的点,然后在新的空白图像上绘制该线(这里我使用的距离为1000像素来自p1):

1
2
3
4
5
6
7
8
9
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()

1
contour_line_img = cv2.bitwise_and(line_img, contour_img)

这是一张图像,显示了这些点,延伸经过轮廓的线以及在轮廓处断开的线。

Line breaking at contour

编辑:请注意,这仅在轮廓为凸形时才有效。如果有任何凹陷,并且线穿过该凹入部分,它将继续在其另一侧上绘制。例如在Silencer的答案中,如果两个点都在一只耳朵的内部并且指向另一只耳朵,则您希望轮廓在碰到边缘时停止,但是我的耳朵会继续在另一只耳朵上绘制。我认为像Silencer's这样的迭代方法最适合一般情况,但如果您知道轮廓凸或如果要放置的点不存在此问题,则我喜欢这种方法的简单性。

Edit2:堆栈上的其他人通过创建一个来回答关于Python中的Line Iterator类的问题:openCV 3.0 python LineIterator