Harris corner detector performs well in many cases, but it can still be improved. Around six years after the original paper by Harris and Stephens, Shi and Tomasi came up with something better and they called it Good Features to Track. You can read the original paper here: http://www.ai.mit.edu/courses/6.891/handouts/shi94good.pdf. They used a different scoring function to improve the overall quality. Using this method, we can find the N strongest corners in the given image. This is very useful when we don't want to use every single corner to extract information from the image. As we discussed, a good interest point detector is very useful in applications such as object tracking, object recognition, and image search.
If you apply the Shi-Tomasi corner detector to an image, you will see something like this:
As we can see here, all the important points in the frame are captured. Let's look at the code to track these features:
int main(int argc, char* argv[]) { // Variable declaration and initialization // Iterate until the user presses the Esc key while(true) { // Capture the current frame cap >> frame; // Resize the frame resize(frame, frame, Size(), scalingFactor, scalingFactor, INTER_AREA); // Convert to grayscale cvtColor(frame, frameGray, COLOR_BGR2GRAY ); // Initialize the parameters for Shi-Tomasi algorithm vector<Point2f> corners; double qualityThreshold = 0.02; double minDist = 15; int blockSize = 5; bool useHarrisDetector = false; double k = 0.07; // Clone the input frame Mat frameCopy; frameCopy = frame.clone(); // Apply corner detection goodFeaturesToTrack(frameGray, corners, numCorners, qualityThreshold, minDist, Mat(), blockSize, useHarrisDetector, k);
As we can see, we extracted the frame and used goodFeaturesToTrack to detect the corners. It's important to understand that the number of corners detected will depend on our choice of parameters. You can find a detailed explanation at http://docs.opencv.org/2.4/modules/imgproc/doc/feature_detection.html?highlight=goodfeaturestotrack#goodfeaturestotrack. Let's go ahead and draw circles on these points to display the output image:
// Parameters for the circles to display the corners int radius = 8; // radius of the circles int thickness = 2; // thickness of the circles int lineType = 8; // Draw the detected corners using circles for(size_t i = 0; i < corners.size(); i++) { Scalar color = Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)); circle(frameCopy, corners[i], radius, color, thickness, lineType, 0); } /// Show what you got imshow(windowName, frameCopy); // Get the keyboard input and check if it's 'Esc' // 27 -> ASCII value of 'Esc' key ch = waitKey(30); if (ch == 27) { break; } } // Release the video capture object cap.release(); // Close all windows destroyAllWindows(); return 1; }
This program takes an input argument: numCorners. This value indicates the maximum number of corners you want to track. Start with a value of 100 and play around with it to see what happens. If you increase this value, you will see more feature points getting detected.