使用 SURF 匹配图像并确定最佳匹配

Posted

技术标签:

【中文标题】使用 SURF 匹配图像并确定最佳匹配【英文标题】:Matching image and determine best match using SURF 【发布时间】:2016-06-30 14:38:27 【问题描述】:

我一直在尝试使用 EMGU 示例 SURFFeature 来确定图像是否在图像集合中。但我无法理解如何确定是否找到匹配项。

............原始图像............场景_1(匹配).. .....................场景_2(不匹配)

....... .......

我一直在查看文档并花费数小时寻找可能的解决方案,以了解如何确定图像是否相同。 正如您在以下图片中看到的那样,两者都找到了匹配项。

很明显,我要查找的匹配项更多(连接线),但是如何在代码中检查呢?

问题:如何过滤掉好的匹配?

我的目标是能够将输入图像(从网络摄像头捕获)与数据库中的图像集合进行比较。但在将所有图像保存到数据库之前,我需要知道可以将输入与哪些值进行比较。 (例如,将 objectKeypoints 保存在 DB 中)

这是我的示例代码(匹配部分):

private void match_test()

    long matchTime;
    using (Mat modelImage = CvInvoke.Imread(@"images\input.jpg", LoadImageType.Grayscale))
    using (Mat observedImage = CvInvoke.Imread(@"images\2.jpg", LoadImageType.Grayscale))
    
        Mat result = DrawMatches.Draw(modelImage, observedImage, out matchTime);
        //ImageViewer.Show(result, String.Format("Matched using 0 in 1 milliseconds", CudaInvoke.HasCuda ? "GPU" : "CPU", matchTime));
        ib_output.Image = result;
        label7.Text = String.Format("Matched using 0 in 1 milliseconds", CudaInvoke.HasCuda ? "GPU" : "CPU", matchTime);
     


public static void FindMatch(Mat modelImage, Mat observedImage, out long matchTime, out VectorOfKeyPoint modelKeyPoints, out VectorOfKeyPoint observedKeyPoints, VectorOfVectorOfDMatch matches, out Mat mask, out Mat homography)

    int k = 2;
    double uniquenessThreshold = 0.9;
    double hessianThresh = 800;

    Stopwatch watch;
    homography = null;

    modelKeyPoints = new VectorOfKeyPoint();
    observedKeyPoints = new VectorOfKeyPoint();

    using (UMat uModelImage = modelImage.ToUMat(AccessType.Read))
    using (UMat uObservedImage = observedImage.ToUMat(AccessType.Read))
    
        SURF surfCPU = new SURF(hessianThresh);
        //extract features from the object image
        UMat modelDescriptors = new UMat();
        surfCPU.DetectAndCompute(uModelImage, null, modelKeyPoints, modelDescriptors, false);

        watch = Stopwatch.StartNew();

        // extract features from the observed image
        UMat observedDescriptors = new UMat();
        surfCPU.DetectAndCompute(uObservedImage, null, observedKeyPoints, observedDescriptors, false);

        //Match the two SURF descriptors
        BFMatcher matcher = new BFMatcher(DistanceType.L2);
        matcher.Add(modelDescriptors);

        matcher.KnnMatch(observedDescriptors, matches, k, null);

        mask = new Mat(matches.Size, 1, DepthType.Cv8U, 1);
        mask.SetTo(new MCvScalar(255));

        Features2DToolbox.VoteForUniqueness(matches, uniquenessThreshold, mask);
        int nonZeroCount = CvInvoke.CountNonZero(mask);

        if (nonZeroCount >= 4)
        
            nonZeroCount = Features2DToolbox.VoteForSizeAndOrientation(modelKeyPoints, observedKeyPoints,
               matches, mask, 1.5, 20);

            if (nonZeroCount >= 4)
                homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(modelKeyPoints,
                   observedKeyPoints, matches, mask, 2);
        

        watch.Stop();
    

    matchTime = watch.ElapsedMilliseconds;

我真的觉得我离解决方案不远了..希望有人可以帮助我

【问题讨论】:

如果你能拍出更好的输入图片,这种方法应该会很好用。 这种方法有点效果。但我的问题仍然存在。我正在寻找一种方法来衡量是否匹配良好或匹配是否糟糕。从肉眼看来,我必须有一个明显的解决方案。 检查this。它会告诉您单应性是否良好,即您是否匹配良好。可能是一个很好的起点。或者您可以将一张图像包裹在另一张图像上,并检查像素强度的绝对差异等。 感谢这确实有帮助。经过 5 次检查后,它似乎运行良好。但请注意:我使用的是 Emgu 3.0(这个 link 帮助我完成了端口。我还必须将我的 homography Mat 复制到新的 Image<Gray,Byte> 或它会崩溃。 好吧 ;D 我不熟悉 C# 包装器 【参考方案1】:

Features2DToolbox.GetHomographyMatrixFromMatchedFeatures 退出时,mask 矩阵is updated to have zeros 匹配是异常值(即,在计算的单应性下不能很好地对应)。因此,在mask 上再次调用CountNonZero 应该可以表明匹配质量。

我看到您希望将匹配分类为“好”或“坏”,而不是仅将多个匹配与单个图像进行比较;从您问题中的示例来看,合理的阈值可能是输入图像中找到的关键点的 1/4。您可能还需要一个绝对最小值,因为如果没有一定数量的证据,您就无法真正认为某件事是好的匹配。所以,例如,像

bool FindMatch(...) 
    bool goodMatch = false;
    // ...
    homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(...);
    int nInliers = CvInvoke.CountNonZero(mask);
    goodMatch = nInliers >= 10 && nInliers >= observedKeyPoints.size()/4;
    // ...
    return goodMatch;

在没有达到计算homography 的分支上,当然goodMatch 在初始化时只是保持假。数字 10 和 1/4 有点随意,取决于您的应用程序。

(警告:以上内容完全来自阅读文档;我还没有实际尝试过。)

【讨论】:

我看到我对此投了反对票;如果反对它的人碰巧正在阅读此评论,我很想知道您发现哪些不满意之处,以便我可以在可能的情况下对其进行改进。 好吧,我没有。非常感谢您的回答! 不客气。我希望它确实会有所帮助。

以上是关于使用 SURF 匹配图像并确定最佳匹配的主要内容,如果未能解决你的问题,请参考以下文章

opencv中SURF特征提取的最佳hessian阈值+最小描述符匹配

opencv之SURF图像匹配

如何将 SURF 兴趣点与图像数据库匹配

Matlab中多幅图像的SURF描述符与匹配

在 openCV 中查找 SURF 的精确匹配

怎么提取SURF匹配后的图像特征点坐标