[图像处理]-霍夫变换原理及python实现线段检测

1.问题简介

霍夫变换常用来在图像中提取直线和圆等几何形状,如下图所示:
在这里插入图片描述
在这里我使用霍夫变换主要是想来提取图像中的直线.

2.基本原理

一条直线可由两个点A=(X1,Y1)和B=(X2,Y2)确定(笛卡尔坐标)
在这里插入图片描述
另一方面 y=kx+q也可以写成关于(k,q)的函数表达式(霍夫空间):
在这里插入图片描述
对应的变换可以通过图形直观表示:
在这里插入图片描述
变换后的空间成为霍夫空间。即:笛卡尔坐标系中一条直线,对应霍夫空间的一个点。

注意
当以下情况
在这里插入图片描述
k=∞是不方便表示的,而且q怎么取值呢,这样不是办法。因此考虑将笛卡尔坐标系换为:极坐标表示。
在这里插入图片描述
上面的公式有一处错误,应该是
x cos ⁡ θ + y sin ⁡ θ = ρ x \cos \theta+y \sin \theta=\rho xcosθ+ysinθ=ρ
在极坐标系下,其实是一样的:极坐标的点→霍夫空间的直线,只不过霍夫空间不再是[k,q]的参数,而是的参数,给出对比图:

在这里插入图片描述
以上就是霍夫变换的基本原理.

3.应用原理

在实现的图像处理领域,图像的像素坐标P(x, y)是已知的,而r, theta则是我们要寻找的变量。如果我们能绘制每个(r, theta)值根据像素点坐标P(x, y)值的话,那么就从图像笛卡尔坐标系统转换到极坐标霍夫空间系统,这种从点到曲线的变换称为直线的霍夫变换。变换通过量化霍夫参数空间为有限个值间隔等分或者累加格子

首先创建一个2D数组(累加器),初始化累加器,所有的值都为0。
行表示 ρ,列表示 θ。
这个数组的大小决定了最后结果的准确性。
如果你希望角度精确到1°,你就需要180列。对于 ρ,最大值为图片对角线距离。

想象一下我们有一个大小为100x100的直线位于图像中央。

  • 取直线上的第一个点,我们知道此处的(x,y)值,把x和y带入公式:ρ = xcosθ + y sinθ;
  • 然后遍历 θ 的取值0, 1, 2, 3,…,180.分别求出对应的 ρ 值,这样我们就得到了一系列(ρ,θ)的数值对;
  • 如果这个数值对在累加器中也存在相应的位置,就在这个位置上加 1。
  • 由于同一条直线上的点必然会有同样的(ρ,θ)。所以现在累加器中的(50,90)=1。
  • 现在取直线上的第二个点。重复上边的过程。更新累加器中的值。现在累加器中(50,90)的值为 2。
  • 你每次做的就是更新累加器中的值。对直线上的每个点都执行上边的操作,每次操作完成之后,累加器中的值就加 1,但其他地方有时会加 1, 有时不会。
  • 按照这种方式下去,到最后累加器中(50,90)的值肯定是最大的。如果你搜索累加器中的最大值,并找到其位置(50,90),这就说明图像中有一条直线,这条直线到原点的距离为 50,它的垂线与横轴的夹角为 90 度。

OpenCV中首先计算(r,θ) 累加数,累加数超过一定值后就认为在同一直线上(有一个阈值)。

4.python代码实现

# coding:utf8

import cv2
import numpy as np


# 读入图像
img = cv2.imread("/home/cheng/Pictures/cangchu.png")
# 转为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Canny边缘检测
edges = cv2.Canny(gray, 50, 100)
"""
canny边缘检测:
有五个步骤:
        1 高斯滤波器降噪
        2 计算梯度
        3 边缘上使用非最大抑制 nms
        4 边缘上使用双阈值去除假阳性
        5 分析所有边缘连接 消除不明显的边缘
"""

minLineLength = 100
maxLineGap = 10
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength, maxLineGap)
"""
cv2.HoughLinesP
    作用:标准霍夫线变换, 找到图像中的所有直线
    参数:
        1 二值图
        2 半径精度
        3 角度精度
        4 最短检测长度
        5 允许的最大缺口
    返回:
        一个列表,每一项是一个四元组,分别是直线两个端点的坐标
"""
for line in lines:
    for x1, y1, x2, y2 in line:
        # 在图片上画直线
        cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)

cv2.imshow("edges", edges)
cv2.imshow("lines", img)
cv2.waitKey()
cv2.destroyAllWindows()
  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
车道线检测是自动驾驶和辅助驾驶技术中非常重要的一项任务。霍夫变换是一种常用的图像处理算法,可用于检测图像中的直线。本文将介绍如何使用霍夫变换Python实现车道线检测系统。 首先,我们需要导入所需的库,包括OpenCV和NumPy。 ```python import cv2 import numpy as np ``` 接下来,我们需要读取图像并将其转换为灰度图像。然后,我们使用Canny边缘检测算法检测图像中的边缘。 ```python img = cv2.imread('test_image.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 50, 150) ``` 现在,我们可以使用霍夫变换检测图像中的直线。霍夫变换需要设置一些参数,包括距离分辨率、角度分辨率和阈值等。在这里,我们将使用以下参数: ```python rho = 2 # 距离分辨率 theta = np.pi / 180 # 角度分辨率 threshold = 50 # 阈值 min_line_length = 100 # 最小线段长度 max_line_gap = 5 # 最大线段间隙 ``` 然后,我们可以使用cv2.HoughLinesP函数来执行霍夫变换。该函数返回检测到的线段的起点和终点坐标。 ```python lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]), min_line_length, max_line_gap) ``` 最后,我们可以将检测到的线段绘制到原始图像上,以显示车道线的位置。 ```python line_image = np.zeros_like(img) for line in lines: x1, y1, x2, y2 = line[0] cv2.line(line_image, (x1, y1), (x2, y2), (255, 0, 0), 5) result = cv2.addWeighted(img, 0.8, line_image, 1, 0) cv2.imshow('result', result) cv2.waitKey(0) ``` 完整的代码如下所示: ```python import cv2 import numpy as np img = cv2.imread('test_image.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 50, 150) rho = 2 # 距离分辨率 theta = np.pi / 180 # 角度分辨率 threshold = 50 # 阈值 min_line_length = 100 # 最小线段长度 max_line_gap = 5 # 最大线段间隙 lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]), min_line_length, max_line_gap) line_image = np.zeros_like(img) for line in lines: x1, y1, x2, y2 = line[0] cv2.line(line_image, (x1, y1), (x2, y2), (255, 0, 0), 5) result = cv2.addWeighted(img, 0.8, line_image, 1, 0) cv2.imshow('result', result) cv2.waitKey(0) ``` 这是一个简单的车道线检测系统的实现。但是,它还有很大的改进空间。例如,它只能检测直线,无法检测曲线,因此在实际应用中可能需要使用更高级的算法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值