(1) First, let's look at three pictures to understand what corner is:

We take a window as the center of a pixel in a picture. When the window moves in all directions, the change of its internal gray value is not obvious, then the point is in the flat area (such as the left image); when the change of its internal gray value is obvious only in several fixed directions, then the point is in the edge area (such as the middle part); when the window moves in all directions, the change is all. Obviously, the point is the corner (see right).
Of course, whether the changes mentioned above are obvious or not is compared with the threshold we set beforehand.
(2)moravec algorithm diagonal definition:
When the window moves in all directions, the gray value in the window will change greatly. But in the actual program, there are only eight directions in all directions. That is, the shape of the meter is 0, 45, 90, 135, 180, 225, 270 and 315 degrees.
For example:
For the sake of simplicity, we only take four directions (0, 45, 90, 135 degrees). We take a square window of w*w (e.g. 5x5) to calculate the sum of squares of gray-scale differences in four directions: 0, 45, 90 and 135 degrees, and take the minimum value as the interest value of the pixel (as shown below).
Formula:


(3)moravec corner detection:
Steps:
<1> For each pixel, we calculate E(u,v). In our algorithm, (u,v) is ((1, 0), (1, 1), (0, 1), (-1, 1), (-1), where only four directions are taken.
minValue = min{E(u,v)} for each location corresponding to the minimum value calculated <2>.
Whether the minValue of each location is greater than the set threshold is determined by <3> and another process is to determine whether it is a local maximum to prevent duplication of corners?
Code:
-
#include <iostream>
-
#include "cv.h"
-
#include "highgui.h"
-
#include "cxcore.h"
-
-
using namespace std;
-
-
int getMoravec(IplImage *src, CvSeq *corners, float threshold)
-
{
-
int winSize = 5;
-
int y, x;
-
int halfwin = winSize/2;
-
int win;
-
IplImage *diffDst = cvCreateImage(cvGetSize(src), 32, 1);
-
int cornersCount = 0;
-
for(y = halfwin; y < src->height - halfwin; y++)
-
{
-
for(x = halfwin; x < src->width - halfwin; x++)
-
{
-
float cornersResult[4];
-
cornersResult[0] = 0;
-
cornersResult[1] = 0;
-
cornersResult[2] = 0;
-
cornersResult[3] = 0;
-
float minValue;
-
for(win = -halfwin; win < halfwin; win++)
-
{
-
cornersResult[0] += pow(cvGetReal2D(src, y, x+win) - cvGetReal2D(src, y, x+win+1), 2);
-
cornersResult[1] += pow(cvGetReal2D(src, y+win, x+win) - cvGetReal2D(src, y+win+1, x+win+1), 2);
-
cornersResult[2] += pow(cvGetReal2D(src, y+win, x) - cvGetReal2D(src, y+win+1, x), 2);
-
cornersResult[3] += pow(cvGetReal2D(src, y+win, x-win) - cvGetReal2D(src, y+win+1, x-win-1),2);
-
}
-
minValue = cornersResult[0];
-
minValue = minValue < cornersResult[1] ? minValue : cornersResult[1];
-
minValue = minValue < cornersResult[2] ? minValue : cornersResult[2];
-
minValue = minValue < cornersResult[3] ? minValue : cornersResult[3];
-
cvSetReal2D(diffDst, y, x, minValue);
-
}
-
}
-
int yywin, xxwin, maxValue;
-
CvPoint resultLoc;
-
for(y = halfwin; y < src->height - halfwin; )
-
{
-
for(x = halfwin; x < src->width - halfwin;)
-
{
-
resultLoc.x = -1;
-
resultLoc.y = -1;
-
maxValue = 0;
-
for(yywin = -halfwin; yywin <= halfwin; yywin++)
-
{
-
for(xxwin = -halfwin; xxwin < halfwin; xxwin++)
-
{
-
if(cvGetReal2D(diffDst, y+yywin, x+xxwin) > maxValue)
-
{
-
maxValue = cvGetReal2D(diffDst, y+yywin, x+xxwin);
-
resultLoc.y = y+yywin;
-
resultLoc.x = x+xxwin;
-
}
-
}
-
}
-
if(maxValue > threshold)
-
{
-
cvSeqPush(corners, &resultLoc);
-
cornersCount ++;
-
}
-
x += winSize;
-
}
-
y += winSize;
-
-
}
-
cvReleaseImage(&diffDst);
-
return cornersCount;
-
}
-
int main()
-
{
-
IplImage *src = cvLoadImage("E:\\study_opencv_video\\lesson17_1\\1.bmp", 0);
-
if(!src)
-
{
-
cout << "No Image loading..." << endl;
-
return 0;
-
}
-
CvSeq *corners;
-
CvMemStorage *mem = cvCreateMemStorage(0);
-
corners = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvPoint), mem);
-
float threshold =30000;
-
-
int cornersCount = getMoravec(src, corners, threshold);
-
-
-
IplImage* show= cvCreateImage(cvGetSize(src),8,3);
-
cvCvtColor(src,show,CV_GRAY2BGR);
-
-
-
-
for(int i = 0; i < cornersCount; i++)
-
{
-
-
CvPoint *pt = (CvPoint *)cvGetSeqElem(corners, i);
-
cvCircle(show, *pt, 5, cvScalar(0,0,255));
-
}
-
cvNamedWindow("show");
-
cvShowImage("show", show);
-
cvWaitKey(0);
-
cvReleaseImage(&src);
-
cvReleaseImage(&show);
-
cvReleaseMemStorage(&mem);
-
cvDestroyWindow("show");
-
return 0;
-
-
-
-
}
Effect:

Added: Simply explain the cvSeq and cvMemStorage in the code. I am not too familiar with them. I took notes of them.
-
CvMemStorage *mem = cvCreateMemStorage(0);
-
CvSeq*corners = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvPoint), mem);
-
cvSeqPush(corners, &resultLoc);
-
CvPoint *pt = (CvPoint *)cvGetSeqElem(corners, i);
-
cvReleaseMemStorage(&mem);
-
cvSeqSort(corners,cmpFunc,0);
-
-
static int cmpFunc(const void* _cur , const void* _next , void* userdata)
-
{
-
PHARRISPOINT cur = (PHARRISPOINT)_cur;
-
PHARRISPOINT next = (PHARRISPOINT)_next;
-
-
return cur->cornerness < next->cornerness ? 1 : -1;
-
}
(4) Disadvantage of Moravec corner detection
moravec corner detection has two main shortcomings:
1. No rotation invariance
2. Strong response to edge points
Author: Villager from: http://blog.csdn.net/lu597203933 Reprint or share are welcome, but be sure to state the source of the article. (Sina Weibo: small village leader zack, welcome to exchange!)