根据提供的信息和示例图片,我将如何解决此问题:
先决条件
由于红色标记是由HoughLinesP 创建的行,因此您在每一行上都有以下信息:(x1, y1, x2, y2) 其中 (x1, y1) 是起点和 (x2, y2) 线的终点。
出于测试目的,我创建了 3 行:
管道
- 创建一个点列表(在我的代码中为
contour),其中包含每条线的开始和结束点。
- 使用
convexHull 计算点列表的凸包。
此时你会得到这种味道的东西:
请注意,生成的船体(绿色)确实包含超过 4 个点(即,不仅是极端点)。所以我们接下来要做的是简化船体,以便只保留 4 个极值点。
-
简化船体
approxPolyDP
- 船体的其余 4 个点应该是 极端点的近似值。
在这里您可以看到最终结果,绿色为近似船体,黄色为 4 个极值点:
Python 代码
最后,作为参考,这是我使用的 Python 代码(这应该不难移植到 Java 中):
import numpy as np
import cv2
input_img = np.zeros((400,400,3), np.uint8)
# 3 lines added for testing purpose
lines = []
lines.append(((350,350),(250,200))) # (start point, end point)
lines.append(((50,350),(55,330)))
lines.append(((60,250),(80,200)))
contour = [] #in Java you'd use a List of Points
for line in lines:
# we create a contour with the start and end points of each line
contour.append(line[0])
contour.append(line[1])
# we draw the lines (in your case, detected by HoughLinesP)
cv2.line(input_img,line[0],line[1],(0,0,255),3)
contour = np.array(contour)
hull = cv2.convexHull(contour) # we compute the convex hull of our contour
epsilon = 0.05*cv2.arcLength(hull,True) # epsilon may need to be tweaked
approx_hull = cv2.approxPolyDP(hull,epsilon,True)
# we check that there are only 4 points left in the approximate hull (if there are more, then you'd need to increase epsilon
if(len(approx_hull) == 4):
for final_point in approx_hull :
# we draw the 4 points contained in the approximate hull
cv2.circle(input_img, (final_point[0][0], final_point[0][1]),5,(0,242,255),2)
cv2.drawContours(input_img, [approx_hull], 0, (0,255,0),1)
cv2.imshow("result",input_img)
另类
我认为来自@YvesDaoust 的solution 也可以。我没有时间测试它,所以请如果你这样做,请让我更新。 :)