Visual Basic でOpenCV(25) - 特徴点マッチング・双方向

Visual BasicOpenCVを用い、2 つの画像に先の特徴点検出を実行し、双方向マッチングを行う例を紹介します。

特徴点マッチング・双方向

2 つの画像に先の特徴点検出を実行し、それぞれのマッチングを行います。本例は特徴点の検出に、AKAZE を用います。フォームやそれに対応するソースコードなどは、これまでに紹介済みです。
先のプログラムは、マッチングを片方向にしか行っていないものでした。本例は逆方向のマッチングも行い、両方に含まれるものだけを抽出し精度を向上させます。

CCvFunc.vb

実際に特徴点検出を行う、CCv の派生クラスCCvFunc のDoCvFunction メソッドを示します。

:
'特徴点の取得、fwd, bwd チェック
Private Function DetectXrossMatch(imgs As Mat()) As _
                                    (List(Of DMatch), KeyPoint()())
    Dim keyp = New KeyPoint(imgs.Length - 1)() {}
    Dim lMatches As New List(Of DMatch)()

    'Using detector = ORB.Create()
    Using detector = AKAZE.Create()
        Using descriptors0 = New Mat()
            Using descriptors1 = New Mat()
                '特徴量の検出と特徴量ベクトルの計算
                detector.DetectAndCompute(imgs(0), Nothing,
                                          keyp(0), descriptors0)
                detector.DetectAndCompute(imgs(1), Nothing,
                                          keyp(1), descriptors1)

                'マッチング方法
                Dim matcher As DescriptorMatcher =
                                DescriptorMatcher.Create("BruteForce")

                '特徴量ベクトル同士のマッチング結果を配列へ格納
                Dim fwdMatches As DMatch() =
                            matcher.Match(descriptors0, descriptors1)
                Dim bckMatches As DMatch() =
                            matcher.Match(descriptors1, descriptors0)

                For i = 0 To fwdMatches.Length - 1
                    Dim forward As DMatch = fwdMatches(i)
                    Dim bckward As DMatch = bckMatches(forward.TrainIdx)
                    If bckward.TrainIdx = forward.QueryIdx Then
                        lMatches.Add(forward)
                    End If
                Next
            End Using
        End Using
    End Using
    Return (lMatches, keyp)
End Function

'----------------------------------------------------------------
' OpenCVを使用して処理
Public Function DoCvFunction(ByVal srcNames As List(Of String)) As Bitmap
    :
End Function
:

DoCvFunction メソッドは、前節とまったく同一です。
DetectXrossMatchメソッドで両方向のマッチングを行い、両方に含まれるものだけを抽出することで精度を向上させます。先のマッチングはdescriptors0 からdescriptors1 のマッチングのみを行っています。それに対して本プログラムでは、descriptors0 からdescriptors1 のマッチングとdescriptors1 からdescriptors0 のマッチングを行い、それぞれをfwdMatches とbckMatches に格納します。そして、For ループで両者の中の一致するものだけをlMatches にAdd メソッドで追加します。これによって、ループを抜けるとlMatches に精度の高い特徴点だけが残ります。

実行

以降に、実行例を示します。ドロップした画像は以前と同じです。