OpenCV:使用ORB算法比较多张图片

8
我正在尝试创建一个C++程序,其中有很多图像在列表中与一个输入图像进行比较。我已经将整个程序工作起来,并且程序正在创建DMatch匹配项。
现在我正在尝试确定与源图像相比的图像列表中哪个是最佳匹配。我首先尝试只比较图像之间有多少匹配项来完成这个任务,但问题是当生成的图像具有很多关键点时,它们也倾向于有很多匹配项,至少在我的程序中是这样。
那么我该如何确定数组中哪个图像是与源图像最匹配的?我正在使用此循环来确定匹配项,但它并不真正起作用:
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);

如果有人可以指导我要使用哪些函数或逻辑,我将不胜感激!


这也是我首先想到的事情,但当我尝试时,没有得到任何准确的结果。 - tversteeg
自此贴以来,您是否找到了可接受的解决方案?我对解决方案非常感兴趣,因为我有一个类似的问题需要快速解决。 - Spawnrider
不是很好,我确实让它工作了,但对于多个图像来说速度非常慢,而且无法很好地扩展。因此,我选择使用第三方解决方案。 - tversteeg
第三方解决方案是什么意思?您能告诉我一个解决方案的名称吗? - Spawnrider
我使用了来自骁龙的Vuforia,他们提供了一个服务,使用他们自己的服务器进行IR。 - tversteeg
显示剩余2条评论
4个回答

1

这取决于列表中的图像是什么。你不能为世界上的每个视觉问题都有一个解决方案。例如,我所在的项目需要识别墙壁图片中的材料。你不能只是将其与不同材料的不同墙壁图片进行比较,并希望得到匹配。

在我的情况下,我需要创建描述符。描述符是一种算法,可以输出可与另一张图片的值进行比较的值。在openCV中已经有很多可用的描述符,如LBP、SURF等。简单来说,你不再比较图像,而是比较图像1的描述符的输出值与列表中所有图像的描述符值。

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

因此,总结一下,没有一种万能的方法可以解决所有视觉问题。你需要根据问题调整你的解决方案。

希望对你有所帮助!


1

没有简单的答案。为了获得更好的结果,您需要实现某种转换并在转换后的地图上进行聚类,而不仅仅是将距离相加。这很困难,甚至可以 发表

否则,您将需要使用更实用的技术,如维度和直方图过滤。您可以查看OpenCV的 拼接器,分离您感兴趣的模块,并根据需要自定义源代码。


0

链接已失效。 - Sabito stands with Ukraine

0

我为您的问题进行了简短的搜索,发现在opencv答案部分有以下条目:

/CV Answer forum

看起来这似乎提供了您所遇到问题的答案。如答案建议的那样,为了过滤您获得的结果,我建议查看RANSAC算法,以在匹配选择中找到最佳结果。

RANSAC desctiption Wikipedia

至少这应该能为您指明正确的方向。


如果您查看我的代码,您会发现我已经在使用RANSAC了。 - tversteeg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接