如何使用OpenCV和HoughLines在图像中检测垂直和水平线?(Python)

27

我正在尝试获取校准棋盘的阈值。由于观察到微型棋盘存在一些灰尘,无法直接检测棋盘角落。我尝试了几种方法,HoughLinesP似乎是最简单的方法。但结果不太好,如何改善我的结果?

import numpy as np
import cv2

img = cv2.imread('lines.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
print img.shape[1]
print img.shape
minLineLength=100
lines = cv2.HoughLinesP(image=edges,rho=0.02,theta=np.pi/500, threshold=10,lines=np.array([]), minLineLength=minLineLength,maxLineGap=100)

a,b,c = lines.shape
for i in range(a):
    cv2.line(img, (lines[i][0][0], lines[i][0][1]), (lines[i][0][2], lines[i][0][3]), (0, 0, 255), 3, cv2.LINE_AA)
    cv2.imwrite('houghlines5.jpg',img)

如下图所示,我无法获得我的棋盘,线条在很多方向上被绘制...(原始图片:https://s22.postimg.org/iq2b91xq9/droite_Image_00000.jpg

输入图像描述


使用阈值处理,或尝试减少小点(腐蚀、膨胀)。 - linusg
我已经尝试过,但没有与霍夫线相耦合。也许这可以帮助获取线条?谢谢你的帮助 ;) - user3601754
我真的想再尝试一下阈值处理! - linusg
我尝试使用中值滤波器去除噪音,但效果不够好,或者尝试对正方形进行标记以隔离它。但结果并不是很好,即重投影误差有时很大(RMS > 1)。 - user3601754
如果您不需要实现自己的解决方案,可以尝试使用已经实现的方法http://docs.opencv.org/2.4/doc/tutorials/calib3d/camera_calibration_square_chess/camera_calibration_square_chess.html - GpG
显示剩余4条评论
3个回答

58

您使用的rho值过小。

尝试以下代码:

import numpy as np
import cv2

gray = cv2.imread('lines.jpg')
edges = cv2.Canny(gray,50,150,apertureSize = 3)
cv2.imwrite('edges-50-150.jpg',edges)
minLineLength=100
lines = cv2.HoughLinesP(image=edges,rho=1,theta=np.pi/180, threshold=100,lines=np.array([]), minLineLength=minLineLength,maxLineGap=80)

a,b,c = lines.shape
for i in range(a):
    cv2.line(gray, (lines[i][0][0], lines[i][0][1]), (lines[i][0][2], lines[i][0][3]), (0, 0, 255), 3, cv2.LINE_AA)
    cv2.imwrite('houghlines5.jpg',gray)

注意,更改rho值、pi值和maxLineGap值以减少异常值。

输入图像 Input Image

边缘图像 Edges Image

输出图像 Output Image

杂项 - 初学者提示

  1. 许多计算机视觉算法假定输入数据符合某些特定的假设。在构建概念验证时,请始终尝试查看应用此类算法之前生成的中间输入。

  2. 为了快速测试,如果算法接受一些参数,请对这些参数的可能值使用for循环并观察结果如何变化。 链接 是有关如何快速生成这些可能值的答案。

  3. 要真正理解算法,请阅读维基百科或更好的来源。然后再进行上述测试(步骤2)。它将进一步澄清您的理解。


如何保存没有红线的图像?我想要完全没有线条的图像。谢谢。 - lucians
2
@Link - 我不确定你所说的没有线条的图像是什么意思。如果您只需要输出原始图像,请在绘制霍夫线之前使用cv2.imwrite('imagename.jpg',gray),即在运行cv2.line命令之前,并在循环外使用imwrite - saurabheights
1
如何获取每个框的轮廓?这意味着我想检测图像中的框并获取它们的坐标。 - Parikshit Chalke
@ParikshitChalke 有很多方法可以做到这一点,但最简单的方法是使用这些边缘的信息并尝试将棋盘边缘(8x8个方格)拟合到输入图像上。通过拟合,我指的是使用一些损失,例如SSD。此外,请针对不同的问题发布一个新问题。 - saurabheights

2
我更愿意将这个写成评论,但不幸的是我不能。你应该改变minLineLength和minLineGap。或者如果你只需要找到正方形,可以获取所有线条并检查它们之间的角度,以获得仅沿着正方形的线条。我以前使用过HoughLineP,它基本上是基于上述两个参数的。此外,尝试使用双边滤波器。当使用中值滤波器进行锐化时无法帮助时,它确实有帮助。

双边滤波器


1
在图像处理中,您需要经过一些步骤,例如在进行边缘检测之前必须经过滤波器。在您的情况下,灰尘只是需要通过滤波器去除的噪声。使用高斯或模糊滤波器,然后使用阈值处理,最后使用Canny算法进行边缘检测。在OpenCV中还有角点检测工具可供使用,或者您可以在阈值处理后直接使用关键点提取。请按照这些步骤操作并查看结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接