利用霍夫变换做直线检测的原理及使用OpenCV函数HoughLines和HoughLinesP()进行直线检测的示例代码

霍夫变换的原理,请大家参考下面这篇博文:
https://blog.csdn.net/poem_qianmo/article/details/26977557

霍夫变换进行直线检测分为两种实现方式:标准霍夫变换和概率霍夫变换。在OpenCV利用标准霍夫变换实现线检测中的函数是HoughLines(),利用概率霍夫变实现线检测的函数是HoughLinesP()。

标准霍夫变换本质上是把图像映射到它的参数空间上,它需要计算所有的M个边缘点,这样它的运算量和所需内存空间都会很大。如果在输入图像中只是处理m(m<M)个边缘点,则这m个边缘点的选取是具有一定概率性的,因此该方法被称为概率霍夫变换(Probabilistic Hough Transform)。

另外从输出的结果来看,函数HoughLines()返回的是描述直线的极坐标;而函数HoughLinesP()返回的是直线的两个端点。

先介绍函数HoughLines(),其原型如下:

void cv::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---输入图像,即源图像,需为8位的单通道二进制图像。

lines---检测到的线条存储在这个lines数组中,它是一个二维数组。每一条直线由两个极坐标参数表示,即参数ρ和θ,其中ρ为直线距离原点的距离(原点为图像的左上角),θ为直线距原点最近的点的旋转角度。当直线为垂直线时,θ值为0;当直线为水平线时,θ值为π/2(即90度)。

rho---累加器的距离分辨率,以像素为单位。要知道为什么有这个参数,得知道霍夫变换线检测的算法原理才行,具体请参考本文开始给的参考博文链接。

theta---累加器的角度分辨率,以弧度为单位。同样的要知道为什么有这个参数,得知道霍夫变换线检测的算法原理才行,具体请参考本文开始给的参考博文链接。

threshold---为阈值,它表示要判断为一条直线所需的最少度量,显然这个值越大,所判断出的直线越少;这个值越小,所判断出的直线越多。

srn---当进行多尺度的霍夫变换时,这是精确的距离累加器步进值。粗略的距离累加器步进尺寸是第三个参数rho,而精确的距离累加器步进尺寸为rho/srn。

stn---当进行多尺度的霍夫变换时,这是精确的角度累加器步进值。粗略的角度累加器步进尺寸是第四个参数theta,而精确的角度累加器步进尺寸为theta/stn。如果srn和stn同时为0,就表示使用经典的霍夫变换。否则,这两个参数应该都为正数。

min_theta---对于标准的霍夫变换和多尺度的霍夫变换,这个值指最小的旋转角度,即θ的最小值,小于这个值的直线将被舍弃。这个值应该介于0到max_theta之间。

max_theta---对于标准的霍夫变换和多尺度的霍夫变换,这个值指最大的旋转角度,即θ的最大值,大于这个值的直线将被舍弃。这个值应该介于min_theta到CV_PI之间。

CV_PI的定义如下:

#define CV_PI   3.1415926535897932384626433832795

关于函数HoughLines()的使用示例,大家可参考我的另一篇博文,链接如下

https://blog.csdn.net/wenhao_ir/article/details/51733627

下面介绍概率霍夫变换函数HoughLinesP()

其函数原型如下:

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

image---为输入图像,要求是8位单通道图像。

lines---为输出的直线向量,每条线用4个元素表示,即直线的两个端点的4个坐标值表示。

rho和theta---分别为距离和角度的分辨率,可以理解为极坐系中r和θ的分辨率。

threshold---为阈值,它表示要判断为一条直线所需的最少度量,显然这个值越大,所判断出的直线越少;这个值越小,所判断出的直线越多。

minLineLength---根据threshold提取出的直线长短不一,这个参数以长度对这些直线作一次筛选,小于这个参数值的就被抛弃。显然这个值越大,所判断出的直线越少;这个值越小,所判断出的直线越多。

maxLineGap---最大直线间隙,即如果有两条线段在一条直线上,但它们之间因为有间隙,所以被认为是两个线段,如果这个间隙大于该值,则被认为是两条线段,否则是一条。显然这个值越大,所判断出的直线越少;这个值越小,所判断出的直线越多。比如两条线段之间的距离为5,如果我们把这个值设为3,则因为两条线段之间的距离为5大于3,所以被判定为两条线段;如果我们把这个值设为8,则因为两条线段之间的距离为5小于8,所以被判定为一条线段。所以这个值越大,所判断出的直线越少。

下面是使用函数HoughLinesP()进行直线检测的示例代码:

代码中用到的图像下载链接:https://pan.baidu.com/s/1AcT_pNXGy7w7E2t1qx2xBQ?pwd=dt3g 

//博主微信/QQ 2487872782
//有问题可以联系博主交流
//有图像处理开发需求请联系博主
//图像处理技术交流QQ群 271891601

//OpenCV版本:3.0
//VS版本:2012

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include<opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>

using namespace cv;
using namespace std;

int main( )
{
  cv::Mat srcImage = cv::imread("F:/material/images/P0041-building.jpg", 0);//读取原图像并同时转换为灰度图
  if (!srcImage.data)   
       return -1;

  cv::Mat edgeMat, houghMat;

  // Canny边缘检测后得到二值图像edgeMat
  Canny(srcImage, edgeMat, 50, 200, 3);
  //为了用带颜色的线条将检测到的直线绘制出来,所以从灰度空间转换到BGR空间
  cvtColor(edgeMat, houghMat, CV_GRAY2BGR);


  // 统计概率的霍夫变换
  vector<Vec4i> lines;
  HoughLinesP(edgeMat, lines, 1, CV_PI/180, 50, 50, 10 );
  for( size_t i = 0; i < lines.size(); i++ )
  {
    Vec4i l = lines[i];
    // 绘制线检测结果
    line( houghMat, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 1, CV_AA);
  }

  cv::imshow("srcImage", srcImage);
  cv::imshow("houghMat", houghMat);
  cv::waitKey();
  return 0;
}

运行结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值