OpenCV 霍夫变换直线检测(SHT、MSHT和PPHT)

一、霍夫变换简述
  霍夫变换(Hough Transform)是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法。主要用来从图像中分离出具有某种相同特征的几何形状(如,直线,圆等)。最基本的霍夫变换是从黑白图像中检测直线(线段)。霍夫变换是在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果。
  霍夫变换是于1962年由PaulHough首次提出,最初的霍夫变换是设计用来检测直线和曲线,起初的方法要求知道物体边界线的解析方程,但不需要有关区域位置的先验知识。这种方法的一个突出优点是分割结果的鲁棒性强,即对数据的不完全或噪声不是非常敏感。然而,要获得描述边界的解析表达常常是不可能的。 后于1972年由Richard Duda & Peter Hart推广使用,经典霍夫变换用来检测图像中的直线,后来霍夫变换扩展到任意形状物体的识别,多为圆和椭圆。霍夫变换运用两个坐标空间之间的变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题。

二、OpenCV中的霍夫线变换
2.1、霍夫先变换的种类
  霍夫线变换是一种用来寻找直线的方法。在使用霍夫线变换之前, 首先要对图像进行边缘检测的处理,也即霍夫线变换的直接输入只能是边缘二值图像.
  OpenCV支持三种不同的霍夫线变换,它们分别是:标准霍夫变换(Standard Hough Transform,SHT)和多尺度霍夫变换(Multi-Scale Hough Transform,MSHT)累计概率霍夫变换(Progressive Probabilistic Hough Transform ,PPHT)。其中,多尺度霍夫变换(MSHT)为经典霍夫变换(SHT)在多尺度下的一个变种。累计概率霍夫变换(PPHT)算法是标准霍夫变换(SHT)算法的一个改进,它在一定的范围内进行霍夫变换,计算单独线段的方向以及范围,从而减少计算量,缩短计算时间。之所以称PPHT为“概率”的,是因为并不将累加器平面内的所有可能的点累加,而只是累加其中的一部分,该想法是如果峰值如果足够高,只用一小部分时间去寻找它就够了。这样猜想的话,可以实质性地减少计算时间。
2.2、OpenCV中如何使用霍夫变换
  在OpenCV中,我们可以用HoughLines函数来调用标准霍夫变换SHT和多尺度霍夫变换MSHT。而HoughLinesP函数用于调用累计概率霍夫变换PPHT。累计概率霍夫变换执行效率很高,所有相比于HoughLines函数,我们更倾向于使用HoughLinesP函数。

三、OpenCV中霍夫变换的使用
3.1、HoughLines( )函数解析
  该函数可以找出采用标准霍夫变换的二值图像线条。在OpenCV中,我们可以用其来调用标准霍夫变换SHT和多尺度霍夫变换MSHT的OpenCV内建算法。

void HoughLines(InputArray image, 
                OutputArray lines, 
                double rho, 
                double theta, 
                int threshold, 
                double srn=0, 
                double stn=0 )  

  第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的单通道二进制图像。
  第二个参数,InputArray类型的lines,经过调用HoughLines函数后储存了霍夫线变换检测到线条的输出矢量。每一条线由具有两个元素的矢量表示,其中,是离坐标原点((0,0)(也就是图像的左上角)的距离。 是弧度线条旋转角度(0~垂直线,π/2~水平线)。
  第三个参数,double类型的rho,以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径。PS:Latex中/rho就表示 。
  第四个参数,double类型的theta,以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。
  第五个参数,int类型的threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中。
  第六个参数,double类型的srn,有默认值0。对于多尺度的霍夫变换,这是第三个参数进步尺寸rho的除数距离。粗略的累加器进步尺寸直接是第三个参数rho,而精确的累加器进步尺寸为rho/srn。
  第七个参数,double类型的stn,有默认值0,对于多尺度霍夫变换,srn表示第四个参数进步尺寸的单位角度theta的除数距离。且如果srn和stn同时为0,就表示使用经典的霍夫变换。否则,这两个参数应该都为正数。
3.2、霍夫变换实例(利用HoughLines函数)
  1、代码


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

using namespace cv;

int main()
{
    //【1】载入原始图和Mat变量定义     
    Mat srcImage = imread("1.jpg");    
    Mat midImage, dstImage;//临时变量和目标图的定义  

    //【2】进行边缘检测和转化为灰度图  
    Canny(srcImage, midImage, 50, 200, 3);//进行一此canny边缘检测  
    cvtColor(midImage, dstImage, CV_GRAY2BGR);//转化边缘检测后的图为灰度图  

    //【3】进行霍夫线变换  
    vector<Vec2f> lines;//定义一个矢量结构lines用于存放得到的线段矢量集合  
    HoughLines(midImage, lines, 1, CV_PI / 180, 150, 0, 0);

    //【4】依次在图中绘制出每条线段  
    for (size_t i = 0; i < lines.size(); i++)
    {
        float rho = lines[i][0], theta = lines[i][1];
        Point pt1, pt2;
        double a = cos(theta), b = sin(theta);
        double x0 = a*rho, y0 = b*rho;
        pt1.x = cvRound(x0 + 1000 * (-b));
        pt1.y = cvRound(y0 + 1000 * (a));
        pt2.x = cvRound(x0 - 1000 * (-b));
        pt2.y = cvRound(y0 - 1000 * (a));
        line(dstImage, pt1, pt2, Scalar(55, 100, 195), 1, CV_AA);
    }

    //【5】显示原始图    
    imshow("【原始图】", srcImage);

    //【6】边缘检测后的图   
    imshow("【边缘检测后的图】", midImage);

    //【7】显示效果图    
    imshow("【效果图】", dstImage);

    waitKey(0);

    return 0;
}

  2、运行结果
  (1)原图

这里写图片描述

  (2)边缘检测后的效果图

这里写图片描述

  (3)霍夫变换的效果图

这里写图片描述

3.3、HoughLinesP( )函数解析
  此函数在HoughLines的基础上末尾加了一个代表Probabilistic(概率)的P,表明它可以采用累计概率霍夫变换(PPHT)来找出二值图像中的直线。

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

  第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的单通道二进制图像。
  第二个参数,InputArray类型的lines,经过调用HoughLinesP函数后后存储了检测到的线条的输出矢量,每一条线由具有四个元素的矢量(x_1,y_1, x_2, y_2) 表示,其中,(x_1, y_1)和(x_2, y_2) 是是每个检测到的线段的结束点。
  第三个参数,double类型的rho,以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径。
  第四个参数,double类型的theta,以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。
  第五个参数,int类型的threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中。
  第六个参数,double类型的minLineLength,有默认值0,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。
  第七个参数,double类型的maxLineGap,有默认值0,允许将同一行点与点之间连接起来的最大的距离。
3.4、概率霍夫变换实例(利用HoughLinesP函数)
  1、代码

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

using namespace cv;

int main()
{
    //【1】载入原始图和Mat变量定义     
    Mat srcImage = imread("1.jpg"); 
    Mat midImage, dstImage;//临时变量和目标图的定义  

    //【2】进行边缘检测和转化为灰度图  
    Canny(srcImage, midImage, 50, 200, 3);//进行一此canny边缘检测  
    cvtColor(midImage, dstImage, CV_GRAY2BGR);//转化边缘检测后的图为灰度图  

    //【3】进行霍夫线变换  
    vector<Vec4i> lines;//定义一个矢量结构lines用于存放得到的线段矢量集合  
    HoughLinesP(midImage, lines, 1, CV_PI / 180, 80, 50, 10);

    //【4】依次在图中绘制出每条线段  
    for (size_t i = 0; i < lines.size(); i++)
    {
        Vec4i l = lines[i];
        line(dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(186, 88, 255), 1, CV_AA);
    }

    //【5】显示原始图    
    imshow("【原始图】", srcImage);

    //【6】边缘检测后的图   
    imshow("【边缘检测后的图】", midImage);

    //【7】显示效果图    
    imshow("【效果图】", dstImage);

    waitKey(0);

    return 0;
}

  2、运行结果
  (1)原图

这里写图片描述

  (2)边缘检测后的效果图

这里写图片描述

  (3)PPFH效果图

这里写图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值