Opencv学习之霍夫变换

Opencv学习之霍夫变换
在许多应用场合中需要快速准确地检测出直线或者圆,其中一种非常有效的解决问题的方法是霍夫变换,其为图像处理中从图像中识别几何形状的基本方法之一。
霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,该过程在一个参数空间中通过计算累积结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换的结果。霍夫变换运用两个坐标空间之间的变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转换为统计峰值问题。

霍夫线变换–HoughLines函数、HoughLinesP函数

在使用霍夫线变换之前,首先要对图像进行边缘检测的处理,即霍夫线变换的直接输入只能是边缘二值图像。opencv支持标准霍夫变换(Standard Hough Transform,SHT)、多尺度霍夫变换(Multi-Scale Hough Transform,MSHT)和累计概率霍夫变换:是SHT的改进,在一定范围内进行霍夫变换,计算单独线段的方向以及范围,从而减少计算量,缩短计算时间。(Progressive Probabilistic Hough Transform,PPHT)三种不同的霍夫变换。
对于霍夫变换,采用极坐标系参数极径和极角(r, θ )来表示直线,每一对(r, θ )代表一条通过点(x,y)的直线,在极坐标对极径极角平面绘出所有通过它的直线,将得到一条正弦曲线,如果两个不同点进行上述操作后得到的曲线在平面 θ -r相交,这就意味着它们通过同一条直线,也就是说,一条直线能够通过在平面 θ -r寻找交于一点的曲线数量来检测,越多的曲线交于一点也就意味着这个交点表示的直线由更多的点组成,可以设置直线上的阈值来定义多少条曲线交于一点,这样才认为检测到了一条直线。
SHT/MSHT:void HoughLines(inputArray,outputArray,double rho,double theta,int threshold,double srn=0,double stn=0)
*第一个参数,输入图像,需为8位的单通道二进制图像。
*第二个参数,存储了霍夫线变换检测到线条的输出矢量,每一条线由具有两个元素的矢量(r, θ )表示。
*第三个参数,以像素为单位的距离精度,也就是直线搜索时的进步尺寸的单位半径。一般为1
*第四个参数,以弧度为单位的角度精度,也就是直线搜索时的进步尺寸的单位角度。一般为CV_PI/180
*第五个参数,累加平面的阈值参数,即识别某部分为途中的一条直线时它在累加平面中必须达到的值。一般为150
*第六个参数,对于多尺度的霍夫变换,这是第三个参数进步尺寸rho的除数距离,粗略的累加器进步尺寸秩解释第三个参数rho,而精确的累加器进步尺寸为rho/srn。
*第七个参数,对于多尺度霍夫变换,stn表示第四个参数进步尺寸的单位角度theta的除数距离。

PPHT:void HoughLinesP(inputArray,outputArray,double rho,double theta,int threshold,double minLineLength=0,double maxLineGap=0)
*第一个参数,输入图像,需为8位的单通道二进制图像。
*第二个参数,存储了检测到的线条的输出矢量,每一条线由具有4个元素的矢量(x_1,y_1,x_2,y_2)表示,其中(x_1,y_1)和(x_2,y_2)是每个检测到的线段的结束点。
*第三个参数,以像素为单位的距离精度,也就是直线搜索时的进步尺寸的单位半径。一般为1
*第四个参数,以弧度为单位的角度精度,也就是直线搜索时的进步尺寸的单位角度。一般为CV_PI/180
*第五个参数,累加平面的阈值参数,即识别某部分为途中的一条直线时它在累加平面中必须达到的值。一般为150
*第六个参数,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。一般为50
*第七个参数,允许同一行点与点之间连接起来的最大距离。一般为10

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

using namespace cv;
using namespace std;

//全局变量声明
Mat g_srcImage,g_edgeImage,g_dstImage;
vector<Vec4i>g_lines;


//主函数
int main()
{
    //载入图片
    g_srcImage=imread("/Users/new/Desktop/6.jpg");
    if(!g_srcImage.data){printf("读取源图像srcImage错误~!\n");return false;}

    namedWindow("image[origin]");
    imshow("image[origin]",g_srcImage);
    namedWindow("image[renderingsP]");
    //Canny边缘检测以及灰度颜色转换
    Canny(g_srcImage, g_edgeImage, 50, 200,3);
    cvtColor(g_edgeImage, g_dstImage, COLOR_GRAY2BGR);
    HoughLinesP(g_edgeImage, g_lines, 1, CV_PI/180, 80,50,10);
    for(size_t i;i<g_lines.size();++i)
    {
        Vec4i l=g_lines[i];
        line(g_dstImage, Point(l[0],l[1]), Point(l[2],l[3]), Scalar(23,180,55),1,CV_AA);
    }

    imshow("image[renderingsP]",g_dstImage);

    waitKey(0);
    return 0;


}


这里写图片描述

霍夫圆变换–HoughCircles函数

基本原理与霍夫线变换大体类似,只是点对应的二维极径极角空间被三维的圆心点x、y和半径r空间取代。对于圆来说,需要三个参数来表示一个圆,即(x,y,r),即圆心的位置(x,y)和半径r。在opencv中常利用“霍夫梯度法”来解决圆变换问题。
霍夫梯度法:
(1)首先对图像应用边缘检测,如Canny边缘检测。
(2)然后,对边缘图像中的每一个非零点,考虑起局部梯度,即用Sobel()函数计算x和y方向的Sobel一阶导数得到梯度。
(3)利用得到的梯度,由斜率指定的直线上的每一个点都在累加器中被累加,这里的斜率是从一个指定的最小值到指定的最大值的距离。
(4)同时,标记边缘图像中每一个非0像素的位置。
(5)然后从二维累加器中这些点中选择候选的中心,这些中心都大于给定阈值并且大于其所有近邻。这些候选的中心按照累加值降序排列,以便于最支持像素的中心首先出现。
(6)接下来对每一个中心,考虑所有的非0像素。
(7)这些像素按照其与中心的距离排序。从到最大半径的最小距离算起,选择非0像素最支持的一条路径。
(8)如果一个中心收到边缘图像非0像素最充分的支持,并且到前期被选择的中心有足够的距离,那么它就会被保留下来。
void HoughCircles(inputArray,outputArray,int method,double dp,double minDist,double param1=100,double param2=100,int minRadius=0,int maxRadiu=0)
*第一个参数,输入图像,需为8位的灰度单通道图像。
*第二个参数,存储了检测到的圆的输出矢量,每个矢量由包含了3个元素的浮点矢量(x,y,radius)表示。
*第三个参数,使用的检测方法,目前opencv中就霍夫梯度法一种可以使用,即HOUGH_GRADIENT。
*第四个参数,用来检测圆心的累加器图像的分辨率与输入图像之比的倒数,且此参数允许创建一个比输入图像分辨率低的累加器。
*第五个参数,为霍夫变换检测到的圆的圆心之间的最小距离,即让算法能明显区分的两个不同圆之间的最小距离。
*第六个参数,它是第三个参数method设置的检测方法的对应的参数,对于霍夫梯度法而言表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半。
*第七个参数,它是第三个参数method设置的检测方法的对应的参数,对于霍夫梯度法而言表示检测阶段圆心的累加阈值。它越小,就越可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了。
*第八个参数,表示圆半径的最小值。
*第九个参数,表示圆半径的最大值。
注意:使用此函数可以很容易检测出圆的圆心,但是它可能找不到合适的圆半径。可以通过第八个和第九个参数指定最小和最大的圆半径来辅助圆检测效果。或者,可以直接忽略返回半径,因为都有默认值0,然后用额外的一些步骤来进一步确定半径。

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

using namespace cv;
using namespace std;

//主函数
int main()
{
    //载入源图像
    Mat srcImage=imread("/Users/new/Desktop/3.jpg");
    if(!srcImage.data){printf("读取源图像srcImage错误~!\n");return false;}
    //显示源图像
    imshow("image[origin]",srcImage);

    Mat tmpImage;
    //转换灰度图并进行图像高斯平滑
    cvtColor(srcImage, tmpImage, COLOR_BGR2GRAY);
    GaussianBlur(tmpImage, tmpImage, Size(5,5), 2,2);
    //进行霍夫圆变换
    vector<Vec3f> Circles;
    HoughCircles(tmpImage, Circles, CV_HOUGH_GRADIENT, 1.5, 15,200,110,0,0);
    //循环遍历绘制圆
    for(size_t i=0;i<Circles.size();++i)
    {
        Point center(cvRound(Circles[i][0]),cvRound(Circles[i][1]));
        int radius=cvRound(Circles[i][2]);
        //绘制圆心
        circle(srcImage, center, 3, Scalar(0,255,0),-1,8,0);
        //绘制圆轮廓
        circle(srcImage, center, radius, Scalar(155,50,255),3,8,0);
    }

    imshow("image[renderings]",srcImage);


    waitKey(0);
    return 0;
}

这里写图片描述

Opencv技巧

(1)cvRound():对double类型进行四舍五入。
(2)Scalar(55,100,195):其中数字依次代表G、B、R颜色值的数值。
(3)line():利用两点画出一条直线。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值