In this tutorial you will learn:
To mention a few:
In this tutorial we will study the corner features, specifically.
Let’s look for corners. Since corners represents a variation in the gradient in the image, we will look for this “variation”.
Consider a grayscale image  . We are going to sweep a window
. We are going to sweep a window  (with displacements
 (with displacements  in the x direction and
 in the x direction and  in the right direction)
 in the right direction)  and will calculate the variation of intensity.
 and will calculate the variation of intensity.
![E(u,v) = \sum _{x,y} w(x,y)[ I(x+u,y+v) - I(x,y)]^{2}](../../../../../_images/math/64298b2668229d15649e5042e90af81a629ab075.png)
where:
 is the window at position
 is the window at position 
 is the intensity at
 is the intensity at 
 is the intensity at the moved window
 is the intensity at the moved window 
Since we are looking for windows with corners, we are looking for windows with a large variation in intensity. Hence, we have to maximize the equation above, specifically the term:
![\sum _{x,y}[ I(x+u,y+v) - I(x,y)]^{2}](../../../../../_images/math/710a44e744b7529f26b0f3695ad3d56bfaf61a90.png)
Using Taylor expansion:
![E(u,v) \approx \sum _{x,y}[ I(x,y) + u I_{x} + vI_{y} - I(x,y)]^{2}](../../../../../_images/math/610201413953d93b59b2983f1756611e7957cf04.png)
Expanding the equation and cancelling properly:

Which can be expressed in a matrix form as:

Let’s denote:

So, our equation now is:

A score is calculated for each window, to determine if it can possibly contain a corner:

where:


a window with a score  greater than a certain value is considered a “corner”
 greater than a certain value is considered a “corner”
This tutorial code’s is shown lines below. You can also download it from here
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
/// Global variables
Mat src, src_gray;
int thresh = 200;
int max_thresh = 255;
char* source_window = "Source image";
char* corners_window = "Corners detected";
/// Function header
void cornerHarris_demo( int, void* );
/** @function main */
int main( int argc, char** argv )
{
  /// Load source image and convert it to gray
  src = imread( argv[1], 1 );
  cvtColor( src, src_gray, CV_BGR2GRAY );
  /// Create a window and a trackbar
  namedWindow( source_window, CV_WINDOW_AUTOSIZE );
  createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo );
  imshow( source_window, src );
  cornerHarris_demo( 0, 0 );
  waitKey(0);
  return(0);
}
/** @function cornerHarris_demo */
void cornerHarris_demo( int, void* )
{
  Mat dst, dst_norm, dst_norm_scaled;
  dst = Mat::zeros( src.size(), CV_32FC1 );
  /// Detector parameters
  int blockSize = 2;
  int apertureSize = 3;
  double k = 0.04;
  /// Detecting corners
  cornerHarris( src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT );
  /// Normalizing
  normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );
  convertScaleAbs( dst_norm, dst_norm_scaled );
  /// Drawing a circle around corners
  for( int j = 0; j < dst_norm.rows ; j++ )
     { for( int i = 0; i < dst_norm.cols; i++ )
          {
            if( (int) dst_norm.at<float>(j,i) > thresh )
              {
               circle( dst_norm_scaled, Point( i, j ), 5,  Scalar(0), 2, 8, 0 );
              }
          }
     }
  /// Showing the result
  namedWindow( corners_window, CV_WINDOW_AUTOSIZE );
  imshow( corners_window, dst_norm_scaled );
}