74.图像的霍夫直线检测

目录

        1 概念讲解及用处

        2 霍夫直线检测原理

        3 霍夫直线检测步骤

        4 API详解

        5 用C++编写代码进行实现

        1 概念讲解及用处

        直线检测是一种图像处理技术,用于在图像中找到直线的位置。它可以应用于很多领域,如计算机视觉、机器人导航、工业自动化等。直线检测在目标识别、图像分割、特征提取等方面都有广泛的应用。

        霍夫直线检测(Hough Line Detection)是一种在图像中检测直线的计算机视觉技术。它通过将图像上的点转换到参数空间,然后在参数空间中进行投票统计,最终找到图像中存在的直线。

        概念解释: 在二维空间中,一条直线可以由两个参数表示:斜率和截距。但是在实际应用中,很难通过这两个参数准确地描述一条直线,特别是当直线不是水平或垂直时。为了克服这个问题,霍夫直线检测采用了参数空间变换,将直线的参数表示形式转换为极坐标系中的一个点。

        2 霍夫直线检测原理

        我们都知道在直角坐标系中,对于直线我们可以用解析式来表示。 y= kx+b 其中,k是斜率,b是截距; 现在我们假设直线的斜率k和直线的截距是未知的,我们知道直线上的两点A(x0,y0)、B(x1,y1)。

        由此我们可以得到关于k,b的表达式:

y_0= kx_0+b

y_1 = kx_1+b

在此,我们可以将y0= kx0+b,看作是一条关于k,b的直线方程,而不是x,y的直线方程,我们不妨将式子改写为:

b=-x_0 * k+ y_0

可以看出直线的斜率为-x0,直线的截距为y0。 同理可得b=-x1*k+y1直线方程。

由此可以得到,k,b是这两条直线的交点。

        但是根据这两个直线方程,我们可以看出,如果直线的y=kx+b的斜率k=0时,即直线是垂直的。此时我们有b=y0,b=y1,此时两条直线是平行状态是没有交点的,因此我们就无法求出直线的解析式。

        总结:

        (1)直角坐标系中的直线上的每一个点,其实在参数空间中都是一条直线.

        (2)直线上的任意多个点在参数空间中形成的直线都会交于一点,该点坐标就是直线的斜率和截距。

        (3)如果直线是竖直的状态,则在参数空间中将不会产生交点,因此利用参数空间可以求得绝大多数之线的斜率与截距.

        为了解决竖直直线在参数空间中没有交点的问题,我们将直线映射到极坐标空间,假设已知直线上的点A(x0,y0)、B(x1,y1),并假设直线上的垂足点为(p,q),则有

p = rcosθ

q = rsinθ

 

直线y=kx+b的斜率:

        k=tan(90+θ)=-cosθ/sinθ

直线上任意点的坐标值为(x,y),直线的斜率为:

(y-q)/(x-p) = (y-rsinθ)/(x-rcosθ)

两斜率相等,可得;

r=xcosθ+ysinθ

其中r为原点到直线的垂直距离,θ为垂线与x轴之间的夹角。

则直线方程中的A(x0,y0)、B(x1,y1)两点的极坐标方程可以写为:

r=x0cosθ+y0sinθ

r=x1cosθ+y1sinθ

关于r和θ的方程,由方程可以看出这是一个含有三角函数的曲线方程,其实r和θ是这两条曲线的交点。是和参数空间是一样的,只是变成了曲线。

        总结:

       (1)直角坐标系中的直线上的每一个点,其实在极坐标空间中都是一条曲线

        (2)直线上的任意多个点在极坐标空间中形成的曲线都会交于一点,该点坐标就是r和θ,可以根据r和θ计算直线的斜率和截距。

        (3)利用极坐标空间可以求得所有直线的解析式。

        3 霍夫直线检测步骤

为了进行霍夫直线检测,需要经过以下步骤:

  1. 创建一个二维累加器数组(也称为霍夫空间)来记录投票。
  2. 对于图像中的每个非零像素点,遍历所有可能的直线参数组合。
  3. 将每个点转换为参数空间中的曲线,即在参数空间中生成一条曲线。
  4. 在参数空间中统计每条曲线上的投票数,即通过点在参数空间曲线上投票来记录直线的可能性。
  5. 遍历所有可能的 θ 值(通常是从 0 到 π 或 -π 到 π)。
  6. 计算当前直线参数 (ρ, θ):ρ = x * cos(θ) + y * sin(θ)
  7. 在霍夫空间中对应的位置进行投票累加。
  8. 根据累加器数组中的最大值或超过阈值的值来确定检测到的直线。

        通过霍夫直线检测,可以在图像中准确地检测出直线,即使直线存在部分缺失或受到噪声干扰。这使得它在许多计算机视觉应用中广泛使用,例如边缘检测、特征提取、图像分割等。

        4 API详解

OpenCV提供了几个函数来实现直线检测,其中最常用的是HoughLines和HoughLinesP函数。

cpp
void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0, double min_theta=0, double max_theta=CV_PI)
函数参数解释:

image:输入图像,通常为二值图像或边缘检测结果。
lines:输出参数,包含检测到的直线的参数。
rho:距离分辨率,表示参数空间中ρ(表示从原点到直线的距离)的精度。
theta:角度分辨率,表示参数空间中θ(表示直线与x轴夹角)的精度。
threshold:投票阈值,表示在参数空间中判断为直线的最小累加器计数。
srn:可选参数,用于霍夫梯度法的累加器分组对ρ的精确度控制。
stn:可选参数,用于霍夫梯度法的累加器分组对θ的精确度控制。
min_theta:可选参数,表示允许检测到的直线的最小角度。
max_theta:可选参数,表示允许检测到的直线的最大角度。

函数功能及实现步骤:

        读取输入图像并进行预处理,如边缘检测。

        创建一个空的向量 lines,用于存储检测到的直线的参数。

        在输入图像上应用霍夫变换,将每个非零像素点转换为参数空间中的曲线,并在累加器数组中计数投票。

        根据阈值和投票数对参数空间中的曲线进行筛选,将满足条件的曲线(即可能是直线的曲线)存储到 lines 中。

        返回存储了检测到的直线参数的 lines。

void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0)
函数参数解释:

image:输入图像,通常为二值图像或边缘检测结果。
lines:输出参数,包含检测到的直线的起点和终点坐标。
rho:距离分辨率,表示参数空间中ρ(表示从原点到直线的距离)的精度。
theta:角度分辨率,表示参数空间中θ(表示直线与x轴夹角)的精度。
threshold:投票阈值,表示在参数空间中判断为直线的最小累加器计数。
minLineLength:可选参数,表示允许检测到的直线的最小长度。
maxLineGap:可选参数,表示同一直线上两条线段之间的最大间隔。

函数功能及实现步骤:

        读取输入图像并进行预处理,如边缘检测。

        创建一个空的向量 lines,用于存储检测到的直线的起点和终点坐标。

        在输入图像上应用随机霍夫变换,边缘像素点将根据阈值进行投票。

        根据投票结果,将满足条件的线段存储到 lines 中。

        返回存储了检测到的直线起点和终点坐标的 lines。

        5 用C++编写代码进行实现

        下面是使用OpenCV和C++实现直线检测的示例代码:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
    // 读取图像
    Mat image = imread("image.jpg", IMREAD_GRAYSCALE);
    
    // 进行边缘检测
    Mat edges;
    Canny(image, edges, 50, 150);
    
    // 进行直线检测
    vector<Vec2f> lines;
    HoughLines(edges, lines, 1, CV_PI / 180, 100);
    
    // 绘制检测到的直线
    for (size_t i = 0; i < lines.size(); i++)
    {
        float rho = lines[i][0];
        float theta = lines[i][1];
        double a = cos(theta), b = sin(theta);
        double x0 = a * rho, y0 = b * rho;
        Point pt1(cvRound(x0 + 1000 * (-b)), cvRound(y0 + 1000 * a));
        Point pt2(cvRound(x0 - 1000 * (-b)), cvRound(y0 - 1000 * a));
        line(image, pt1, pt2, Scalar(0, 0, 255), 3, LINE_AA);
    }
    
    // 显示结果
    imshow("Lines", image);
    waitKey(0);
    
    return 0;
}

        述代码首先读取了一张灰度图像,然后进行边缘检测,接着使用HoughLines函数进行直线检测,并将检测到的直线用红色线段绘制在原始图像上。最后显示结果图像。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别叭叭儿—好好学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值