文档章节

【OpenCV入门指南】第七篇 线段检测与圆检测

andyhe91
 andyhe91
发布于 2014/12/17 14:11
字数 1584
阅读 678
收藏 3

【OpenCV入门指南】第七篇 线段检测与圆检测

在《OpenCV入门指南】第五篇轮廓检测上》与《OpenCV入门指南】第六篇轮廓检测下》讲解了OpenCV的轮廓检测。本篇将讲解在OpenCV中使用线段检测与圆检测。

线段检测与圆检测主要运用Hough变换,Hough变换是一种利用图像的全局特征将特定形状的边缘连接起来,形成连续平滑边缘的一种方法。它通过将源图像上的点影射到用于累加的参数空间,实现对已知解析式曲线进行识别。

OpenCV编程中,线段检测和圆检测已经封装成函数了,直接使用cvHoughLines2cvHoughCircles即可,下面来看看函数介绍和实际代码。

OpenCV入门指南》系列文章地址:http://blog.csdn.net/morewindows/article/category/863841

 

函数功能:检测图像中的线段

函数原型:

CvSeqcvHoughLines2

  CvArrimage

  voidline_storage

  int method,

  double rho

  double theta

  int threshold,

  double param1=0, double param2=0 

);

参数说明:

第一个参数表示输入图像,必须为二值图像(黑白图)。

第二个参数表示存储容器,和上一篇的轮廓检测一样,可以传入CvMemStorage类型的指针。

第三个参数表示变换变量,可以取下面的值:

  CV_HOUGH_STANDARD - 传统或标准 Hough 变换每一个线段由两个浮点数 (ρ, θ) 表示,其中 ρ 是线段与原点(0,0) 之间的距离,θ 线段与 x-轴之间的夹角。

  CV_HOUGH_PROBABILISTIC - 概率 Hough 变换(如果图像包含一些长的线性分割,则效率更高)。它返回线段分割而不是整个线段。每个分割用起点和终点来表示。

  CV_HOUGH_MULTI_SCALE - 传统 Hough 变换的多尺度变种。线段的编码方式与 CV_HOUGH_STANDARD 的一致。

第四个参数表示与象素相关单位的距离精度。

第五个参数表示弧度测量的角度精度。

第六个参数表示检测线段的最大条数,如果已经检测这么多条线段,函数返回。

第七个参数与第三个参数有关,其意义如下:

  对传统 Hough 变换,不使用(0).

  对概率 Hough 变换,它是最小线段长度.

  对多尺度 Hough 变换,它是距离精度 rho 的分母 (大致的距离精度是 rho 而精确的应该是 rho / param1 ).

第八个参数与第三个参数有关,其意义如下:

  对传统 Hough 变换,不使用 (0).

  对概率 Hough 变换,这个参数表示在同一条线段上进行碎线段连接的最大间隔值(gap), 即当同一条线段上的两条碎线段之间的间隔小于param2时,将其合二为一。

  对多尺度 Hough 变换,它是角度精度 theta 的分母 (大致的角度精度是 theta 而精确的角度应该是 theta / param2).

 

线段检测的原理还是有点复杂,有兴趣请阅读专业书籍,下面给一个份示例代码:

[cpp] view plaincopy

  1. // 图像中的线段检测  

  2. //By MoreWindows (http://blog.csdn.net/MoreWindows)  

  3. #include <opencv2/opencv.hpp>  

  4. using namespace std;  

  5. #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  

  6. int main()  

  7. {     

  8.     const char *pstrWindowsSrcTitle = "原图(http://blog.csdn.net/MoreWindows)";  

  9.     const char *pstrWindowsLineName = "线段检测";  

  10.   

  11.     // 从文件中加载原图  

  12.     IplImage *pSrcImage = cvLoadImage("201.jpg", CV_LOAD_IMAGE_UNCHANGED);  

  13.     // 灰度图  

  14.     IplImage *pGrayImage =  cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);  

  15.     cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);  

  16.     // 边缘图  

  17.     IplImage *pCannyImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);  

  18.     cvCanny(pGrayImage, pCannyImage, 30, 90);  

  19.     //cvSmooth(pCannyImage, pCannyImage);  

  20.   

  21.     // 线段检测(只能针对二值图像)  

  22.     CvMemStorage *pcvMStorage = cvCreateMemStorage();  

  23.     double fRho = 1;  

  24.     double fTheta = CV_PI / 180;  

  25.     int nMaxLineNumber = 50;   //最多检测条直线  

  26.     double fMinLineLen = 50;   //最小线段长度  

  27.     double fMinLineGap = 10;   //最小线段间隔  

  28.     CvSeq *pcvSeqLines = cvHoughLines2(pCannyImage, pcvMStorage, CV_HOUGH_PROBABILISTIC, fRho, fTheta, nMaxLineNumber, fMinLineLen, fMinLineGap);  

  29.       

  30.     // 绘制线段  

  31.     IplImage *pColorImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 3);  

  32.     cvCvtColor(pCannyImage, pColorImage, CV_GRAY2BGR);  

  33.     int i;  

  34.     for(i = 0; i < pcvSeqLines->total; i++)  

  35.     {  

  36.         CvPoint* line = (CvPoint*)cvGetSeqElem(pcvSeqLines, i);  

  37.         cvLine(pColorImage, line[0], line[1], CV_RGB(255,0,0), 2);  

  38.     }  

  39.   

  40.     cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);  

  41.     cvShowImage(pstrWindowsSrcTitle, pSrcImage);  

  42.     cvNamedWindow(pstrWindowsLineName, CV_WINDOW_AUTOSIZE);  

  43.     cvShowImage(pstrWindowsLineName, pColorImage);  

  44.   

  45.     cvWaitKey(0);  

  46.   

  47.     cvReleaseMemStorage(&pcvMStorage);  

  48.     cvDestroyWindow(pstrWindowsSrcTitle);  

  49.     cvDestroyWindow(pstrWindowsLineName);  

  50.     cvReleaseImage(&pSrcImage);  

  51.     cvReleaseImage(&pGrayImage);  

  52.     cvReleaseImage(&pCannyImage);  

  53.     cvReleaseImage(&pColorImage);  

  54.     return 0;  

  55. }  

运行结果如下:

 

圆检测函数要用到cvHoughCircles这个函数的函数原形如下:

CVAPI(CvSeq*) cvHoughCircles

  CvArrimagevoidcircle_storage,

  int method

  double dp

  double min_dist,

  double param1 CV_DEFAULT(100),

  double param2 CV_DEFAULT(100),

  int min_radius CV_DEFAULT(0),

  int max_radius CV_DEFAULT(0)

);

可以看出cvHoughCircles与上面的cvHoughLines2函数比较类似,因此讲下部分参数的意思就可以了:

第二个参数表示Hough变换方式,目前只能用CV_HOUGH_GRADIENT

第三个参数表示寻找圆弧圆心的累计分辨率,通常设置成1就可以了。

第四个参数表示两个不同圆之间的最小距离,由于是按圆心来计算距离的,因此对同心圆的检测就无能为力了。

注意,圆检测函数可以使用灰度图。

 

圆检测的代码如下:

[cpp] view plaincopy

  1. // 图像中的圆检测  

  2. //By MoreWindows (http://blog.csdn.net/MoreWindows)  

  3. #include <opencv2/opencv.hpp>  

  4. using namespace std;  

  5. #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  

  6. int main()  

  7. {     

  8.     const char *pstrWindowsSrcTitle = "原图(http://blog.csdn.net/MoreWindows)";  

  9.     const char *pstrWindowsLineName = "圆检测";  

  10.   

  11.     // 从文件中加载原图  

  12.     IplImage *pSrcImage = cvLoadImage("201.jpg", CV_LOAD_IMAGE_UNCHANGED);  

  13.     // 灰度图  

  14.     IplImage *pGrayImage =  cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);  

  15.     cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);  

  16.     //cvSmooth(pGrayImage, pGrayImage);  

  17.   

  18.     // 圆检测(灰度图)  

  19.     CvMemStorage *pcvMStorage = cvCreateMemStorage();  

  20.     double fMinCircleGap = pGrayImage->height / 10;  

  21.     CvSeq *pcvSeqCircles = cvHoughCircles(pGrayImage, pcvMStorage, CV_HOUGH_GRADIENT, 1, fMinCircleGap);  

  22.     //每个圆由三个浮点数表示:圆心坐标(x,y)和半径  

  23.   

  24.     // 绘制直线  

  25.     IplImage *pColorImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 3);  

  26.     cvCvtColor(pGrayImage, pColorImage, CV_GRAY2BGR);  

  27.     int i;  

  28.     for (i = 0; i < pcvSeqCircles->total; i++)  

  29.     {  

  30.         float* p = (float*)cvGetSeqElem(pcvSeqCircles, i);  

  31.         cvCircle(pColorImage, cvPoint(cvRound(p[0]), cvRound(p[1])), cvRound(p[2]), CV_RGB(255, 0, 0), 2);  

  32.     }  

  33.   

  34.     cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);  

  35.     cvShowImage(pstrWindowsSrcTitle, pSrcImage);  

  36.     cvNamedWindow(pstrWindowsLineName, CV_WINDOW_AUTOSIZE);  

  37.     cvShowImage(pstrWindowsLineName, pColorImage);  

  38.   

  39.     cvWaitKey(0);  

  40.   

  41.     cvReleaseMemStorage(&pcvMStorage);  

  42.     cvDestroyWindow(pstrWindowsSrcTitle);  

  43.     cvDestroyWindow(pstrWindowsLineName);  

  44.     cvReleaseImage(&pSrcImage);  

  45.     cvReleaseImage(&pGrayImage);  

  46.     cvReleaseImage(&pColorImage);  

  47.     return 0;  

  48. }  

运行结果如下,可以看出圆的检测准确度不高。

 

OpenCV入门指南】第五篇轮廓检测上》、《OpenCV入门指南】第六篇轮廓检测下》及《【OpenCV入门指南】第七篇线段检测与圆检测》介绍了图像的轮廓检测,线段检测及圆检测。

下面几篇将介绍图像的直方图,这对统计图像的信息以及根据这些信息来增强图像非常有帮助。欢迎继续浏览《【OpenCV入门指南】第八篇灰度直方图》、《【OpenCV入门指南】第九篇灰度直方图均衡化》与《【OpenCV入门指南】第十篇彩色直方图均衡化》。


© 著作权归作者所有

共有 人打赏支持
andyhe91
粉丝 58
博文 129
码字总数 209109
作品 0
长沙
私信 提问
【OpenCV入门指南】第四篇 图像的二值化

【OpenCV入门指南】第四篇 图像的二值化 在上一篇《【OpenCV入门指南】第三篇Canny边缘检测》中介绍了使用Canny算子对图像进行边缘检测。与边缘检测相比,轮廓检测有时能更好的反映图像的内容...

长平狐
2012/12/10
13K
0
【OpenCV入门指南】第二篇 缩放图像

【OpenCV入门指南】第二篇 缩放图像 上一篇《【OpenCV入门指南】第一篇安装OpenCV》讲解了如何在VS2008下安装和配置OpenCV,本篇将介绍使用OpenCV来缩放图片。首先介绍几个关键函数——cvRes...

长平狐
2012/12/10
297
0
【OpenCV入门指南】第一篇 安装OpenCV

【OpenCV第一篇】安装OpenCV 本篇主要介绍如何下载OpenCV安装程序,如何在VS2008下安装配置OpenCV,文章最后还介绍了一个使用OpenCV的简单小例子。 《OpenCV入门指南》系列文章地址:http://...

长平狐
2012/12/10
1K
0
【OpenCV入门指南】第三篇Canny边缘检测

【OpenCV入门指南】第三篇Canny边缘检测 图像的边缘检测的原理是检测出图像中所有灰度值变化较大的点,而且这些点连接起来就构成了若干线条,这些线条就可以称为图像的边缘。 Canny边缘检测算...

长平狐
2012/12/10
639
0
【OpenCv小白入门】人脸检测

本篇小结是关于OpenCv小白入门的,分享一下自己的想法,并且较为详细的总结一下利用OpenCv自带的Haar分类器进行人脸检测以及基于OpenCV3.1+Vs2013+C++的具体代码实现。 原文链接 没有实际的操...

cleverzcc
2018/01/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

精品书籍推荐

JavaScript书籍推荐 1、[JavaScript高级程序设计(第3版)] 2、你不知道的JavaScript(中卷) 3、ES6标准入门(第二版)阮一峰

轻轻的往前走
13分钟前
2
0
JVM(六)为什么新生代有两个Survivor分区?

本文会使用排除法的手段,来讲解新生代的区域划分,从而让读者能够更清晰的理解分代回收器的原理,在开始之前我们先来整体认识一下分代收集器。 分代收集器会把内存空间分为:老生代和新生代...

王磊的博客
19分钟前
5
0
程序员最喜欢的15款文本编辑器推荐

程序员最喜欢的15款文本编辑器推荐 2017年09月18日 17:30:50 kangle_zhu 阅读数:59390 转载地址:http://www.cr173.com/html/50553_1.html 很多时候比如编程查看代码或者打开各种文档下我们...

linjin200
21分钟前
6
0
如何在php后端及时推送消息给客户端

walkor大神,目前需求是这样的: 有一群商家在后台网页处理批量导入产品 -》 服务器接受请求 -》 开始foreach一个一个处理导入请求; 我现在想每成功导入一个就推送到前台显示已经导入成功,...

dragon_tech
39分钟前
13
0
Java利用hanlp完成语句相似度分析的案例详解

分享一篇hanlp分词工具使用的小案例,即利用hanlp分词工具分析两个中文语句的相似度的案例。供大家一起学习参考! 在做考试系统需求时,后台题库系统提供录入题目的功能。在录入题目的时候,...

左手的倒影
46分钟前
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部