zoukankan      html  css  js  c++  java
  • 图像局部显著性—线特征

    线检测--快速几何形状检测

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

    (一)、边缘检测

           一维显著特征常见表示为边缘。边缘检测的预处理常用 高斯模糊;主要数学运算为计算一阶和二阶导数,寻找梯度和零交叉点,其中梯度计算可用快速卷积码实现;常见的算子有:
                  一阶::Roberts Cross算子,Prewitt算子,Sobel算子, Kirsch算子,罗盘算子;
                  二阶: Marr-Hildreth,在梯度方向的二阶导数过零点,Canny算子,Laplacian算子。
           图像处理过程使用卷积实现边缘检测:常用的边缘检测模板有Laplacian算子、Roberts算子、Sobel算子、log(Laplacian-Gauss)算子、Kirsch算子和Prewitt算子等。

           常见算子Sobel和Canny比较:Soble边缘检测算法比较简,实际应用中效率比canny边缘检测效率要高,但是边缘不如Canny检测的准确,但是很多实际应用的场合,sobel边缘却是首选,尤其是对效率要求较高,而对细纹理不太关心的时候,也可以作为预检测。


    (二):快速几何形状检测

    1. 线段检测和圆检测:

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

          在OpenCV编程中,线段检测和圆检测已经封装成函数了,直接使用cvHoughLines2cvHoughCircles即可。
     

    Hough线检测函数原型:

    CvSeq* cvHoughLines2(
      CvArr* image, //第一个参数表示输入图像,必须为二值图像(黑白图)
      void* line_storage,//第二个参数表示存储容器,和上一篇的轮廓检测一样,可以传入CvMemStorage类型的指针
      int method,//第三个参数表示变换变量,可以取下面的值:
     //CV_HOUGH_STANDARD - 标准 Hough 变换. 每一线段由两浮点数(ρ,θ)表示,其中ρ是线段与原点(0,0)之间的距离,θ线段与 x-轴之间的夹角。
     //CV_HOUGH_PROBABILISTIC - 概率Hough变换(若图像包含一些长的线性分割,效率更高)。返回线段分割而非整个线段。每个分割用起点和终点表示。
     //CV_HOUGH_MULTI_SCALE - 传统 Hough 变换的多尺度变种。线段的编码方式与 CV_HOUGH_STANDARD 的一致。
      double rho,//第四个参数表示与象素相关单位的距离精度。
      double theta,//第五个参数表示弧度测量的角度精度。
      int threshold,//第六个参数表示检测线段的最大条数,如果已经检测这么多条线段,函数返回。
      double param1=0, //第七个参数与第三个参数有关,其意义如下:
      //对传统 Hough 变换,不使用(0); 对概率 Hough 变换,它是最小线段长度.
      对多尺度 Hough 变换,它是距离精度 rho 的分母 (大致的距离精度是 rho 而精确的应该是 rho / param1 ).
    double param2=0//第八个参数与第三个参数有关,其意义如下:
      //对传统 Hough 变换,不使用 (0).
      //对概率 Hough 变换,此参数表示在同一线段上进行碎线段连接的最大间隔值(gap), 即当同一线段两碎线段间的间隔小于param2时,将其合二为一。
      //对多尺度 Hough 变换,它是角度精度 theta 的分母 (大致的角度精度是 theta 而精确的角度应该是 theta / param2). 
    );

    函数实现:
    // 图像中的线段检测  
    #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 = "线段检测";  
          
    // 从文件中加载原图    
    Mat SrcImage = imread("D:/Circle.jpg", CV_LOAD_IMAGE_UNCHANGED);  
    // 灰度图  
    Mat GrayImage= Mat(Size(SrcImage.rows, SrcImage.cols), CV_8SC1);//CV_32FC1);  
    //cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);  
    // 边缘图  
    Mat CannyImage= Mat(Size(SrcImage.rows, SrcImage.cols), CV_8SC1);//CV_32FC1);  
    cvCanny(pGrayImage, pCannyImage, 30, 90);  //1、使用了Canny检测的方法!!!
    //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);   
            for(int 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);  
          
            
          
            cvReleaseMemStorage(&pcvMStorage);  
            cvDestroyWindow(pstrWindowsSrcTitle);  
            cvDestroyWindow(pstrWindowsLineName);  
            //cvReleaseImage(&pSrcImage);  
            //cvReleaseImage(&pGrayImage);  
            //cvReleaseImage(&pCannyImage);  
            //cvReleaseImage(&pColorImage);  
        cvWaitKey(0);  
        return 0;  
    }  

    引用原结果:

            


    Hough圆检测的代码:

    #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原型里面的算法.....


    基本应用:矩形检测
    待完成.....
    han and zhu (2005)提出使用潜在的匹配矩形形状和嵌套结构(矩形和消失点之间)的语法来推导 矩形框 最有可能的对应线段...
    计算机视觉:算法与应用 p196-p197

  • 相关阅读:
    java 静态和非静态代码块执行顺序
    spring boot 学习
    js中的jQuery Validate增加手机号码验证
    JAVA验证手机号码是否正确
    redis启动报错 var/run/redis_6379.pid exists, process is already running or crashed
    移动端点击a标签拨打电话
    js计算两个日期之间的天数
    JS根据日期获取判断星期几
    JAVA生成订单编号工具类
    JAVA微信支付——微信公众号内支付 代码
  • 原文地址:https://www.cnblogs.com/wishchin/p/9200136.html
Copyright © 2011-2022 走看看