11. 霍夫线检测

本文深入探讨了霍夫变换原理,它是检测图像中直线的一种有效方法,尤其在形状存在畸变时。霍夫变换在OpenCV中通过`cv.HoughLines()`函数实现,接受二值图像、ρ和θ精度、阈值作为参数。概率霍夫变换(HoughLinesP())则更为高效,仅处理部分点并直接返回线段端点。通过调整参数,可以优化检测效果。
摘要由CSDN通过智能技术生成

原理

霍夫变换是一种流行的检测任何形状的技术,前提是您可以用数学形式表示该形状。即使它被破坏或扭曲一点,它也可以检测到形状。我们将看到它对一条线是如何工作的。
一条直线可以表示为 y=mx+c 或以参数形式表示,如 ρ=xcosθ+ysinθ 其中 ρ 是原点到直线的垂直距离,θ 是这条垂直线与水平轴形成的夹角以逆时针方向测量(该方向因您表示坐标系的方式而异。OpenCV 中使用此表示)。参考下面的图像:
在这里插入图片描述
所以如果线在原点以下通过,它会有一个正的 rho 并且角度小于 180。如果它在原点之上,而不是取大于 180 的角度,而是取小于 180 的角度,并且 rho被取为负。任何垂直线将具有 0 度,水平线将具有 90 度。

变换步骤参考Hough transform

1. OpenCV 中的霍夫变换

上面解释的所有内容都封装在 OpenCV 函数 cv.HoughLines()中。它只是返回一组 :math:(rho, theta) 值。 ρ 以像素为单位,θ 以弧度为单位。第一个参数,输入图像应该是一个二值图像,所以在应用霍夫变换之前应用阈值或使用Canny边缘检测。第二个和第三个参数分别是 ρ 和 θ 精度。第四个参数是阈值,这意味着它应该被视为一条线的最低投票数。请记住,投票数取决于线上的点数。所以它代表了应该检测的最小线长。

img = cv.imread("../../file/photos/sudoku.jpg")
img_c = img.copy()
gray = cv.cvtColor(img_c, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 50, 150, 3)  # 进行边缘检测

lines = cv.HoughLines(edges, 1, np.pi / 180, 150)
# 取出每条线单元
for line in lines:
    rho, theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)

    x0 = a * rho
    y0 = b * rho
    x1 = int(x0 + 1000 * (-b))  # 延伸长该线段的x坐标
    y1 = int(y0 + 1000 * a)  # 延伸该线段的y坐标
    x2 = int(x0 - 1000 * (-b))
    y2 = int(y0 - 1000 * a)
	# 两点确定一条直线,画出检测到的直线
    cv.line(img_c, (x1, y1), (x2, y2), (255, 0, 0), thickness=2)

plt.imshow(img_c, )
plt.axis("off")
plt.show()

结果如下:

在这里插入图片描述

2. OpenCV中的概率霍夫变换

在霍夫变换中,您可以看到,即使对于具有两个参数的行,也需要进行大量计算。概率霍夫变换是我们看到的霍夫变换的优化。它没有考虑所有的点。相反,它只需要一个足以进行线检测的随机点子集。我们只需要降低阈值。请参见下图,它比较了霍夫空间中的霍夫变换和概率霍夫变换。 (图片提供:Franck Bettinger 的主页)
在这里插入图片描述
OpenCV 实现基于 Matas, J. 和 Galambos, C. 和 Kittler, J.V. 使用渐进式概率霍夫变换对线条进行鲁棒检测 。使用的函数是 cv.HoughLinesP()。它有两个新参数。

  • minLineLength - 线的最小长度。比这短的线段被拒绝。
  • maxLineGap - 线段之间的最大允许间隙,将它们视为一条线。

最重要的是,它直接返回直线的两个端点。在以前的情况下,你只能得到线的参数,而且你必须找到所有的点。在这里,一切都很直接和简单。

img = cv.imread(cv.samples.findFile('sudoku.png'))
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 100, 150, apertureSize=3)
lines = cv.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength=50, maxLineGap=20)

for line in lines:
    x1, y1, x2, y2 = line[0]  #得到的每条线的四个点
    cv.line(img, (x1, y1), (x2, y2), (0, 255, 0), thickness=2)
img = cv.cvtColor(img, cv.COLOR_BGRA2RGB) 
plt.subplot(121), plt.imshow(gray, cmap='gray'), plt.title("Input image")
plt.axis("off")
plt.subplot(122), plt.imshow(img), plt.title("houghliens image")
plt.axis("off")

plt.show()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值