打不开博主的blog,所以暂为记录

来源:互联网 发布:java的命名规范 编辑:程序博客网 时间:2024/06/06 15:43


1. 计算出descriptor:

?View Code CPP
12345
Mat img = imread(filename);cv::Feature2D *detector = new cv::OrbFeatureDetector();cv::Feature2D *extractor = new cv::OrbDescriptorExtractor();detector->detect(img, kpImg);extractor->compute(img, kpImg, descImg);

其中的detector负责提取图片中的特征点,并由extractor提取出descriptor,最终保存到descImg中。

2. 两张图片的descriptor进行对比

?View Code CPP
12345678
BruteForceMatcher< L2 > matcher;matcher.knnMatch(desc1, desc2, matches1, 2);matcher.knnMatch(desc2, desc1, matches2, 2); ratioTest(matches1);ratioTest(matches2); symmetryTest(matches1, matches2, symMatches);

首先会使用BruteForceMatcher找出两个descriptor到对方的配对点,然后使用ratioTest和SymmetryTest来剔除不靠谱的匹配特征点,也就是下面所要说的剔除匹配点的操作。

3. 剔除低质量匹配点
ratioTest用来剔除距离比例相差过大的配对点,配对点之间的距离相差越大,能匹配上的概率也就越小。这里使用一个参数ratio来控制剔除距离相差在一定范围之外的特征点。

?View Code CPP
12345678910111213141516171819202122232425
int ratioTest( VVecMatch &matches ){  float ratio = 0.8f;  int removed=0;  // for all matches  for (std::vector<std::vector>::iterator    matchIterator= matches.begin();    matchIterator!= matches.end(); ++matchIterator)   {    // if 2 NN has been identified    if (matchIterator->size() > 1)     {      // check distance ratio      if ((*matchIterator)[0].distance/        (*matchIterator)[1].distance > ratio) {          matchIterator->clear(); // remove match          removed++;      }    } else { // does not have 2 neighbours      matchIterator->clear(); // remove match      removed++;    }  }  return removed;}

symmetryTest用来判断两个图像间的特征点匹配是否是一一映射,对于不是的点则剔除掉。

?View Code CPP
123456789101112131415161718192021222324252627282930313233343536
void symmetryTest( const VVecMatch matches1,                                const VVecMatch matches2,                                VecMatch& symMatches ){  // for all matches image 1 -> image 2  for (std::vector<std::vector>::const_iterator matchIterator1= matches1.begin();    matchIterator1!= matches1.end(); ++matchIterator1)   {    // ignore deleted matches    if (matchIterator1->size() < 2)             continue;     // for all matches image 2 -> image 1    for (std::vector<std::vector>::const_iterator matchIterator2= matches2.begin();      matchIterator2!= matches2.end();      ++matchIterator2)     {      // ignore deleted matches      if (matchIterator2->size() < 2)                 continue;             // Match symmetry test      if ((*matchIterator1)[0].queryIdx ==         (*matchIterator2)[0].trainIdx &&         (*matchIterator2)[0].queryIdx ==         (*matchIterator1)[0].trainIdx)        {         // add symmetrical match         symMatches.push_back(           cv::DMatch((*matchIterator1)[0].queryIdx,           (*matchIterator1)[0].trainIdx,           (*matchIterator1)[0].distance));         break; // next match in image 1 -> image 2      }    }  }}

4. 判断是否匹配上

经过上面的特征匹配和剔除,剩下来的应该都是比较靠谱的匹配点了。如果用一个图片来和一个模板集合来进行比对,那么通过简单的比较能够匹配到的特征点数目就能够判断出是否匹配上了。

PS:对于OpenCV中的所有特征匹配算法都可以用这个办法来做,比如SIFT, SURF等等。只需要简单的替换第一步中的extractor和detector就可以了

原创粉丝点击