opencv学习_11 (moravec角点检测及缺点)

(1)首先我们来看三幅图片理解什么是角点:



我们在图片以某像素点为中心,取一窗口,当窗口向各个方向移动时,其内部灰度值变化不是很明显,则该点即处在平坦区域(如左边图);当其内部灰度值只在几个固定的方向上变化较为明显,那么该点则处在边缘区域(如图中间部分);当向各个方向移动,其变化都是很明显,则该点为角点(如图右)。

当然,上面所说的变化明显与否,是与我们事先设定的阀值进行对比的。

(2)moravec算法对角点定义:

窗口在各个方向上移动,窗口内的灰度值都会产生较大的变化。但实际程序中,这里的各个方向实际只有8个方向。即米形0°,45°,90°,135°,180°,225°,270°,315°。

例如:

这里我们为了简单起见,我们只取了四个方向(0°,45°,90°,135°),取一个w*w(如:5x5)的方形窗口, 计算0度、45度、90度、135度四个方向灰度差的平方和, 取其中的最小值作为该像素点的兴趣值(如下图)。

公式:      




(3)moravec角点检测实现:

步骤:

<1>对于每一个像素点,计算在E(u,v),在我们的算法中,(u,v)的取值是((1,0), (1,1), (0,1), (-1, 1),这里只取了四个方向

       <2>计算最小值对应的每个位置minValue = min{E(u,v)}

       <3>对每个位置minValue进行判定,是不是大于设定的阀值,其中还有个过程是判断其是否为局部最大值以防止产生重复的角点

   代码:

[cpp]  view plain  copy
 print ?
  1. #include <iostream>  
  2. #include "cv.h"  
  3. #include "highgui.h"  
  4. #include "cxcore.h"  
  5.   
  6. using namespace std;  
  7.   
  8. int getMoravec(IplImage *src, CvSeq *corners, float threshold)  
  9. {  
  10.     int winSize = 5;  
  11.     int y, x;  
  12.     int halfwin = winSize/2;  
  13.     int win;  
  14.     IplImage *diffDst = cvCreateImage(cvGetSize(src), 32, 1);  // 保存最小的变量值  
  15.     int cornersCount = 0;   // 保存角点个数  
  16.     for(y = halfwin; y < src->height - halfwin; y++)  
  17.     {  
  18.         for(x = halfwin; x < src->width - halfwin; x++)  
  19.         {  
  20.             float cornersResult[4];  
  21.             cornersResult[0] = 0;  
  22.             cornersResult[1] = 0;  
  23.             cornersResult[2] = 0;  
  24.             cornersResult[3] = 0;  
  25.             float minValue;  
  26.             for(win = -halfwin; win < halfwin; win++)  
  27.             {  
  28.                 cornersResult[0] += pow(cvGetReal2D(src, y, x+win) - cvGetReal2D(src, y, x+win+1), 2);  
  29.                 cornersResult[1] += pow(cvGetReal2D(src, y+win, x+win) - cvGetReal2D(src, y+win+1, x+win+1), 2);  
  30.                 cornersResult[2] += pow(cvGetReal2D(src, y+win, x) - cvGetReal2D(src, y+win+1, x), 2);  
  31.                 cornersResult[3] += pow(cvGetReal2D(src, y+win, x-win) - cvGetReal2D(src, y+win+1, x-win-1),2);  
  32.             }  
  33.             minValue = cornersResult[0];  
  34.             minValue = minValue < cornersResult[1] ? minValue : cornersResult[1];  
  35.             minValue = minValue < cornersResult[2] ? minValue : cornersResult[2];  
  36.             minValue = minValue < cornersResult[3] ? minValue : cornersResult[3];  
  37.             cvSetReal2D(diffDst, y, x, minValue);  
  38.         }  
  39.     }  
  40.     int yywin, xxwin, maxValue;  
  41.     CvPoint resultLoc;  
  42.     for(y = halfwin; y < src->height - halfwin; )  
  43.     {  
  44.         for(x = halfwin; x < src->width - halfwin;)  
  45.         {     
  46.             resultLoc.x = -1;  
  47.             resultLoc.y = -1;  
  48.             maxValue = 0;  
  49.             for(yywin = -halfwin; yywin <= halfwin; yywin++)  
  50.             {  
  51.                 for(xxwin = -halfwin; xxwin < halfwin; xxwin++)  
  52.                 {  
  53.                     if(cvGetReal2D(diffDst, y+yywin, x+xxwin) > maxValue)  
  54.                     {  
  55.                         maxValue = cvGetReal2D(diffDst, y+yywin, x+xxwin);  
  56.                         resultLoc.y = y+yywin;  
  57.                         resultLoc.x = x+xxwin;   
  58.                     }  
  59.                 }  
  60.             }  
  61.             if(maxValue > threshold)  
  62.             {  
  63.                 cvSeqPush(corners, &resultLoc);    //  将角点加入到corners中  这个函数需要记住*******  
  64.                 cornersCount ++;  
  65.             }  
  66.             x += winSize;       //  ++  可能会出现多个corners  
  67.         }  
  68.         y += winSize;  
  69.           
  70.     }  
  71.     cvReleaseImage(&diffDst);  
  72.     return cornersCount;  
  73. }  
  74. int main()  
  75. {  
  76.     IplImage *src = cvLoadImage("E:\\study_opencv_video\\lesson17_1\\1.bmp", 0);  
  77.     if(!src)  
  78.     {  
  79.         cout << "No Image loading..." << endl;  
  80.         return 0;  
  81.     }  
  82.     CvSeq *corners;  
  83.     CvMemStorage *mem = cvCreateMemStorage(0);  // 创建内存序列  用于保存最终角点的空间  
  84.     corners = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvPoint), mem);  // corners指向该内存序列  角点将会保存在一个CvSeq中  
  85.     float threshold =30000;  
  86.     // 调用函数计算角点  
  87.     int cornersCount = getMoravec(src, corners, threshold);  
  88.   
  89.         //图像show用于显示角的提取结果  
  90.     IplImage* show= cvCreateImage(cvGetSize(src),8,3);  
  91.     cvCvtColor(src,show,CV_GRAY2BGR);  
  92.   
  93.   
  94.     // 获取每一个角点的坐标  
  95.     for(int i = 0; i < cornersCount; i++)  
  96.     {  
  97.         // 以角点坐标为中心, 绘制一个半斤为5的圆  
  98.         CvPoint *pt = (CvPoint *)cvGetSeqElem(corners, i);  // 这个也得记住*******  
  99.         cvCircle(show, *pt, 5, cvScalar(0,0,255));  
  100.     }  
  101.     cvNamedWindow("show");  
  102.     cvShowImage("show", show);  
  103.     cvWaitKey(0);  
  104.     cvReleaseImage(&src);  
  105.     cvReleaseImage(&show);  
  106.     cvReleaseMemStorage(&mem);    // 这个也得记住***  
  107.     cvDestroyWindow("show");  
  108.     return 0;  
  109.   
  110.   
  111.   
  112. }  
 效果:

附加:简单解释下代码中的cvSeq和cvMemStorage,我用的不是太熟,当做笔记了哈哈~~:

[cpp]  view plain  copy
 print ?
  1. CvMemStorage *mem = cvCreateMemStorage(0);  //创建内存序列  
  2. CvSeq*corners = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvPoint), mem);  // corners指向内存序列  
  3. cvSeqPush(corners, &resultLoc);    //  将点加入到内存序列中  
  4. CvPoint *pt = (CvPoint *)cvGetSeqElem(corners, i);  // 获得seq中第i个元素  
  5. cvReleaseMemStorage(&mem);   //释放内存序列空间  
[cpp]  view plain  copy
 print ?
  1. cvSeqRemove(corners,i);  // 移除第i个点  
[cpp]  view plain  copy
 print ?
  1. cvSeqSort(corners,cmpFunc,0);// 对内存序列中的点进行排序  

[cpp]  view plain  copy
 print ?
  1. //对seq排序时的比较函数  
  2. static int cmpFunc(const void* _cur , const void* _next , void* userdata)  
  3. {  
  4.     PHARRISPOINT cur = (PHARRISPOINT)_cur;  
  5.     PHARRISPOINT next = (PHARRISPOINT)_next;  
  6.   
  7.     return cur->cornerness < next->cornerness ? 1 : -1;  
  8. }  


(4)moravec角点检测的缺点

moravec角点检测主要有两个缺点:

一:不具有旋转不变性

二:对边缘点的反应比较强烈


转自:

http://blog.csdn.net/lu597203933

猜你喜欢

转载自blog.csdn.net/yzxuminjie/article/details/50948902
今日推荐