Computer Vision Discussion Group 162501053 reprinted Please note: http://blog.csdn.net/abcd1992719g/article/details/26824529
Income in the bag
- Use OpenCV connerHarris for Corner Detection
- Implement the Harris algorithm by yourself
Below is a self-implemented
Because the threshold value is relatively high, it is not found around the house
Before that, we talked about edge detection. The basic principle of edge detection is that the gradient in the x or y direction changes greatly, that is, the gradient changes greatly in both directions.
Left 1, smooth area, no edge and corner points, window moving in any direction is not changed left 2, Edge Area, moving in the edge direction is not changed left 3, corner area, significant changes have taken place in any direction.
Below we define
E(U,V) = Sigma (X,Y)W[I(X+U,Y+V) −I(X,Y)] 2 (w is our window, and [u, v] is our shift, that is, moving)
We want to know how tiny moves affect E.
So we started the first-order Taylor of I.
I(X+U,Y+V) =I(X,Y) +IXU+IYV+ Higherorder terms
≈I(X,Y) +IXU+IYV
=I(X,Y) + [Ix Iy] [U v] T
Then, use the following formula.
E(U,V) = Σ [I(X+U,Y+V) −I(X,Y)] 2 (X,Y)W
We get
Therefore, we can write
M is a second-order moment matrix, which can be obtained by the difference of the original image.
Let's imagine that if the gradient is in the direction of x or y, that is, Ix = 0 or Iy = 0, then our M is
If a or B is very close to 0, that is to say they are very small, then this is not a corner point. The corner points a and B must be very large.
We found that E is a quadratic curve about U and V, so that E (u, v) = CONST, then E is an elliptic and M, the right corner of the matrix can be written in the format on the left. We can get two feature values.
The short axis of a long axis is determined by the feature value, and the elliptical direction is determined by the matrix R. R is not used in the following, so you can ignore it.
Here, our feature values come in handy. When the two feature values are very similar, it means that my elliptic is very small, and the entire E changes dramatically, then I found my corner. The formula given by Harris is as follows:
So many people are struggling with how to calculate.
det = Ix2*Iy2 - Ixy^2trace = Ix2 + Iy2
[There is another empirical formula. My own implementation adopts this one]
Having said so many theories, it is actually not that difficult to implement. Let's take a look at the steps of the algorithm.
1. Use the sobel operator to calculate the horizontal and vertical gradients respectively.
-1 0 1
-2 0 2
-1 0 1
-1-2-1
0 0 0
1 2 1
2. Calculate the second-order Gaussian matrix, that is, all the difference and
3. Calculate the response function R
4. Set the threshold value
5. Determine whether the response function R of This vertex is the largest in the circle if it is non-maximum suppression.
It should be emphasized that harris only has partial immutations on the affine transformation. Translation and rotation have covariant, but scaling does not, such
First-profile API
-
C ++: Void CornerHarris (InputArray
Src, OutputArray
Dst, Int
BlockSize, Int
Ksize, Double
K, Int
BorderType= BORDER_DEFAULT )
-
|
- Src-8-bit or floating point matrix.
- Dst-Stores the harris response function. The type isCV_32FC1 because the calculated value is large,Size andSame as src.
- BlockSize-Window size.
- Ksize-Sobel operator size.
- K-Generally 0.04-0.06.
- BorderType.
|
Calculate the covariance matrix for each pixel over a neighborhood. The harris response function is used.
Below is the official sample, which I will not explain much. It is purely an API call. Note that after the response function is obtained, it is normalized to [0,255].
#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 variablesMat src, src_gray;int thresh = 200;int max_thresh = 255;char* source_window = "Source image";char* corners_window = "Corners detected";/// Function headervoid 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 );}
The following is my own implementation. I found a lot of places and did not find others' source code...
# Include "opencv2/highgui. hpp "# include" opencv2/imgproc. hpp "# include <cmath> # include <iostream> using namespace cv; Mat harris (Mat & im, double sigma, int thresh, int radius) {Mat dx, dy, Ix, iy, Ix2, Iy2, Ixy, cim; Sobel (im, Ix, CV_64F, 1, 0, 3); // algorithm Step 1: Calculate the horizontal vertical differential Sobel (im, iy, CV_64F, 0, 1, 3); int ksize = max (1, (int) (6 * sigma); if (ksize % 2 = 0) ksize ++; GaussianBlur (Ix. mul (Ix), Ix2, Size (ksize, ksize), sigma); // the second step of the algorithm is to calculate the second-order Gaussian difference matrix GaussianBlur (Iy. mul (Iy), Iy2, Size (ksize, ksize), sigma); GaussianBlur (Ix. mul (Iy), Ixy, Size (ksize, ksize), sigma); // Harris corner measure // cim = (Ix2. * Iy2-Ixy. ^ 2 ). /(Ix2 + Iy2); cim = (Ix2.mul (Iy2)-Ixy. mul (Ixy)/(Ix2 + Iy2); // step 3 of the algorithm, calculate the response function. I used another Mat structedElement (radius, radius, CV_8U, scalar (1); Mat mx, norm_cim; normalize (cim, norm_cim, 0,255, NORM_MINMAX, CV_8U, Mat (); dilate (norm_cim, mx, structedElement ); norm_cim = (norm_cim = mx) & (norm_cim> thresh); // algorithm 4th step 1 fusion, non-maximum suppression and Threshold Detection return norm_cim;} int main (int, char ** argv) {Mat src, gray; src = imread (argv [1]); cvtColor (src, gray, CV_RGB2GRAY); Mat corners = harris (gray, 1.5, 30, 2); for (int j = 0; j <corners. rows; j ++) {for (int I = 0; I <corners. cols; I ++) {if (corners. at <unsigned char> (j, I)> 0) {circle (gray, Point (I, j), 3, Scalar (0), 2, 8, 0) ;}} namedWindow ("result", 1); imshow ("result", gray); waitKey (); return 0 ;}
Additional benefits harris matlab version http://www.cs.illinois.edu /~ Slazebni/spring13/harris. mharris python version http://www.janeriksolem.net/2009/01/harris-corner-detector-in-python.html