2013-03-04 114 views
6

我想创建一个C++程序,其中有一个列表中的图像与一个输入图像相比有很多图像。我得到了整个事情的工作,该计划正在创建DMatch比赛。OpenCV:使用ORB比较多个图像

现在我正在尝试确定与源图像比较的图像列表中的哪一个是最匹配的。我首先试图通过比较图像之间的哪些匹配来做到这一点,但问题是当生成的图像有很多关键点时;他们也往往有很多比赛,至少在我的计划中。

那么如何确定哪个图像阵列与源图像最匹配呢?我使用这个循环,以确定比赛,但它并没有真正的工作:

vector< vector<DMatch> > filteredMatches; 
vector<int> goodIds; 
Ptr<DescriptorMatcher> matcher(new BFMatcher(NORM_HAMMING, false)); 

printf("bad matches: "); 

for(size_t i = 0; i < images.size();i++){ 
    vector<DMatch> matches, good_matches; 

    matcher->clear(); 
    matcher->match(images[i], tex_des, matches); 
    if(matches.size() < 8){ 
     printf("F%d,", (int)i + 1); 
     continue; 
    } 

    double min_dist = 100; 

    for(size_t j = 0; j < matches.size(); j++){ 
     double dist = matches[j].distance; 
     if(dist < min_dist) 
      min_dist = dist; 
    } 

    if(min_dist > 50.0){ 
     printf("D%d,", (int)i + 1); 
     continue; 
    } 

    double good_dist = min_dist * 3; 
    for(size_t j = 0; j < matches.size(); j++){ 
     if(matches[j].distance < good_dist) 
      good_matches.push_back(matches[j]); 
    } 

    size_t size = good_matches.size(); 
    if(size < 8){ 
     printf("M%d,", (int)i + 1); 
     continue; 
    } 

    vector<Point2f> srcPoints(size); 
    vector<Point2f> dstPoints(size); 

    for(size_t j = 0; j < size; j++){ 
     srcPoints[j] = destination[good_matches[j].trainIdx].pt;  
     dstPoints[j] = keyPoints[i][good_matches[j].queryIdx].pt; 
    } 

    vector<unsigned char> inliersMask(srcPoints.size()); 
    Mat H = findHomography(srcPoints, dstPoints, CV_FM_RANSAC, 3.0, inliersMask); 

    vector<DMatch> inliers; 
    for(size_t j = 0; j < inliersMask.size(); j++){ 
     if(inliersMask[j]){ 
      inliers.push_back(good_matches[j]); 
     } 
    } 
    if(inliers.size() < 4){ 
     printf("S%d,", (int)i + 1); 
     continue; 
    } 

    filteredMatches.push_back(inliers); 
    goodIds.push_back((int)i); 

    H.release(); 
} 

printf(" good matches: "); 

int best = -1; 
int amount = 0; 
for(size_t i = 0; i < filteredMatches.size(); i++){ 
    int size = (int)filteredMatches.at(i).size(); 
    if(size < 8) continue; 

    printf("%d,", goodIds[i] + 1); 

    if(amount < size){ 
     amount = size; 
     best = i; 
    } 
} 

if(best >= 0) printf(" best match on image: %d, keypoints: %d, ", goodIds[best] + 1, amount); 

如果有人能指点功能或逻辑我必须用我将不胜感激!

+0

说“与最内层的匹配是我最好的搭配”有什么问题? – 2013-03-08 14:38:24

+0

这也是我想到的第一件事,但是当我尝试它时,我没有得到任何准确的结果。 – tversteeg 2013-03-08 14:40:17

+0

好的,所以图片(甚至是假的)与我猜的很相似。如果您取所有比赛或所有比赛的平均距离,准确度如何?你可以发布图片失败的例子吗? – 2013-03-08 15:03:16

回答

0

您的问题很短的搜索提供我按照OpenCV的答案部分条目:

/CV Answer forum

这似乎答案提供给您的问题似乎是有。要按照答案中的建议筛选结果,我会看看RANSAC算法,以便在匹配选择中找到最佳结果。

RANSAC desctiption Wikipedia

至少这应该指向你在正确的方向。

+0

如果你看看我的代码,你可以看到我已经在使用RANSAC。 – tversteeg 2013-03-12 08:05:14

0

这取决于列表中的图像是什么。对于世界上的每一个视力问题,你都不能有一个解决方案。例如,我工作的项目需要识别墙上照片中的材料。你不能用不同的材料将它与不同的墙面图片进行比较,并希望得到一个匹配。

在我的情况下,我需要创建描述符。 Descriptors是可以与其他图片的其他值进行比较的输出值的算法。 OpenCV中已经有很多描述符可用,如LBP,SURF等。简而言之,您不再比较图像,将图像1的描述符的输出值与所有图像的描述符值进行比较图像在列表中。

您需要拿起您的眼睛/大脑用于在现实生活中找到匹配的描述符。例如,如果匹配是基于颜色的,则可以使用CLD或DCD。如果匹配基于纹理,则使用LBP。您也可以像我在我的项目中那样做,并使用大量描述符,并使用机器学习与训练有素的数据算法来找到最佳匹配。

因此,总而言之,没有银弹可以解决所有视力问题。您需要根据问题调整解决方案。

希望它能帮助!

1

没有任何直接的答案。为了获得更好的结果,你必须实现某种变换,并对变换后的地图进行聚类,而不是仅仅总结距离。这很难,甚至publishable

否则,你将不得不使用更实用的技术,如尺寸和直方图过滤。你可以看看OpenCV的stitcher,隔离你感兴趣的模块,并根据你的需要定制源代码。