在OpenCV中,函数cvGoodFeaturesToTrack()采用了Shi和Tomasi提出的方法,先利用sobel算子计算二阶导数,再计算特征值,它返回满足易于跟踪的一系列角点。函数定义如下:
GoodFeaturesToTrack
确定图像的强角点
void cvGoodFeaturesToTrack( const CvArr* image, CvArr* eig_image, CvArr* temp_image,
CvPoint2D32f* corners, int* corner_count,
double quality_level, double min_distance,
const CvArr* mask=NULL );
image
输入图像,8-位或浮点32-比特,单通道
eig_image
临时浮点32-位图像,尺寸与输入图像一致
temp_image
另外一个临时图像,格式与尺寸与 eig_image 一致
corners
输出参数,检测到的角点
corner_count
输出参数,检测到的角点数目
quality_level
最大最小特征值的乘法因子。定义可接受图像角点的最小质量因子。
min_distance
限制因子。得到的角点的最小距离。使用 Euclidian 距离
mask
ROI:感兴趣区域。函数在ROI中计算角点,如果 mask 为 NULL,则选择整个图像。 必须为单通道的灰度图,大小与输入图像相同。mask对应的点不为0,表示计算该点。
函数 cvGoodFeaturesToTrack 在图像中寻找具有大特征值的角点。该函数,首先用cvCornerMinEigenVal 计算输入图像的每一个象素点的最小特征值,并将结果存储到变量 eig_image 中。然后进行非最大值抑制(仅保留3x3邻域中的局部最大值)。下一步将最小特征值小于 quality_level•max(eig_image(x,y)) 排除掉。最后,函数确保所有发现的角点之间具有足够的距离,(最强的角点第一个保留,然后检查新的角点与已有角点之间的距离大于 min_distance )。
例子如下:
#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 maxCorners = 23; int maxTrackbar = 100; RNG rng(12345); char* source_window = "Image"; /// Function header void goodFeaturesToTrack_Demo( int, void* ); /** * @function main */ int main( int argc, char** argv ) { /// Load source image and convert it to gray src = imread( "1.jpg", 1 ); cvtColor( src, src_gray, CV_BGR2GRAY ); /// Create Window namedWindow( source_window, CV_WINDOW_AUTOSIZE ); /// Create Trackbar to set the number of corners createTrackbar( "Max corners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo ); imshow( source_window, src ); goodFeaturesToTrack_Demo( 0, 0 ); waitKey(0); return(0); } /** * @function goodFeaturesToTrack_Demo.cpp * @brief Apply Shi-Tomasi corner detector */ void goodFeaturesToTrack_Demo( int, void* ) { if( maxCorners < 1 ) { maxCorners = 1; } /// Parameters for Shi-Tomasi algorithm vector<Point2f> corners; double qualityLevel = 0.01; double minDistance = 10; int blockSize = 3; bool useHarrisDetector = false; double k = 0.04; /// Copy the source image Mat copy; copy = src.clone(); /// Apply corner detection goodFeaturesToTrack( src_gray, corners, maxCorners, qualityLevel, minDistance, Mat(), blockSize, useHarrisDetector, k ); /// Draw corners detected cout<<"** Number of corners detected: "<<corners.size()<<endl; int r = 4; for( int i = 0; i < corners.size(); i++ ) { circle( copy, corners[i], r, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), -1, 8, 0 ); } /// Show what you got namedWindow( source_window, CV_WINDOW_AUTOSIZE ); imshow( source_window, copy ); }