图像局部显著性—线特征

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

          参考:【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

原文地址:https://www.cnblogs.com/wishchin/p/9200136.html