OpenCV
Open Source Computer Vision
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Creating your own corner detector

Table of Contents

Prev Tutorial: Shi-Tomasi corner detector
Next Tutorial: Detecting corners location in subpixels

Original author Ana Huamán
Compatibility OpenCV >= 3.0

Goal

In this tutorial you will learn how to:

  • Use the OpenCV function cv::cornerEigenValsAndVecs to find the eigenvalues and eigenvectors to determine if a pixel is a corner.
  • Use the OpenCV function cv::cornerMinEigenVal to find the minimum eigenvalues for corner detection.
  • Implement our own version of the Harris detector as well as the Shi-Tomasi detector, by using the two functions above.

Theory

Code

This tutorial code's is shown lines below. You can also download it from here

#include <iostream>
using namespace cv;
using namespace std;
Mat src, src_gray;
Mat myHarris_dst, myHarris_copy, Mc;
Mat myShiTomasi_dst, myShiTomasi_copy;
int myShiTomasi_qualityLevel = 50;
int myHarris_qualityLevel = 50;
int max_qualityLevel = 100;
double myHarris_minVal, myHarris_maxVal;
double myShiTomasi_minVal, myShiTomasi_maxVal;
RNG rng(12345);
const char* myHarris_window = "My Harris corner detector";
const char* myShiTomasi_window = "My Shi Tomasi corner detector";
void myShiTomasi_function( int, void* );
void myHarris_function( int, void* );
int main( int argc, char** argv )
{
CommandLineParser parser( argc, argv, "{@input | building.jpg | input image}" );
src = imread( samples::findFile( parser.get<String>( "@input" ) ) );
if ( src.empty() )
{
cout << "Could not open or find the image!\n" << endl;
cout << "Usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
cvtColor( src, src_gray, COLOR_BGR2GRAY );
int blockSize = 3, apertureSize = 3;
cornerEigenValsAndVecs( src_gray, myHarris_dst, blockSize, apertureSize );
/* calculate Mc */
Mc = Mat( src_gray.size(), CV_32FC1 );
for( int i = 0; i < src_gray.rows; i++ )
{
for( int j = 0; j < src_gray.cols; j++ )
{
float lambda_1 = myHarris_dst.at<Vec6f>(i, j)[0];
float lambda_2 = myHarris_dst.at<Vec6f>(i, j)[1];
Mc.at<float>(i, j) = lambda_1*lambda_2 - 0.04f*((lambda_1 + lambda_2) * (lambda_1 + lambda_2));
}
}
minMaxLoc( Mc, &myHarris_minVal, &myHarris_maxVal );
/* Create Window and Trackbar */
namedWindow( myHarris_window );
createTrackbar( "Quality Level:", myHarris_window, &myHarris_qualityLevel, max_qualityLevel, myHarris_function );
myHarris_function( 0, 0 );
cornerMinEigenVal( src_gray, myShiTomasi_dst, blockSize, apertureSize );
minMaxLoc( myShiTomasi_dst, &myShiTomasi_minVal, &myShiTomasi_maxVal );
/* Create Window and Trackbar */
namedWindow( myShiTomasi_window );
createTrackbar( "Quality Level:", myShiTomasi_window, &myShiTomasi_qualityLevel, max_qualityLevel, myShiTomasi_function );
myShiTomasi_function( 0, 0 );
waitKey();
return 0;
}
void myShiTomasi_function( int, void* )
{
myShiTomasi_copy = src.clone();
myShiTomasi_qualityLevel = MAX(myShiTomasi_qualityLevel, 1);
for( int i = 0; i < src_gray.rows; i++ )
{
for( int j = 0; j < src_gray.cols; j++ )
{
if( myShiTomasi_dst.at<float>(i,j) > myShiTomasi_minVal + ( myShiTomasi_maxVal - myShiTomasi_minVal )*myShiTomasi_qualityLevel/max_qualityLevel )
{
circle( myShiTomasi_copy, Point(j,i), 4, Scalar( rng.uniform(0,256), rng.uniform(0,256), rng.uniform(0,256) ), FILLED );
}
}
}
imshow( myShiTomasi_window, myShiTomasi_copy );
}
void myHarris_function( int, void* )
{
myHarris_copy = src.clone();
myHarris_qualityLevel = MAX(myHarris_qualityLevel, 1);
for( int i = 0; i < src_gray.rows; i++ )
{
for( int j = 0; j < src_gray.cols; j++ )
{
if( Mc.at<float>(i,j) > myHarris_minVal + ( myHarris_maxVal - myHarris_minVal )*myHarris_qualityLevel/max_qualityLevel )
{
circle( myHarris_copy, Point(j,i), 4, Scalar( rng.uniform(0,256), rng.uniform(0,256), rng.uniform(0,256) ), FILLED );
}
}
}
imshow( myHarris_window, myHarris_copy );
}
Designed for command line parsing.
Definition utility.hpp:890
n-dimensional dense array class
Definition mat.hpp:829
CV_NODISCARD_STD Mat clone() const
Creates a full copy of the array and the underlying data.
MatSize size
Definition mat.hpp:2177
_Tp & at(int i0=0)
Returns a reference to the specified array element.
int cols
Definition mat.hpp:2155
bool empty() const
Returns true if the array has no elements.
int rows
the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
Definition mat.hpp:2155
Random Number Generator.
Definition core.hpp:2874
Template class for short numerical vectors, a partial case of Matx.
Definition matx.hpp:369
std::string String
Definition cvstd.hpp:151
#define CV_32FC1
Definition interface.h:118
#define MAX(a, b)
Definition cvdef.h:518
@ circle
Definition gr_skig.hpp:62
void imshow(const String &winname, InputArray mat)
Displays an image in the specified window.
int main(int argc, char *argv[])
Definition highgui_qt.cpp:3
Definition core.hpp:107
STL namespace.

Explanation

Result