opencv——霍夫变换—直线检测

霍夫变换

定义

霍夫变换是一种特征检测(feature extraction),被广泛应用在图像分析(image
analysis)、计算机视觉(computer vision)以及数位影像处理(digital image processing)。

霍夫变换是用来辨别找出物件中的特征,其流程大致如下:

给定一个物件、要辨别的形状的种类,算法会在参数空间(parameter space)中执行投票来决定物体的形状,而这是由累加空间(accumulator space)里的局部最大值(local maximum)来决定。

常用霍夫变换

  • 1.霍夫直线变换:在图像中寻找直线

  • 2.霍夫圆变换:在图像中寻找圆。

霍夫直线变换

  • Hough Line Transform用来做直线检测
  • 前提条件 – 边缘检测已经完成
    Canny,输入8位图像,输出单通道8位灰度图像
  • 平面空间到极坐标空间转换

如何知道被检测的是一条直线?
在这里插入图片描述
首先将图像转换为极坐标系
极坐标中点的坐标由θ和r进行表征

在这里插入图片描述
根据上面的公式,我们能够推导出如下公式:
在这里插入图片描述
推导过程可以如下:
在这里插入图片描述

公式有什么作用?
例如
在这里插入图片描述
对于上面这条直线,有如下五个点是在直线上的:
在这里插入图片描述
所以我们可以得到五条直线:
在这里插入图片描述

如果我们以θ为横坐标,r为纵坐标,当我们把这五条直线画在同一个坐标系中,我们能得到下面这幅图:

在这里插入图片描述
我们发现,这五条直线交于同一点,这就是直线有的特点,我们就通过这个特点,将所有的直线累加,那交点处因为是所有直线的累加,其像素值一定是最高的,我们知道,像素越高,在图像上越亮,当达到255的时候,是最亮,即为白色。所以我们可以通过这种方式来检测到直线。

在这里插入图片描述

可视化讲解

在这里插入图片描述
有这样的一张图像,对应的极坐标图像如下
在这里插入图片描述
白色的点就是直线交汇的地方
用极坐标反推即可得推测出直线的位置
在这里插入图片描述

HoughLines

此API最终输出的是极坐标中的坐标,也就是(θ,r)
最终结果反算回去还需要一定的难度,于是opencv中有HoughLinesP
这里介绍HoughLines

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 
);

(1)InputArray类型的src ,8位,单通道二进制源图像(灰度图像)。

(2)OutputArray类型的lines,直线的输出向量。每一直线都由一个双元素向量表示。rho是距坐标原点的距离(0,0)(图像左上角)。theta是以弧度为单位的线旋转角度。

(3)double类型的rho,累加器的距离分辨率(像素),一般取1

(4)double类型的theta,累加器的角度分辨率(弧度),一般取值CV_PI/180,每次一度

(5)int类型的threshold,累加器阈值参数。只返回获得足够累加器数量的直线,一般取10,10个像素点算一个直线,如果直线足够长可以换成100。

(6)double类型的srn,对于多尺度Hough变换,它是距离分辨率rho的除数,粗累加器距离分辨率为rho,精确累加器分辨率为rho/srn。如果srn=0和stn=0,则使用经典Hough变换。否则,这两个参数都应为正。如果不用多尺度霍夫变换则设为0

(7)double类型的sth,对于多尺度Hough变换,它是距离分辨率θ的除数。如果不用多尺度霍夫变换则设为0

(8)double类型的min_theta,用于标准和多尺度Hough变换,检查直线的最小角度。必须介于0和maxθ之间。

(9)double类型的max_theta,用于标准和多尺度Hough变换,用于检查线条的最大角度。必须介于最小θ和CVπ之间。

HoughLinesP

此函数返回的直接是坐标
建议使用这个API

HoughLines( 
    InputArray image, 
    OutputArray lines,
    double rho, 
    double theta, 
    int threshold,                              
    double minLineLength = 0, 
    double maxLineGap = 0                             
);

(1)InputArray类型的src ,8位,单通道二进制源图像(灰度图)。

(2)OutputArray类型的lines,直线的输出向量。每一直线都由一个双元素向量表示。rho是距坐标原点的距离(0,0)(图像左上角)。theta是以弧度为单位的线旋转角度。

(3)double类型的rho,累加器的距离分辨率(像素)一般取1

(4)double类型的theta,累加器的角度分辨率(弧度)一般取值CV_PI/180,每次一度。

(5)int类型的threshold,累加器阈值参数。只返回获得足够累加器数量的直线。一般取10,10个像素点算一个直线,如果直线足够长可以换成100。

(6)double类型的minLineLength,最小直线长度。小于该值的线段将被拒绝。

(7)double类型的maxLineGap,同一行上的点之间链接它们所允许的最大间距。

代码

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
	Mat src, src_gray, dst;
	src = imread("C:/Users/86176/Pictures/pics/lines.jpg");
	if (!src.data)
	{
		cout << "could not load image !";
		return -1;
	}
	imshow("【输入图像】", src);

	GaussianBlur(src, src, Size(3, 3), 0, 0);
	Canny(src, src_gray, 0, 255);
	cvtColor(src_gray, dst, CV_GRAY2BGR);

	imshow("【获取边缘】", src_gray);

	vector<Vec4f> plines;
	HoughLinesP(src_gray, plines, 1, CV_PI / 180.0, 100, 0, 10);

	Scalar color = Scalar(0, 0, 255);
	for (size_t i = 0; i < plines.size(); i++) {
		Vec4f hline = plines[i];
		line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 3, LINE_AA);
	}

	imshow("【输出图像】", dst);

	waitKey(0);
	return 0;
}

效果

在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Spark!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值