TOPへ
OpenCVSharp + AKAZE
 パターンマッチング

いつの間にかVB.NETからC#へ浮気をしてしまった今日この頃・・・
ふと仕事柄、画像処理を勉強している中で出会ったAKAZEが面白そうなので、試しに遊んでみた

サンプルコードはこちら(VisualStudioExpress2017NugetOpenCVSharp4を入れたもの)

ただEXEで遊んでみたいだけの人はこちらをダウンロード

サンプルの操作方法)
1)パターン画像を読み込む(サーチエリア画像の元画像の一部切り取り画像など)
2)サーチエリア画像を読み込む(サーチエリア画像を意地悪して回転とか変形させた画像とか)
3)普通のテンプレートマッチかAKAZE特徴量マッチかのボタンを押す
   このときCannyをチェックすると画像にCannyフィルタ(微分のようなもの)をプリフィルタでかけれます
4)うまくサーチがヒットすれば、切り取り画像が表示され、別ウィンドウで処理結果等が分かる絵がでてくる



サンプルプログラムの処理概要(AKAZEのみ解説)
1)パターン画像をOpenCVの画像形式MATに変換
2)サーチエリア画像をOpenCVの画像形式MATに変換
   1)も2)もAKAZEの画像端の特徴が出にくいことを補うために、額縁をつけています
3)パターン画像とサーチエリア画像の特徴量をAKAZEディテクタで検出します
  この結果、それぞれの画像から以下の物が検出されます
  特徴のある場所・・・keypoint
  特徴量(特徴量ベクトル)・・・descriptor
4)上記のdescriptorリスト同士を総当たり(brute force )で比較し、比較した結果を表すDmatch型変数のリストを得ます
  このDmatch1つにはキーポイントのペア(比較元と比較先)、その類似度distance(小さいほど似ている)が格納
  されています。
5)前のステップのDmatchには、間違ってペアリングされているDmachもいっぱいあります。よって、何とか選別したい。
  この時、distanceの小さい(類似度が高いもの)から順に採用するだけで良い気がしますが、
  比較元の1つのキーポイントが比較先に複数類似箇所がある場合もあります。同じ比較元とのペアばっかり採用してしまう
  ことになります。これを防止するためにKnnK−近傍法)が用いられます。比較元1つのキーポイントに対して、
  類似度の高い順にk個(プログラムではk=2を指定して2個)を取ってくる。この2つが似ている(類似度が同じくらい)
  だった場合、間違ったペアかもしれない確率が高く、逆に1つ目がダントツで類似度が良ければ、おそらくこのペアで
  あっているであろう、と推測して採用していく。この採用基準で、比較元のキーポイント全てを平等に評価していく。
  (ただし、円のように比較元1つに対して1周どこをとっても似ている場合、この手法は通じない・・実際にAKAZEは苦手)
6)おそらく、大部分の間違ったペアがそぎ落とされた結果のペアリストがある(List<Dmatch>型のgood変数)そして、
  このgoodリストを作ると同時にgoodに採用した比較元のキーポイントの座標配列pPatternと比較先のキーポイント
  座標配列pSerchも同時に作っておいた。この2つの配列を使って、ホモグラフィー行列を計算する。
  ホモグラフィー行列とは、比較元の座標系から比較先の座標への座標変換行列である。このとき、goodにはまだ若干の
  間違ったペアが紛れ込んでいるので、直線の近似式を作るときと同じように変換した点が変換先の点とフィットしない子がいる
  FindHomographyメソッドは、引数にHomographyMethods.Ransacを指定することにより、それらの除外リスト(mask)を生成
  除外して行列を作る機能がある。(このマスクを後の描画でいらないペアを描画しないように使っている)
7)ホモグラフィ行列が求まれば、比較元の4隅の角点や中央点、中央から右に水平に出した0度の方向の点が、比較先のどこの点に
  投影されるのかが分かるので、赤枠でここに検出したよ・・と表示させている。
  また、比較先画像からそのエリアを切り出すためには、ホモグラフィ行列の逆行列を用いて、サーチエリア画像を描画させる・・
  
WarpPerspectiveメソッドを使って。プログラム中では額縁付きでホモグラフィ行列作っているので、一旦額縁付きの
  サイズの画像に描画させてから、額縁分を後でそぎ落としてフォームにセットしてます。

 

最後・・プログラムにし忘れたのだが、肝心のサーチがヒットした時の、座標・回転方向・ズーム倍率は??
Cv2.PerspectiveTransform
メソッドで元画像の中心位置、中心からW/2分右にずれた点を変換したもの・・・すでにプログラムの最後にある
centerp[0]
・・・中心、centerp[1]・・・中心からw/2右に行った点・・・を使えば簡単に計算できますよね・・?
ちなみに私が最初のほうでつけたpad(額縁)の分を最後に引き算しないと・・もともとの座標からpad分ずれてますのでご注意。

参考にさせていただいたHP) 皆様大変参考になりました!感謝です!。土日良い暇つぶしになりました。
チグサウェブ 【C#OpenCVSharpで画像処理!【Visual Studio 2022
Qiita OpenCV 3Python 3で特徴量マッチング(A-KAZE, KNN
中京大学 工学部 橋本 学 テンプレートマッチングの魅力
HatenaBlogすりごまの鯖缶?ブログ 2缶目 画像処理でナンバープレートを消す
OpenCV-Pythonチュートリアル » 特徴量検出と特徴量記述 »特徴点のマッチングとHomographyによる物体検出
HatenaBlog 技術メモブログ OpenCVSharpを用いた画像位置合わせ
Qiita OpenCVcv::findHomographyについて



単純形状でキーポイント少なく、対称形状で対応が取りずらい例。
さすがに対応がはちゃめちゃで切り出し画像がぶっ飛んでるww。円とかもダメ。
普通のテンプレートマッチで見つけてください。また、AKAZEはエッジ画像とかだと情報量が
減って余計マッチ精度落ちますね・・Cannyチェックボックスで遊んでみてください。