【问题标题】:Homography, inliers/ Emgu CV/ SURF in C#C# 中的单应性、内点/ Emgu CV/ SURF
【发布时间】:2011-01-09 16:25:19
【问题描述】:

如何使用 C# 中的单应性或其他方法获得匹配的 kyepoints 的内点/异常值?

我正在研究http://www.emgu.com/wiki/index.php/SURF_feature_detector_in_CSharp 上提供的 SURF 示例。

我得到了匹配功能。代码使用 HomographyMatrix(单应性)。我想区分内点和异常点。

在 C++ 中:

bgroup({findFundamentalMat})

int cvFindFundamentalMat(const CvMat* points1, const CvMat* points2, 
    CvMat* fundamentalMatrix, int method=CV_FM_RANSAC, double param1=1., 
    double param2=0.99, CvMat* status=NULL)

返回内点。我可以在 C# 中看到类似的代码吗?

再次,我只需要分离异常值/内部值。

【问题讨论】:

  • 什么?这个问题一团糟。有一条评论甚至不是您的代码的一部分。而且很不清楚你在问什么。

标签: c# surf computer-vision


【解决方案1】:

如果您想要分离内点/异常值并且您已经有了匹配项,请尝试以下操作:

//**RANSAC OUTLIER REMOVAL **//
Mat status;
vector<Point2f> trainMatches;
vector<Point2f> queryMatches;
vector<DMatch> inliers; 

    for( int i = 0; i < goodmatches.size(); i++ )
    {
        //-- Get the keypoints from the good matches
        trainMatches.push_back( cv::Point2f(keypointsB[ goodmatches[i].trainIdx ].pt.x/640.0f, keypointsB[ goodmatches[i].trainIdx ].pt.y/480.0f) );
        queryMatches.push_back( cv::Point2f(keypointsA[ goodmatches[i].queryIdx ].pt.x/640.0f, keypointsA[ goodmatches[i].queryIdx ].pt.y/480.0f) );
    }   

    Mat _homography;    
    Mat h = cv::findHomography(trainMatches,queryMatches,CV_RANSAC,0.005, status);

    for(size_t i = 0; i < queryMatches.size(); i++) 
    {
        if(status.at<char>(i) != 0) 
        {
            inliers.push_back(goodmatches[i]);
        }
    }

请注意,我对点进行了归一化,因此单应性估计更加稳健。

【讨论】:

    【解决方案2】:

    您的问题不太清楚,因为如果您使用 emgucv 单应性计算,则如果匹配对超过 10 个,则使用 RANSAC 使用CameraCalibration.FindHomography() 函数进行估计。 我正在为我的论文研究这些主题,因此我将发布一些相关代码,这些代码应该完全回复您并服务于其他人。

    result = MatchingRefinement.VoteForSizeAndOrientation(result, 1.5, 20);
    homography = MatchingRefinement.
        GetHomographyMatrixFromMatchedFeatures(result, 
            HomographyDirection.DIRECT, HOMOGRAPHY_METHOD.LMEDS);
    inverseHomography = MatchingRefinement.GetHomographyMatrixFromMatchedFeatures(
        result, HomographyDirection.INVERSE, HOMOGRAPHY_METHOD.LMEDS);
    
    PointF[] pts1 = new PointF[result.Length];
    PointF[] pts1_t = new PointF[result.Length];
    PointF[] pts2 = new PointF[result.Length];
    
    for (int i = 0; i < result.Length; i++)
    {
        pts1[i] = result[i].ObservedFeature.KeyPoint.Point;
        pts1_t[i] = result[i].ObservedFeature.KeyPoint.Point;
        pts2[i] = result[i].SimilarFeatures[0].Feature.KeyPoint.Point;
    }
    
    // Project model features according to homography
    homography.ProjectPoints(pts1_t);
    
    Image<Bgr, Byte> finalCorrespondance = inputImage.Copy();
    
    matchedInliersFeatures = new List<MatchedImageFeature>();
    
    for (int i1 = 0; i1 < pts1_t.Length; i1++)
    {
        if (Math.Sqrt(Math.Pow(pts2[i1].X - pts1_t[i1].X, 2d) + 
            Math.Pow(pts2[i1].Y - pts1_t[i1].Y, 2d)) <4d) // Inlier
        {
            PointF p_t = pts1_t[i1];
            PointF p = pts1[i1];
            finalCorrespondance.Draw(new CircleF(p, 2f), 
                new Bgr(Color.Yellow), 2);
            finalCorrespondance.Draw(new CircleF(p_t, 2f), 
                new Bgr(Color.Black), 2);
            finalCorrespondance.Draw(new LineSegment2DF(p, p_t), 
                new Bgr(Color.Blue), 1);
    
            MatchedImageFeature feature = new MatchedImageFeature();
            feature.SimilarFeatures = new SimilarFeature[] { 
                result[i1].SimilarFeatures[0] 
            };
            feature.ObservedFeature = result[i1].ObservedFeature;
            matchedInliersFeatures.Add(feature);
        }
    }
    
    List<ImageFeature> inliers = new List<ImageFeature>();
    foreach (MatchedImageFeature match in matchedInliersFeatures)
    {
        inliers.Add(match.ObservedFeature);
        inliers.Add(match.SimilarFeatures[0].Feature);
    }
    

    【讨论】:

      【解决方案3】:

      cvFindFundamentalMat 在 C# 中的签名如下所示:

      int cvFindFundamentalMat(CvMat points1, CvMat points2, CvMat fundamentalMatrix, 
           CV_FM method, double param1, double param2, CvMat status);
      

      参数默认值是在 C# 4.0 中引入的。我假设 Emgu CV 还不支持 .Net 4.0(如果我错了,请纠正我),因此可以进行提供默认值的重载:

      int cvFindFundamentalMat(CvMat points1, CvMat points2, CvMat fundamentalMatrix)
      {
          return cvFindFundamentalMat(points1, points2, fundamentalMatrix,
                 CV_FM.CV_FM_RANSAC, 1.0, 0.99, null);
      }
      

      注意:正如评论者所说,很难确定您要的是什么。在这里,我刚刚猜到你的一些问题是提供的 C++ 代码在 C# 中的样子。

      【讨论】:

      • 感谢您的帮助。我需要解释你为什么使用状态(空)。我在示例 PointF 格式的点中有。我必须用它们制作矩阵吗? Matrix circles = new Matrix(length, 1, 2);或 Matrix circles = new Matrix(length, 2, 1);
      • status==null 只是因为 C++ 签名的默认值为 null。
      • 但是是的,如果您有 PointF 数据,则必须先将它们转换为 CvMat 结构。
      猜你喜欢
      • 2016-07-16
      • 2012-04-02
      • 2015-11-09
      • 1970-01-01
      • 2011-09-04
      • 2011-06-25
      • 2020-11-30
      • 2015-03-05
      • 1970-01-01
      相关资源
      最近更新 更多