1、
前两天分别使用了SIFT、SURF、ORB实现特征匹配,这三种方法SURF方法效果较优,但是比较耗时,使用Harris方法进行改进测试,效果和SURF方法可以向媲美,并且测试用一幅图像,匹配时间提高了接近3/4,由时间1000ms多提速到250ms左右。
2、在Opencv中有三种方法实现:
1>
opencv自带的函数检测角点特征,其检测效果与k值有关,需要经验设置;
2>
改进后的角点检测,受k值影响不大;
3>
使用fastDetector方法,此方法检测速度快,匹配效果好。
如下列代码实现,三种方法,分别通过设置nMethod方法实现:
int nMethod = 2;
if (nMethod ==
0)
//
使用opencv自带的函数检测,检测角点数与k值有关
{
// opencv自带的角点响应函数计算
Mat matCornerStrength; // opencv函数检测结果,也就是每个像素的角点响应函数值
int nBlockSize = 3,
nKSize =
3;
double dK =
0.01;
cv::cornerHarris(matSrc,
matCornerStrength,
nBlockSize,
nKSize,
dK);
//
计算最小最大响应值
double dMinStrength =
0.0, dMaxStrength =
0.0;
cv::minMaxLoc(matCornerStrength,
&dMinStrength,
&dMaxStrength);
//
默认3*3核膨胀,膨胀之后,除了局部最大值点和原来相同,其他非局部最大值点
//
被3*3邻域内的最大值点取代
Mat matDilated;
Mat matKernel =
Mat();
//
最大值抑制的核,也就是膨胀用到的核
cv::dilate(matCornerStrength,
matDilated,
matKernel);
//
和原图相比,只剩下和原图值相同的点,这些点都是局部最大值点,保存到matLocalMax
Mat matLocalMax;
//
局部最大值结果
cv::compare(matCornerStrength,
matDilated,
matLocalMax,
cv::CMP_EQ);
double dQulityLevel =
0.1;
//
根据角点响应最大值计算阈值
double dThreshold =
dQulityLevel *
dMaxStrength;
Mat matCornerTh;
// matCornerStrength阈值化后的结果
cv::threshold(matCornerStrength,
matCornerTh,
dThreshold,
255, cv::THRESH_BINARY);
//
转化为8bit图
Mat matCornerMap;
matCornerTh.convertTo(matCornerMap,
CV_8U);
//
和局部最大值图比,剩下角点局部最大值图,即:完成非最大值抑制
cv::bitwise_and(matCornerMap,
matLocalMax,
matCornerMap);
//
获取角点,遍历全图
std::vector<</span>Point2f>
vtPoints;
for (int y = 0;
y <
matCornerMap.rows;
y++)
{
const uchar *pRowPtr =
matCornerMap.ptr<</span>uchar>(y);
for (int x = 0;
x <
matCornerMap.cols;
x++)
{
if (pRowPtr[x])
{
vtPoints.push_back(cv::Point2f(x,
y));
}
}
}
cv::KeyPoint::convert(vtPoints,
vtCorners, 1, 1, 0,
-1);
}
else if(nMethod ==
1)
//
改进的harris方法
{
//
直接计算两个特征值,通过比较两个特征值进行分类,不在使用极大值抑制的方法
//
选取容忍距离:容忍距离内只有一个特征点
//
首先选取一个具有最大最小特征值的点(即:max(min(e1,
e2)), e1、e2是harris矩阵的特征值)作为角点
//
然后依次按照最大最小特征值顺序寻找余下的角点,当然和前一角点距离在容忍距离内的新角点被忽略
int nMaxNum =
200; //
角点最大数目
double dQuality =
0.01; //
质量等级,这里是0.01*max(min(e1,
e2)),e1、e2是harris矩阵的特征值
double dMinDistance =
10;
//
两个角点之间的容忍度
int nBlockSize =
3;
double dK =
0.04;
std::vector<</span>Point2f>
vtPoints;
cv::goodFeaturesToTrack(matSrc,
vtPoints,
nMaxNum,
dQuality,
dMinDistance,
Mat(),
nBlockSize,
false,
dK);
cv::KeyPoint::convert(vtPoints,
vtCorners, 1, 1, 0,
-1);
}
else if (nMethod ==
2)
// fast Harris方法
{
//
原理:若像素点圆形领域圆周上有3/4的点和该像素点不同(编程时不超过某阈值th),则认为该点就是候选角点
// opencv内选用半径为3的圆周上(上下左右)四个点,若超过三个点和该像素点不同,则该点为候选角点
//
该算法需要非极大值抑制
int nThreshold =
20;
cv::Ptr<</span>Feature2D>
fastDetector =
cv::FastFeatureDetector::create(nThreshold,
true);
fastDetector->detect(matSrc,
vtCorners);
}
3、结果测试,分别包括时间和特征点匹配效果,FastFeatrueDetctor效果较好,时间较短,暂时选择此特征匹配方法:
http://s12/mw690/003eu7RDzy79n1CpDB14b&690
http://s10/mw690/003eu7RDzy79n1CvZrz29&690
http://s15/mw690/003eu7RDzy79n1CCTmu9e&690
http://s5/mw690/003eu7RDzy79n1CFQoI04&690
http://s10/mw690/003eu7RDzy79n1V47K9d9&690
http://s15/mw690/003eu7RDzy79n1V6C9o5e&690
加载中,请稍候......