【Shi-Tomasi⾓点检测+SIFT特征匹配】OpenCVC++实现
在进⾏SIFT特征提取时,由于会提取数量较多的尺度空间特征点,会导致特征向量提取和特征点匹配环节的⽤时较长。在三维测量等应⽤条件下,⾓点是进⾏测量的关键点,因此采⽤Shi-Tomasi或Harris⾓点检测提取关键的特征点,可以减少冗余⽆效的特征点,提升运算的实时性。接下来介绍在编程时遇到的两个问题:
1.如何⽤⾓点提取结果⽣成特征描述⼦
Shi-Tomasi⾓点检测函数如下:
goodFeaturesToTrack(Left_Corner_graysrcImage,//输⼊图像
Left_Corners,//检测到的⾓点的输出向量
g_maxCornerNumber,//⾓点的最⼤数量
qualityLevel,//⾓点检测可接受的最⼩特征值
minDistance,//⾓点之间的最⼩距离
贴对联简笔画
Mat(),//感兴趣区域
blockSize,//计算导数⾃相关矩阵时指定的邻域范围
fal,//不使⽤Harris⾓点检测
k);//权重系数
可以看到⾓点提取的结果是
草满池塘水满陂vector<Point2f>
这⼀类型的动态数组,⽽SIFT特征匹配的特征点输⼊是KeyPoint类
CV_WRAP KeyPoint();
/**
@param _pt x & y coordinates of the keypoint
@param _size keypoint diameter
@param _angle keypoint orientation
新年英文祝福语@param _respon keypoint detector respon on the keypoint (that is, strength of the keypoint)
@param _octave pyramid octave in which the keypoint has been detected
@param _class_id object id
*/
因此需要进⾏转换。但是,若使⽤KeyPoint::convert()进⾏转换或直接使⽤detectandcompute()函数,转换出来的特征点仅有⼀个
Point2f类型的成员变量pt即坐标信息被输⼊,很多重要的参数,如主⽅向、尺度空间信息没有输⼊。因此⽤先detect后compute的⽅法或者使⽤⽗类Features2D下的另⼀个成员函数detectandcompute(),进⾏特征检测的结果都不具备旋转不变性,只能应⽤于双⽬对齐后的左右视图,现详细分析detectandcompute()函数:
1.1 detectandcompute()函数
函数的参数如下:
CV_WRAP virtual void detectAndCompute( InputArray image, InputArray mask,
CV_OUT std::vector<KeyPoint>& keypoints,
OutputArray descriptors,
bool uProvidedKeypoints=fal);汽车多少年报废
最后⼀个参数布尔变量uProvidedKeypoints是⽤于判定是否使⽤其他检测⽅法检测出的特征点信息进⾏输⼊,若为fal则代表使⽤SIFT特征检测的结果作为输⼊,若为true则代表采⽤外源输⼊。下⾯这⼀部分是uProvidedKeypoints为true即采⽤外源输⼊的代码:
if( uProvidedKeypoints )
{
firstOctave =0;
int maxOctave = INT_MIN;
for( size_t i =0; i < keypoints.size(); i++)
比划比划
{公司股权转让协议书
int octave, layer;
float scale;
unpackOctave(keypoints[i], octave, layer, scale);
firstOctave = std::min(firstOctave, octave);
behalf
maxOctave = std::max(maxOctave, octave);
actualNLayers = std::max(actualNLayers, layer-2);
}
firstOctave = std::min(firstOctave,0);
CV_Asrt( firstOctave >=-1&& actualNLayers <= nOctaveLayers );
actualNOctaves = maxOctave - firstOctave +1;
}
可以看到特征点位置参数在内部进⾏了赋值。(可以⾃⾏查看源代码)
因此我们也可以采⽤detectandcompute函数进⾏特征描述⼦计算。
2.如何⽤RANSCA算法剔除误匹配点
什么有礼这部分直接上代码,采⽤的是⽤findHomography函数计算单应性矩阵,然后将左图特征点单应性变换到右图上,与右图上的特征点计算误差距离。若距离⼤于⼀定阈值则剔除。
//【10】计算单应性矩阵H,⽤RANSCA剔除误匹配点
vector<Point2f> Left_Matches, Right_Matches;
int Match_Points_Num = matches.size();
for(int i =0; i < Match_Points_Num; i++)//将得到的左右匹配结果点分别存⼊动态数组
{
Left_Matches.push_back(Left_Keypoints[matches[i].queryIdx].pt);
Right_Matches.push_back(Right_Keypoints[matches[i].trainIdx].pt);
}
Mat H =findHomography(Left_Matches, Right_Matches, CV_RANSAC);
vector<char>mask(Left_Matches.size());
vector<Point2f> Left_Matches_Aftertrans;
perspectiveTransform(Left_Matches, Left_Matches_Aftertrans, H);
for(int i =0; i < Right_Matches.size(); i++)//剔除误差范数⼤于5的点
{
if(norm(Right_Matches[i]- Left_Matches_Aftertrans[i])<=5)
{
mask[i]=1;
}
}
Mat img_matches;
drawMatches(Left_Corner_srcImage, Left_Keypoints, Right_Corner_srcImage,Right_Keypoints,
matches, img_matches, Scalar::all(-1), Scalar::all(-1), mask, DrawMatchesFlags::DEFAULT);