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

    xiaoxiao2021-08-19  78

    【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 plain  copy // 图像中的线段检测   //By MoreWindows (http://blog.csdn.net/MoreWindows)   #include <opencv2/opencv.hpp>   using namespace std;   #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")   int main()   {          const char *pstrWindowsSrcTitle = "原图(http://blog.csdn.net/MoreWindows)";       const char *pstrWindowsLineName = "线段检测";          // 从文件中加载原图       IplImage *pSrcImage = cvLoadImage("201.jpg", CV_LOAD_IMAGE_UNCHANGED);       // 灰度图       IplImage *pGrayImage =  cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);       cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);       // 边缘图       IplImage *pCannyImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);       cvCanny(pGrayImage, pCannyImage, 30, 90);       //cvSmooth(pCannyImage, pCannyImage);          // 线段检测(只能针对二值图像)       CvMemStorage *pcvMStorage = cvCreateMemStorage();       double fRho = 1;       double fTheta = CV_PI / 180;       int nMaxLineNumber = 50;   //最多检测条直线       double fMinLineLen = 50;   //最小线段长度       double fMinLineGap = 10;   //最小线段间隔       CvSeq *pcvSeqLines = cvHoughLines2(pCannyImage, pcvMStorage, CV_HOUGH_PROBABILISTIC, fRho, fTheta, nMaxLineNumber, fMinLineLen, fMinLineGap);              // 绘制线段       IplImage *pColorImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 3);       cvCvtColor(pCannyImage, pColorImage, CV_GRAY2BGR);       int i;       for(i = 0; i < pcvSeqLines->total; i++)       {           CvPoint* line = (CvPoint*)cvGetSeqElem(pcvSeqLines, i);           cvLine(pColorImage, line[0], line[1], CV_RGB(255,0,0), 2);       }          cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);       cvShowImage(pstrWindowsSrcTitle, pSrcImage);       cvNamedWindow(pstrWindowsLineName, CV_WINDOW_AUTOSIZE);       cvShowImage(pstrWindowsLineName, pColorImage);          cvWaitKey(0);          cvReleaseMemStorage(&pcvMStorage);       cvDestroyWindow(pstrWindowsSrcTitle);       cvDestroyWindow(pstrWindowsLineName);       cvReleaseImage(&pSrcImage);       cvReleaseImage(&pGrayImage);       cvReleaseImage(&pCannyImage);       cvReleaseImage(&pColorImage);       return 0;   }  

    运行结果如下:

     

    圆检测函数要用到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 plain  copy // 图像中的圆检测   //By MoreWindows (http://blog.csdn.net/MoreWindows)   #include <opencv2/opencv.hpp>   using namespace std;   #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")   int main()   {          const char *pstrWindowsSrcTitle = "原图(http://blog.csdn.net/MoreWindows)";       const char *pstrWindowsLineName = "圆检测";          // 从文件中加载原图       IplImage *pSrcImage = cvLoadImage("201.jpg", CV_LOAD_IMAGE_UNCHANGED);       // 灰度图       IplImage *pGrayImage =  cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);       cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);       //cvSmooth(pGrayImage, pGrayImage);          // 圆检测(灰度图)       CvMemStorage *pcvMStorage = cvCreateMemStorage();       double fMinCircleGap = pGrayImage->height / 10;       CvSeq *pcvSeqCircles = cvHoughCircles(pGrayImage, pcvMStorage, CV_HOUGH_GRADIENT, 1, fMinCircleGap);       //每个圆由三个浮点数表示:圆心坐标(x,y)和半径          // 绘制直线       IplImage *pColorImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 3);       cvCvtColor(pGrayImage, pColorImage, CV_GRAY2BGR);       int i;       for (i = 0; i < pcvSeqCircles->total; i++)       {           float* p = (float*)cvGetSeqElem(pcvSeqCircles, i);           cvCircle(pColorImage, cvPoint(cvRound(p[0]), cvRound(p[1])), cvRound(p[2]), CV_RGB(255, 0, 0), 2);       }          cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);       cvShowImage(pstrWindowsSrcTitle, pSrcImage);       cvNamedWindow(pstrWindowsLineName, CV_WINDOW_AUTOSIZE);       cvShowImage(pstrWindowsLineName, pColorImage);          cvWaitKey(0);          cvReleaseMemStorage(&pcvMStorage);       cvDestroyWindow(pstrWindowsSrcTitle);       cvDestroyWindow(pstrWindowsLineName);       cvReleaseImage(&pSrcImage);       cvReleaseImage(&pGrayImage);       cvReleaseImage(&pColorImage);       return 0;   }  

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

     

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

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

    转载请注明原文地址: https://ju.6miu.com/read-676654.html

    最新回复(0)