opencv Learning _13 (trajkovic Corner Detection)

Keywords: angular less Windows

Source: http://blog.csdn.net/songzitea/article/details/13614977

Background introduction

The main content of this section comes from the introduction of Trajkovic operator by Miroslav Trajkovic and Mark Hedley[1] in 1998. FastCorner Detection . Trajkovic Operator (4-Neighbours) [3] (Note: The pictures in this section are mainly from here). The value of Trajkovic operator corner extraction method is that it is better than other corner extraction methods in the same period (such as Moravec corner, Harris corner). At the same time, it is much faster than other corner extraction methods in the same period.

fundamental theory

The definition of the author's diagonal point is the same as that of Moravec's and Harris's: the point where the gray value of the image varies greatly in all directions is regarded as the corner point. The definition of corner quantity is similar to Moravec, that is, the minimum value of gray level change in each direction (when the change of gray level is the smallest in a certain direction and the minimum value is larger than a certain threshold, then this point is considered as a corner point). And Moravec Trajkovic performs better than harris, because Trajkovic uses pixel interpolation to compare the degree of gray value change in each direction, while moravec only compares in a limited direction. Compared with harris, both have the same effect, but Trajkovic is much faster than haris.

Trajkovic's performance in speed determines that it can be used in systems with high real-time requirements. But Trajkovic also has the disadvantage that it does not have rotation invariance, is sensitive to noise, and has a large response value to diagonal points. There will be corresponding methods for these shortcomings, but these shortcomings can not be completely solved. Trajkovic operator calculates the angular points in a small circular window, and considers all the straight lines passing through the center of the circle, that is, calculates the degree of gray value change in each possible direction. Assuming that the center of a circle is represented by C, any straight line passing through the center of the circle will intersect the circle at two points, as shown in Figure 1.

Figure 1: Notation for Trajkovic Operator

So, the definition of Trajkovic's diagonal quantity is


C(x,y) denotes the amount of corners at any point (x,y) on image I. This formula can tell whether it is a corner or not. There are four cases in which point (x,y) is located at the destination of the image. As shown in the following figure:


The first case: point (x,y) in the internal area: at this time, the circular window through the center of point (x,y) is completely in a relatively flat area, or most of the circular windows are in this flat area (as shown in figure A above). In this case, at least one large straight line passing through the center point C makes the Ic equal to Ip and Ic equal to Ip'. According to the formula for calculating corners, the calculated C(x,y) must be a very small value, so that the point (x,y) can be excluded from the corners. Moreover, in most cases, there will be more than one such point P memory, making noise tolerance to a certain extent.

Second case: point (x,y) on the edge: at this time, the center point (x,y) of the circular window just falls on the edge (as shown in figure B above). There is only one point to P,P'makes Ic approximately equal to Ip and Ic approximately equal to Ip'. Under ideal conditions, the angular quantity C(x,y) calculated from the formula of angular quantity is relatively small. But because there is only one straight line like this, it is easy to be disturbed by noise.

Third case: point (x,y) at the corner: when the center of the circular window (x,y) is at the corner (as shown in figure C above). The gray value of at least one point in any point (x,y) intersecting with a circle P, P', P'differs greatly from that of the central point. So the calculated corners are larger (larger than the set threshold, so they will be considered corners).

Fourth case: point (x,y) at an isolated point: if at an isolated point (as shown in figure D above), for each line Ip, Ip', the difference between the score and the value of Ic is large, then the calculated corners are also large. This point is noisy at this point, but because of the large amount of corners, it will be considered as corners. In order to eliminate the influence of this kind of noise, we can first use Gauss smoothing to denoise.

According to the above analysis, Trajkovic is greatly affected by noise, so it is possible to realize Gauss smoothing denoising before corner detection using Trajkovic operator.

Calculating Method of Corner Quantity

At present, there is no specific introduction about how to calculate the corner quantity of Trajkovic. Firstly, as shown in Figure 2 below, the horizontal gray value variation rA and the vertical gray value variation rB are easy to calculate.

How to calculate the change degree of gray value in any direction? First of all, we can take the minimum value of the corners:



 

Figure 2: Interpixel positions               Figure3: Interpixel approximation for a 3x3 window using 4-neighbours

Now, we can convert the problem into that any line passing through point C intersects with a circle at P, P', Q':

Substitute Formula (2) into Formula (1):


Well,The minimum is the conclusion that

Multigrid Algorithm

Corners can be divided into two categories: geometric corners and texture corners. Geometric corners are intersected by the edges of objects in the image. The texture corners are generated by the texture of the object surface (such as grass, clothing texture, etc.). Usually, the number of geometric corners in an image is much less than that of texture corners. The aim of multi-lattice algorithm is to detect more geometric corners and less texture points. Trajkovic believes that geometric corners are more stable than texture corners. Therefore, from the point of view of practical use, it is reasonable to reduce texture corners.

After observation, it is found that the texture corners are generally very dense, and the gray value changes in a very small area. Therefore, the transformation of gray value in the region can be eliminated by reducing the original image and then extracting the corners. The method of image reduction is not interpolation, but averaging. As shown in the following figure:


In Trajkovic corner detection, firstly, the original image is reduced by using multi-grid method, which not only reduces the number of texture corner points detected, but also speeds up the speed of Trajkovic corner detection. In the reduced version of Trajkovic corner detection image, a simple corner calculation formula is used to preliminarily determine whether the candidate corner points are or not. If so, it is further determined on the original image.

Figure 4: Corner points detected at different image resolutions

As shown in Figure 4, the original size is 256*256. There is a grassland in the image, and the corners on the grassland are meaningless for us to match corners. When the image was reduced to 128*128, the corners on the grassland were eliminated. Of course, the image can not be reduced too much, otherwise, the geometric corners will disappear, when reduced to 64*64, part of the geometric corners will disappear.

Algorithm flow




Code:

  1. #include <iostream>  
  2. #include "cv.h"  
  3. #include "highgui.h"  
  4. #include "cxcore.h"  
  5. using namespace std;  
  6.   
  7. void getTrajkovic4NCorner(IplImage* src,IplImage* srcResize , float T1 , float T2 ,CvSeq* corners,int maximumSize)  
  8. {  
  9.     int x,y,maxChar=255,scaleX = src->width/srcResize->width,scaleY = src->height/srcResize->height;  
  10.       
  11.       
  12.     IplImage* srcResizeMap ,*srcMap;  
  13.       
  14.     srcResizeMap = cvCreateImage(cvGetSize(srcResize),8,1);     //The amount of corners used to save the reduced image  
  15.     srcMap = cvCreateImage(cvGetSize(src),32,1);                //The amount of corners calculated to preserve the source image  
  16.       
  17.     cvZero(srcMap);  
  18.     cvZero(srcResizeMap);  
  19.   
  20.     for( y=1;y<srcResize->height-1;y++)  
  21.     {  
  22.         uchar* preRow = (uchar*)(srcResize->imageData + (y-1)*srcResize->widthStep);  
  23.         uchar* curRow = (uchar*)(srcResize->imageData + y*srcResize->widthStep);  
  24.         uchar* nextRow = (uchar*)(srcResize->imageData + (y+1)*srcResize->widthStep);  
  25.           
  26.         uchar* MapData = (uchar*)(srcResizeMap->imageData + y*srcResizeMap->widthStep);  
  27.       
  28.         for(x=1;x<srcResize->width-1;x++)  
  29.         {  
  30.               
  31.             int IC,IA,IB,IAA,IBB;  
  32.             int rA,rB,C_Simple;  
  33.               
  34.             //curRow[x] is uchar type and IC is int type. If the other three bytes of int type are assigned directly, random values may be generated.  
  35.             IC = curRow[x]&maxChar;  
  36.               
  37.             IA = curRow[x+1]&maxChar;  
  38.             IAA = curRow[x-1]&maxChar;  
  39.   
  40.             IB = preRow[x]&maxChar;  
  41.             IBB = nextRow[x]&maxChar;  
  42.               
  43.             rA = (IA-IC)*(IA-IC) + (IAA-IC)*(IAA-IC);  
  44.             rB = (IB-IC)*(IB-IC) + (IBB-IC)*(IBB-IC);  
  45.               
  46.             C_Simple = rA < rB ? rA : rB;  
  47.           
  48.             if(C_Simple > T1)  
  49.             {  
  50.                 MapData[x]=1;  
  51.             }  
  52.         }  
  53.       
  54.     }  
  55.   
  56.     for( y=1;y<srcResize->height-1;y++)  
  57.     {  
  58.           
  59.         uchar* srcResizeMapData = (uchar*)(srcResizeMap->imageData + y*srcResizeMap->widthStep);  
  60.         //uchar* srcMapData = (uchar*)(srcMap->imageData + y*srcMap->widthStep);  
  61.   
  62.         for(x=1;x<srcResize->width-1;x++)  
  63.         {  
  64.               
  65.             if(srcResizeMapData[x]==0)  
  66.             {  
  67.                 continue;  
  68.             }  
  69.               
  70.             int originX,originY,IC,IA,IB,IAA,IBB;  
  71.             int rA,rB,C_Simple;  
  72.               
  73.             originX = x*scaleX;  
  74.             originY = y*scaleY;  
  75.               
  76.             uchar* srcPreRow = (uchar*)(src->imageData + (originY-1)*src->widthStep);  
  77.             uchar* srcCurRow = (uchar*)(src->imageData + originY*src->widthStep);  
  78.             uchar* srcNextRow = (uchar*)(src->imageData + (originY+1)*src->widthStep);  
  79.               
  80.             IC = srcCurRow[originX]&maxChar;  
  81.               
  82.             IA = srcCurRow[originX+1]&maxChar;  
  83.             IAA = srcCurRow[originX-1]&maxChar;  
  84.   
  85.             IB = srcPreRow[x]&maxChar;  
  86.             IBB = srcNextRow[x]&maxChar;  
  87.   
  88.             rA = (IA-IC)*(IA-IC) + (IAA-IC)*(IAA-IC);  
  89.             rB = (IB-IC)*(IB-IC) + (IBB-IC)*(IBB-IC);  
  90.               
  91.             C_Simple = rA < rB ? rA : rB;  
  92.               
  93.             if(C_Simple>T2)  
  94.             {  
  95.                 float B1,B2,C,A,B,C_InterPixel;  
  96.                   
  97.                 B1 = (IB-IA)*(IA-IC)+(IBB-IAA)*(IAA-IC);  
  98.                 B2 = (IB-IAA)*(IAA-IC)+(IBB-IA)*(IA-IC);  
  99.                 C = rA;  
  100.                 B = B1<B2 ? B1 : B2;  
  101.                 A = rB-rA-2*B;  
  102.                   
  103.                 if(B<0 &&(A+B)>0)  
  104.                 {  
  105.                     C_InterPixel = C-(B*B)/A;  
  106.                 }  
  107.                 else  
  108.                 {  
  109.                     C_InterPixel=C_Simple;  
  110.                 }  
  111.                   
  112.                 if(C_InterPixel>T2)  
  113.                 {  
  114.   
  115.                     float* srcMapData = (float*)(srcMap->imageData + originY*srcMap->widthStep);  
  116.                     srcMapData[originX]=C_InterPixel;  
  117.                     //cvSetReal2D(srcMap,originY,originX,C_InterPixel);  
  118.                 }  
  119.             }  
  120.               
  121.         }  
  122.   
  123.     }  
  124.   
  125.   
  126.     //Computation of local maximum and whether the maximum is greater than the threshold  
  127.     int beginY,endY,beginX,endX;  
  128.     int halfWinSize = maximumSize/2;  
  129.   
  130.     beginY = halfWinSize;  
  131.     endY = srcMap->height - halfWinSize;  
  132.   
  133.     beginX = halfWinSize;  
  134.     endX = srcMap->width - halfWinSize;  
  135.       
  136.     for(y=beginY;y<endY;)  
  137.     {  
  138.         for(x=beginX;x<endX;)  
  139.         {  
  140.             //Finding Local Maxima and Its Location Information  
  141.             float maxValue=0;  
  142.             int flag = 0 ;  
  143.             CvPoint maxLoc;  
  144.             maxLoc.x = -1;  
  145.             maxLoc.y = -1;  
  146.   
  147.   
  148.             //Firstly, the local maxima of maximumSize*maximumSize in the window centered by the point (x,y) bit are calculated.  
  149.             for(int winy=-halfWinSize;winy<=halfWinSize;winy++)  
  150.             {  
  151.                 for(int winx=-halfWinSize;winx<=halfWinSize;winx++)  
  152.                 {  
  153.                     float value ;  
  154.                     value = cvGetReal2D(srcMap,y+winy,x+winx);  
  155.                       
  156.                     //Calculate the maximum value in the window, save it to max and save its coordinates to maxLoc  
  157.                     if(value>maxValue)  
  158.                     {  
  159.                         maxValue = value;  
  160.                         maxLoc.x = x+winx;  
  161.                         maxLoc.y = y+winy;  
  162.                         flag = 1;  
  163.                     }  
  164.                 }  
  165.             }  
  166.               
  167.   
  168.   
  169.               
  170.             //If a local maximum is found and the value is greater than the preset threshold, it is considered a corner point.  
  171.             if(flag==1 && maxValue>T2)  
  172.             {  
  173.                 cvSeqPush(corners,&maxLoc);  
  174.               
  175.             }  
  176.               
  177.           
  178.             x = x+halfWinSize;  
  179.   
  180.         }  
  181.           
  182.         y = y + halfWinSize;  
  183.     }  
  184.   
  185.     cvReleaseImage(&srcResizeMap);  
  186.     cvReleaseImage(&srcMap);  
  187. }  
  188.   
  189. int main(int argc,char* argv[])  
  190. {  
  191.     //Dependent variable  
  192.     int scale = 2;  
  193.     IplImage* src,*srcGray,*srcGrayResize;  
  194.     CvMemStorage* mem = cvCreateMemStorage(0);  
  195.     CvSeq* TrajkovicPoints;  
  196.   
  197.     src = cvLoadImage("E:\\study_opencv_video\\lesson17_2\\2.jpg");//Source image  
  198.       
  199.     srcGray = cvCreateImage(cvGetSize(src),8,1);  
  200.       
  201.     if(!src)  
  202.     {  
  203.         cout << "src is null" << endl;  
  204.         return 0;  
  205.     }  
  206.       
  207.     cvCvtColor(src,srcGray,CV_BGR2GRAY);  
  208.     srcGrayResize = cvCreateImage(cvSize(srcGray->width/scale,srcGray->height/scale),8,1);  
  209.     cvResize(srcGray,srcGrayResize);//Modify resize to a multi-lattice algorithm  
  210.   
  211.     //Trajkovic 4. Space for corner preservation of neighborhood corners. Corner coordinates are stored in a sequence  
  212.     TrajkovicPoints = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvPoint),mem);  
  213.       
  214.   
  215.     //Trajkovic 4 Neighborhood Corner Detection  
  216.     int T1=120,T2=150,localArea = 8;   //Local Area is the size of the window when the local maximum is suppressed  
  217.     getTrajkovic4NCorner(srcGray,srcGrayResize,T1,T2,TrajkovicPoints,localArea);  
  218.       
  219.     //Get the coordinates of each corner  
  220.     for(int x=0;x<TrajkovicPoints->total;x++)  
  221.     {  
  222.         //Get the coordinates of the x-th corner  
  223.         CvPoint* pt = (CvPoint*)cvGetSeqElem(TrajkovicPoints,x);  
  224.   
  225.         //Draw a circle with radius 5 centered on the coordinates of corners  
  226.         cvCircle(src,*pt,2,cvScalar(255,0,255,0));  
  227.     }  
  228.   
  229.   
  230.     //Display image  
  231.     cvNamedWindow("dst");  
  232.     cvShowImage("dst",src);  
  233.     cvWaitKey(0);  
  234.   
  235.     //Release resources  
  236.     cvReleaseImage(&src);  
  237.     cvReleaseImage(&srcGray);  
  238.     cvReleaseImage(&srcGrayResize);  
  239.     cvReleaseMemStorage(&mem);  
  240.     return 0;  
  241.   
  242. }  
English Links: http://kiwi.cs.dal.ca/~dparks/CornerDetection/trajkovic.htm

Posted by virtual_odin on Wed, 03 Apr 2019 19:06:32 -0700