我想识别用于构建乐高分拣机的乐高积木(我使用带有opencv的c ++)。 这意味着我必须区分看起来非常相似的对象。
砖块在平板输送机上单独进入我的相机。但它们可能以任何可能的方式存在:颠倒,侧面或“正常”。
我的方法是通过用相机拍摄许多不同的位置和旋转来教给分拣机砖。每个视图的特征都是由surf-algorythm计算的。
void calculateFeatures(const cv::Mat& image,
std::vector<cv::KeyPoint>& keypoints,
cv::Mat& descriptors)
{
// detector == cv::SurfFeatureDetector(10)
detector->detect(image,keypoints);
// extractor == cv::SurfDescriptorExtractor()
extractor->compute(image,keypoints,descriptors);
}
如果有一块未知的砖块(我想要排序的砖块),它的特征也会被计算出来并与已知的砖块相匹配。 为了找到错误匹配的功能,我按照OpenCV 2 Cookbook:
一书中的描述进行操作使用匹配器(= cv :: BFMatcher(cv :: NORM_L2))搜索两个方向上的两个最近邻居
matcher.knnMatch(descriptorsImage1, descriptorsImage2,
matches1,
2);
matcher.knnMatch(descriptorsImage2, descriptorsImage1,
matches2,
2);
我检查找到的最近邻居的距离之间的比率。如果两个距离非常相似,则可能使用假值。
// loop for matches1 and matches2
for(iterator matchIterator over all matches)
if( ((*matchIterator)[0].distance / (*matchIterator)[1].distance) > 0.65 )
throw away
最后只接受对称匹配对。这些匹配不仅n1是特征f1的最近邻居,而且f1是与n1最近的邻居。
for(iterator matchIterator1 over all matches)
for(iterator matchIterator2 over all matches)
if ((*matchIterator1)[0].queryIdx == (*matchIterator2)[0].trainIdx &&
(*matchIterator2)[0].queryIdx == (*matchIterator1)[0].trainIdx)
// good Match
现在只剩下相当不错的比赛。为了过滤掉一些更糟糕的匹配,我使用基本矩阵检查哪些匹配符合img1在img2上的投影。
std::vector<uchar> inliers(points1.size(),0);
cv::findFundamentalMat(
cv::Mat(points1),cv::Mat(points2), // matching points
inliers,
CV_FM_RANSAC,
3,
0.99);
std::vector<cv::DMatch> goodMatches
// extract the surviving (inliers) matches
std::vector<uchar>::const_iterator itIn= inliers.begin();
std::vector<cv::DMatch>::const_iterator itM= allMatches.begin();
// for all matches
for ( ;itIn!= inliers.end(); ++itIn, ++itM)
if (*itIn)
// it is a valid match
结果非常好。但在极端相似的情况下,仍然会发生故障 在上面的图片中,您可以看到类似的砖被很好地识别出来。
然而,在第二张图片中,同样可以识别错误的砖块。
现在问题是如何改善匹配。
我有两个不同的想法:
第二张图片中的匹配追溯到非常合适的特征,但前提是视野强烈变化。要识别砖块,我必须在许多不同的位置比较它(至少如图3所示)。这意味着我知道我只允许最低限度地改变视野。视野变化的强度应该隐藏在基本矩阵中。如何从这个矩阵中读出房间中的位置变化了多远?特别是旋转和强缩放应该是有意义的;如果砖块一旦贴在左侧,那就无所谓了。
第二个想法:
我从2张图片中计算了基本矩阵,并滤除了不适合投影的特征 - 不应该有办法使用三张或更多图片做同样的事情吗? (关键词Trifocal tensor)。这样匹配应该变得更加稳定。但我不知道如何使用OpenCV这样做,也不能在谷歌上找到任何相关信息。
答案 0 :(得分:2)
我没有完整的答案,但我有一些建议。
在图像分析方面:
这些更简单的功能将为您提供合理的第一个过滤器,以限制您的搜索空间。
机械方面:
这两点都会限制您的搜索空间。