Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EMGU 2.4中的Surf特征检测/匹配问题_C#_Image Processing_Opencv_Emgucv_Surf - Fatal编程技术网

C# EMGU 2.4中的Surf特征检测/匹配问题

C# EMGU 2.4中的Surf特征检测/匹配问题,c#,image-processing,opencv,emgucv,surf,C#,Image Processing,Opencv,Emgucv,Surf,所以在我的业余时间,我喜欢尝试通过计算机视觉技术自动化各种游戏。通常情况下,模板匹配与过滤器和像素检测工作与我很好。然而,我最近决定尝试使用特征匹配来导航某个级别。我的目的是保存一张经过过滤的完整地图图像。 然后每隔几秒钟从屏幕上复制一次小地图,并以同样的方式进行过滤,然后使用Surf将其与我的完整地图进行匹配,这将有望为我提供球员的当前位置(比赛的中心将是球员在地图上的位置)。下面是一个很好的例子(左为找到匹配的完整地图,右为迷你地图图像)。 我遇到的问题是,EMGU库中的Surf匹配在许

所以在我的业余时间,我喜欢尝试通过计算机视觉技术自动化各种游戏。通常情况下,模板匹配与过滤器和像素检测工作与我很好。然而,我最近决定尝试使用特征匹配来导航某个级别。我的目的是保存一张经过过滤的完整地图图像。

然后每隔几秒钟从屏幕上复制一次小地图,并以同样的方式进行过滤,然后使用Surf将其与我的完整地图进行匹配,这将有望为我提供球员的当前位置(比赛的中心将是球员在地图上的位置)。下面是一个很好的例子(左为找到匹配的完整地图,右为迷你地图图像)。

我遇到的问题是,EMGU库中的Surf匹配在许多情况下似乎会发现不正确的匹配。

有时情况并非完全糟糕,如下所示:

我可以看到发生的事情是,它在地图上的不同位置为关键点找到更好的匹配,因为Surf应该是比例不变的。我对EMGU库或Surf了解不够,无法限制它,使它只接受像最初的好匹配,或者扔掉这些不好的匹配,或者调整它那些不可靠的比赛反而是好的

我正在使用新的2.4 EMGU代码库,下面是我的冲浪匹配代码。我真的想让它切中要害,这样它只返回总是相同大小的匹配(正常小地图大小与完整地图上的大小的比例),这样我就不会得到一些疯狂形状的匹配

public Point MinimapMatch(Bitmap Minimap, Bitmap FullMap)
    {
        Image<Gray, Byte> modelImage = new Image<Gray, byte>(Minimap);
        Image<Gray, Byte> observedImage = new Image<Gray, byte>(FullMap);     
        HomographyMatrix homography = null;

        SURFDetector surfCPU = new SURFDetector(100, false);
        VectorOfKeyPoint modelKeyPoints;
        VectorOfKeyPoint observedKeyPoints;
        Matrix<int> indices;

        Matrix<byte> mask;
        int k = 6;
        double uniquenessThreshold = 0.9;
        try
        {
            //extract features from the object image
            modelKeyPoints = surfCPU.DetectKeyPointsRaw(modelImage, null);
            Matrix<float> modelDescriptors = surfCPU.ComputeDescriptorsRaw(modelImage, null, modelKeyPoints);

            // extract features from the observed image
            observedKeyPoints = surfCPU.DetectKeyPointsRaw(observedImage, null);
            Matrix<float> observedDescriptors = surfCPU.ComputeDescriptorsRaw(observedImage, null, observedKeyPoints);
            BruteForceMatcher<float> matcher = new BruteForceMatcher<float>(DistanceType.L2);
            matcher.Add(modelDescriptors);

            indices = new Matrix<int>(observedDescriptors.Rows, k);
            using (Matrix<float> dist = new Matrix<float>(observedDescriptors.Rows, k))
            {
                matcher.KnnMatch(observedDescriptors, indices, dist, k, null);
                mask = new Matrix<byte>(dist.Rows, 1);
                mask.SetValue(255);
                Features2DToolbox.VoteForUniqueness(dist, uniquenessThreshold, mask);
            }

            int nonZeroCount = CvInvoke.cvCountNonZero(mask);
            if (nonZeroCount >= 4)
            {
                nonZeroCount = Features2DToolbox.VoteForSizeAndOrientation(modelKeyPoints, observedKeyPoints, indices, mask, 1.5, 20);
                if (nonZeroCount >= 4)
                    homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(modelKeyPoints, observedKeyPoints, indices, mask, 2);
            }

            if (homography != null)
            {  //draw a rectangle along the projected model
                Rectangle rect = modelImage.ROI;
                PointF[] pts = new PointF[] { 
                new PointF(rect.Left, rect.Bottom),
                new PointF(rect.Right, rect.Bottom),
                new PointF(rect.Right, rect.Top),
                new PointF(rect.Left, rect.Top)};
                homography.ProjectPoints(pts);
                Array.ConvertAll<PointF, Point>(pts, Point.Round);

                Image<Bgr, Byte> result = Features2DToolbox.DrawMatches(modelImage, modelKeyPoints, observedImage, observedKeyPoints, indices, new Bgr(255, 255, 255), new Bgr(255, 255, 255), mask, Features2DToolbox.KeypointDrawType.DEFAULT);
                result.DrawPolyline(Array.ConvertAll<PointF, Point>(pts, Point.Round), true, new Bgr(Color.Red), 5);                  

                return new Point(Convert.ToInt32((pts[0].X + pts[1].X) / 2), Convert.ToInt32((pts[0].Y + pts[3].Y) / 2));
            }


        }
        catch (Exception e)
        {
            return new Point(0, 0);
        }


     return new Point(0,0);
  }
public Point MinimapMatch(位图Minimap,位图FullMap)
{
图像模型图像=新图像(小地图);
图像观察图像=新图像(FullMap);
同形矩阵同形=空;
SURFDECTOR surfCPU=新的SURFDECTOR(100,错误);
关键点模型关键点向量;
关键点向量观测到的关键点;
矩阵指数;
矩阵掩模;
int k=6;
双唯一阈值=0.9;
尝试
{
//从对象图像中提取特征
modelKeyPoints=surfCPU.DetectKeyPointsRaw(modelImage,null);
矩阵modelDescriptors=surfCPU.ComputedDescriptorsRaw(modelImage,null,modelKeyPoints);
//从观测图像中提取特征
observedKeyPoints=surfCPU.DetectKeyPointsRaw(observedImage,null);
矩阵observedDescriptors=surfCPU.ComputedDescriptorsRaw(observedImage,null,observedKeyPoints);
BruteForceMatcher matcher=新的BruteForceMatcher(DistanceType.L2);
添加(模型描述符);
索引=新矩阵(observedDescriptors.Rows,k);
使用(矩阵距离=新矩阵(observedDescriptors.Rows,k))
{
匹配器.KnnMatch(observedDescriptor,index,dist,k,null);
掩码=新矩阵(距离行,1);
掩码设置值(255);
特性2dToolbox.VoteForUnique(距离、唯一阈值、掩码);
}
int nonZeroCount=CvInvoke.cvCountNonZero(掩码);
如果(非零计数>=4)
{
非零计数=功能2dToolbox.VoteForSizeAndOrientation(模型关键点、观测关键点、索引、掩码,1.5,20);
如果(非零计数>=4)
单应性=Features2DToolbox.GetHomographyMatrix从匹配的特征(modelKeyPoints、observedKeyPoints、Index、mask,2);
}
if(单应性!=null)
{//沿投影模型绘制一个矩形
矩形rect=modelImage.ROI;
PointF[]pts=新的PointF[]{
新的点F(左直,下直),
新的点F(右直,下直),
新的点F(右直,上直),
新的PointF(rect.Left,rect.Top)};
单应性.投影点(pts);
数组.ConvertAll(pts,Point.Round);
图像结果=Features2DToolbox.DrawMatches(modelImage、modelKeyPoints、ObserveImage、ObserveKeyPoints、Index、新Bgr(255、255、255)、新Bgr(255、255、255)、掩码、Features2DToolbox.KeypointDrawType.DEFAULT);
结果:DrawPolyline(Array.ConvertAll(pts,Point.Round),真,新Bgr(Color.Red),5);
返回新点(Convert.ToInt32((pts[0].X+pts[1].X)/2),Convert.ToInt32((pts[0].Y+pts[3].Y)/2);
}
}
捕获(例外e)
{
返回新点(0,0);
}
返回新点(0,0);
}

您有一个特定场景,在该场景中,提取的关键点周围都有黑色区域。 当涉及到特征匹配时,请记住它发生在与提取的关键点对应的描述符之间

冲浪描述符描述的是一个补丁,而不是一个关键点,在您的场景中,这可能是导致匹配性能差的原因

[编辑]

分析您的场景一种可能的候选方法是一种基于部分轮廓匹配的方法。我不认为您可以在opencv开箱即用中找到它,因此我可以向您推荐一篇好文章。”
Donoser提供的“外部轮廓的有效部分形状匹配”,您可以从CiteSerx获取,并且非常容易实现。

您有一个特定场景,其中提取的关键点周围都有黑色区域。 当涉及到特征匹配时,请记住它发生在与提取的关键点对应的描述符之间

冲浪描述符描述的是一个补丁,而不是一个关键点,在您的场景中,这可能是导致匹配性能差的原因

[编辑]

分析你的场景一个可能的候选方法是一个包含部分轮廓匹配的方法