C# 中的单应性、内点/ Emgu CV/ SURF

发布于 2024-10-10 23:59:08 字数 610 浏览 2 评论 0原文

如何使用 C# 中的单应性或其他方法获取匹配关键点的内点/离群值?

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

我得到了匹配的功能。代码中使用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# 中看到类似的代码吗?

同样,我只需要分离异常值/内部值。

How can I get inliers/outliers of matched kyepoints using homography or some other method in C#?

I am working on SURF example provided on http://www.emgu.com/wiki/index.php/SURF_feature_detector_in_CSharp.

I got matchedFeature. Code uses HomographyMatrix (homography). I want to separate inliers and outliers.

In 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)

returns inliers. Can I see similiar code also in C#.

Again I just need outliers/inliers separation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

想你的星星会说话 2024-10-17 23:59:09

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

//**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]);
        }
    }

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

If you want inliers/outliers separation and you already have your matches try this:

//**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]);
        }
    }

Note that I normalized the points so Homography estimation is more robust.

放低过去 2024-10-17 23:59:09

您的问题不太清楚,因为如果您使用 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);
}

Your question is not so clear because if you are using emgucv homography computation is estimated using CameraCalibration.FindHomography() function using RANSAC if there are more than 10 matching pairs.
I'm working on these topics for my thesis so i will post some relevant code that should fully reply to you and serve also to others.

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);
}
拥抱我好吗 2024-10-17 23:59:09

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

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# 中的样子。

The signature of cvFindFundamentalMat in C# would look like this:

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

Parameter defaults was introduced in C# 4.0. I assume that Emgu CV does not support .Net 4.0 yet (correct me if I'm wrong), thus an overload providing the default values could be made:

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

Note: as commenters also have stated, it is hard to be sure what you're asking for. Here, I have just guessed that some of your question is how the provided C++ code would look like in C#.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文