1

余暇には、コンピューター ビジョン技術を使ってさまざまなゲームを自動化するのが好きです。通常、フィルターとピクセル検出を使用したテンプレート マッチングは問題なく機能します。しかし、私は最近、機能マッチングを使用してレベル内をナビゲートしようと決心しました。私が意図したのは、探索したマップ全体のフィルター処理された画像を保存することでした。 フルマップ

次に、数秒ごとに画面からミニマップをコピーし、同じ方法でフィルター処理し、Surf を使用してそれを完全なマップに一致させます。これにより、プレイヤーの現在の場所が得られることを願っています (試合の中心は、プレイヤーがいる場所になります)。地図)。これが意図したとおりに機能する良い例を以下に示します (左側に一致が見つかった完全なマップ、右側がミニ マップ イメージです。 良い試合

私が問題を抱えているのは、EMGU ライブラリの Surf Matching が、多くの場合、間違った一致を検出するように見えることです。 悪い一致 悪い一致 2

以下のように、完全に悪くない場合もあります。 ウォンキーマッチ

サーフはスケール不変であるはずなので、マップ上のさまざまな場所のキーポイントにより適した一致を見つけることが、何が起こっているのかを見ることができます。私は EMGU ライブラリまたは Surf について十分に理解していないため、最初の適切な一致のみを受け入れ、これらの不適切な一致を破棄するか、それらの不安定な一致が代わりに適切な一致になるように調整する必要があります。

私は新しい 2.4 EMGU コード ベースを使用しており、SURF マッチングのコードは以下のとおりです。常に同じサイズ(通常のミニマップサイズとフルマップのサイズの比率)の一致のみを返すようにして、クレイジーな形の一致が得られないようにすることを本当に望んでいます.

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);
  }
4

1 に答える 1

1

抽出されたキーポイントの周りに黒い領域がある特定のシナリオがあります。特徴の一致に関しては、抽出されたキーポイントに対応する記述子間で発生することに注意してください。

SURF記述子は、単一のキーポイントではなくパッチを記述し、シナリオでは、マッチングパフォーマンスの低下の原因となる可能性があります.

[編集]

シナリオを分析すると、可能な候補となる方法は、部分的な輪郭の一致に基づく方法です。箱から出してすぐにopencv内に実装されているとは思わないので、citeseerxから取得して非常に簡単に実装できる、Donoserによる優れた論文「外部輪郭の効率的な部分形状マッチング」を提案できます。

于 2012-08-28T07:52:42.083 に答える