Python/OpenCV - 使用两种不同的Hough线方法检测网球场中的线 - 得到不同的结果
我正在尝试使用openCV和霍夫变换来检测网球场上的线条。我想找到水平和垂直的线条,以便找到交点,最终检测出网球场的角落。
这是原始图像。

但是我遇到了一些问题。
1) 我尝试使用HoughLineP。这里是代码:
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,100,200,apertureSize = 3)
lines = cv2.HoughLinesP(edges, 1, np.pi/2, 6, None, 50, 10);
for line in lines[0]:
pt1 = (line[0],line[1])
pt2 = (line[2],line[3])
cv2.line(img, pt1, pt2, (0,0,255), 2)
cv2.imshow('dst',img)
return res
这是结果:
HoughLineP的结果2) 我尝试使用HoughLines。这里是代码:
gray=cv2.cvtColor(res,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,100,200,apertureSize = 3)
#Lignes
lines = cv2.HoughLines(edges,1,np.pi/70,110)
for rho,theta in lines[0]:
if (np.pi/70 <= theta <= np.pi/7) or (2.056 < theta < 4.970) or (1.570 <= theta <= 1.600): #(2,6 <=theta <= 26) or (theta >118 and theta <= 285)
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv2.line(res,(x1,y1),(x2,y2),(0,0,255),1)
这是结果:
HoughLine的结果在第一种情况下,我只得到了很少的线条,我考虑过延长它们,但没有找到合适的方法……我尝试使用fitLine,但它只适用于找轮廓(findContours方法在这个图像上效果很差)。
在第二种情况下,效果不错,但我得到了很多几乎相同的线条,而在右下角,我没有任何交点来检测角落……
也许我走错了方向……
你们有什么想法或者可以尝试的东西吗?最后,我只想关注与网球场相关的兴趣点。
附注:我做了一个方法来计算水平线和垂直线之间的交点。

非常感谢,
1 个回答
看起来HougLines的输出包含了你想要的线条。你只需要把那些异常值过滤掉。
为此,你可以使用一个网球场的模型。你知道的事情包括:
- 场地的外边界,用一个大矩形表示
- 两个通道,用两条线表示,这两条线切割矩形的两侧
- 发球区,用两条线表示,每个发球区都有一条平行于发球线的线和一条平行于场地边界的线
你可以尝试利用你已有的模型来过滤掉异常值。有些方法,比如RANSAC,就是为此而设计的。基本思路是随机选择一些点,计算模型,然后检查这些点是否符合数据。经过几次迭代,最合适的模型很可能就是你要找的。这是一种比较常见的方法(最早由Fischler在1986年发布),所以你可以找到很多相关的资料。下面是一个简单的算法示例,可能适合你(可能需要一些调整):
在交点中随机选择4个点。计算透视投影P,将这些点映射到场地的俯视图。你可以使用OpenCV的getPerspectiveTransform来实现。现在你就有了场地的模型,俯视图。
因为你有了场地的模型(基于网球的规则),你可以确定其他线条的交点(比如发球线与通道线、发球区等)在俯视图中的位置。如果你对这些点应用透视变换的逆变换P^{-1},就可以将它们转换到图像空间。
检查一致性:在图像空间中寻找与模型中线条交点最接近的交点。这里你需要一个指标:在距离小于x像素的情况下,线条交点的数量,或者SSD(平方和差)。你将使用这个指标来评估不同的模型。
评估你的模型:如果你定义的指标小于之前找到的最佳模型,那么这个就是你当前的最佳模型。
迭代。你进行的迭代次数与最终选择到一个好模型的概率直接相关。可以参考Fischler和Bolls的开创性工作,了解如何设置迭代次数。
到最后,经过多次迭代,你将找到一个最符合你数据的模型,也就是描述网球场的内点和不符合的外点。请注意,这种方法对大量异常值(超过50%)是比较稳健的,但得到好结果的机会只是统计上的(不过你可以通过调整迭代次数来设定结果的预期质量)。
希望这对你有帮助,
Ben