10基于opencv的霍夫变换(霍夫线变换_霍夫圆变换)

来源:互联网 发布:芯片编程器 编辑:程序博客网 时间:2024/05/21 09:11

霍夫变换:霍夫线变换和霍夫圆变换

一、HoughLines( )函数

1.1 HoughLines( )函数各参数详解

voidHoughLines(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,就表示使用经典的霍夫变换。否则,这两个参数应该都为正数。

 

1.2调用示例 

Mat ScrImage, OutImage, OutImage1, OutImage2, OutImage3;

ScrImage = imread("E:\\1TJQ\\Opencv\\Images\\image1.jpg");

vector<Vec2f> lines;

   Canny(ScrImage,OutImage1, 150, 50);//Canny边缘检测,霍夫变换的输入图像必须是经过边缘检测的图像

HoughLines(OutImage1, lines, 1, CV_PI / 180, 99); //霍夫变换,将检测到的线存入向量lines(ryo,theta)

for (size_t i = 0; i < lines.size(); i++)//霍夫变换显示

   {

      float rho =lines[i][0], theta = lines[i][1]; //向量lines里面存储了点的极坐标(ryotheta)

      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(OutImage,pt1, pt2, Scalar(55, 100, 195)); //画线函数

}

imshow("HoughLines变换】", OutImage);

 

二、HoughLinesP( )函数

2.1 HoughLinesP( )函数各参数详解

voidHoughLinesP(InputArray image,OutputArray lines,double rho,double theta,int threshold,doubleminLineLength = 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,允许将同一行点与点之间连接起来的最大的距离。

2.2调用示例 

Mat ScrImage, OutImage, OutImage1, OutImage2, OutImage3;

ScrImage = imread("E:\\1TJQ\\Opencv\\Images\\image1.jpg");

vector<Vec4i> LinesP;

   cvtColor(OutImage1,OutImage2, CV_GRAY2BGR);//Canny边缘检测后的灰度图像,转换为BGR图像

HoughLinesP(OutImage1, LinesP, 1, CV_PI / 180, 10); //霍夫累计概率变换

for (size_t i = 0; i < LinesP.size(); i++)              //累计概率霍夫变换画线

   {

      //vector<Vec4i> l = LinesP[i];

      //Point pt1, pt2;

      //pt1.x = LinesP[0];

      line(OutImage2,Point(LinesP[i][0], LinesP[i][1]),Point(LinesP[i][2], LinesP[i][3]),Scalar(186,88, 255));

}

imshow("【累计概率的HoughLines变换】",OutImage2);

 

三、HoughCircles( )函数

3.1 HoughCircles( )函数各参数详解

voidHoughCircles(InputArray image,OutputArray circles,int method,double dp,double minDist,double param1 = 100,double param2= 100,int minRadius = 0,int maxRadius = 0)

Ø  第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的灰度单通道图像。

Ø  第二个参数,InputArray类型的circles,经过调用HoughCircles函数后此参数存储了检测到的圆的输出矢量,每个矢量由包含了3个元素的浮点矢量(x, y, radius)表示。

Ø  第三个参数,int类型的method,即使用的检测方法,目前OpenCV中就霍夫梯度法一种可以使用,它的标识符为CV_HOUGH_GRADIENT,在此参数处填这个标识符即可。

Ø  第四个参数,double类型的dp,用来检测圆心的累加器图像的分辨率于输入图像之比的倒数,且此参数允许创建一个比输入图像分辨率低的累加器。上述文字不好理解的话,来看例子吧。例如,如果dp= 1时,累加器和输入图像具有相同的分辨率。如果dp=2,累加器便有输入图像一半那么大的宽度和高度。

Ø  第五个参数,double类型的minDist,为霍夫变换检测到的圆的圆心之间的最小距离,即让我们的算法能明显区分的两个不同圆之间的最小距离。这个参数如果太小的话,多个相邻的圆可能被错误地检测成了一个重合的圆。反之,这个参数设置太大的话,某些圆就不能被检测出来了。

Ø  第六个参数,double类型的param1,有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半。

Ø  第七个参数,double类型的param2,也有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值。它越小的话,就可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了。

Ø  第八个参数,int类型的minRadius,有默认值0,表示圆半径的最小值。

Ø  第九个参数,int类型的maxRadius,也有默认值0,表示圆半径的最大值。

需要注意的是,使用此函数可以很容易地检测出圆的圆心,但是它可能找不到合适的圆半径。我们可以通过第八个参数minRadius和第九个参数maxRadius指定最小和最大的圆半径,来辅助圆检测的效果。或者,我们可以直接忽略返回半径,因为它们都有着默认值0,单单用HoughCircles函数检测出来的圆心,然后用额外的一些步骤来进一步确定半径。

3.2调用示例 

Mat ScrImage, OutImage, OutImage1, OutImage2, OutImage3;

ScrImage = imread("E:\\1TJQ\\Opencv\\Images\\image1.jpg");

vector<Vec3f> lineCircle;

   Canny(ScrImage,OutImage1, 150, 50);//Canny边缘检测,霍夫变换的输入图像必须是经过边缘检测的图像

HoughCircles(OutImage1, lineCircle, CV_HOUGH_GRADIENT, 2, 100,1000,100); //霍夫圆变换

for (size_t i = 0; i < lineCircle.size(); i++)//霍夫圆变换绘图

   {

      Point center(cvRound(lineCircle[i][0]),cvRound(lineCircle[i][1]));

      int radius= cvRound(lineCircle[i][2]);//绘制圆心 

      circle(OutImage3,center, 3, Scalar(0, 255, 0), -1, 8, 0);//绘制圆轮廓 

      circle(OutImage3,center, radius, Scalar(155, 50, 255), 3, 8, 0);

}

imshow("HoughLines圆变换】", OutImage3);

 

四、完整程序

#include <opencv2/core/core.hpp>

#include <opencv2/imgproc/imgproc.hpp>

#include <opencv2/opencv.hpp>

 

#include <vector>

#include <cstdio>

 

using namespacestd;

using namespacecv;

 

int main()

{

   Mat ScrImage, ScrImgaeCopy1, OutImage, OutImage1, OutImage2,OutImage3, OutImage4, OutImage5, OutImage6, OutImage7, OutImage8, OutImage9;

   ScrImage = imread("E:\\1TJQ\\Opencv\\Images\\circle1.jpg");  //读入图像 \\image1.jpg brownbug.jpg whitebug.jpg

   imshow("【原图】", ScrImage);

 

   vector<Vec2f> lines;

   vector<Vec4i> LinesP;

   vector<Vec3f> lineCircle;

 

   Canny(ScrImage,OutImage1, 150, 50);           //Canny边缘检测,霍夫变换的输入图像必须是一些经过边缘检测的图像

  

   cvtColor(OutImage1,OutImage, CV_GRAY2BGR);//Canny边缘检测后的灰度图像,转换为BGR图像

   cvtColor(OutImage1,OutImage2, CV_GRAY2BGR); //Canny边缘检测后的灰度图像,转换为BGR图像

   cvtColor(OutImage1,OutImage3, CV_GRAY2BGR); //Canny边缘检测后的灰度图像,转换为BGR图像

 

   HoughLines(OutImage1,lines, 1, CV_PI / 180, 99);//霍夫变换,将检测到的线存入向量lines(ryo,theta)

   HoughLinesP(OutImage1,LinesP, 1, CV_PI / 180, 10); //霍夫累计概率变换

   HoughCircles(OutImage1,lineCircle, CV_HOUGH_GRADIENT, 2, 100,1000,100); //霍夫圆变换

 

   for (size_t i = 0; i < lines.size(); i++)//霍夫变换

   {

      float rho =lines[i][0], theta = lines[i][1]; //向量lines里面存储了点的极坐标(ryotheta)

      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(OutImage,pt1, pt2, Scalar(55, 100, 195)); //画线函数

   }

 

   for (size_t i = 0; i < LinesP.size(); i++)//累计概率霍夫变换画线

   {

      line(OutImage2,Point(LinesP[i][0], LinesP[i][1]),Point(LinesP[i][2], LinesP[i][3]),Scalar(186,88, 255));

   }

 

   for (size_t i = 0; i < lineCircle.size(); i++)//霍夫圆变换绘图

   {

      Point center(cvRound(lineCircle[i][0]),cvRound(lineCircle[i][1]));

      int radius= cvRound(lineCircle[i][2]); //绘制圆心 

      circle(OutImage3,center, 3, Scalar(0, 255, 0), -1, 8, 0); //绘制圆轮廓 

      circle(OutImage3,center, radius, Scalar(155, 50, 255), 3, 8, 0);

   }

 

   resize(OutImage,OutImage, Size(), 1, 1); //放大图片2

   resize(OutImage2,OutImage2, Size(), 1, 1); //放大图片2

 

   imshow("Sobel边缘检测X+Y", OutImage1);

   imshow("HoughLines变换】",OutImage);

   imshow("【累计概率的HoughLines变换】",OutImage2);

   imshow("HoughLines圆变换】", OutImage3);

 

   waitKey(0);

   return NULL;

}

 

参考内容:

http://www.cnblogs.com/mq0036/p/5902104.html

阅读全文
0 0
原创粉丝点击