概要
OpenCvSharpを用いての特徴点抽出の情報が少なく,実装まで苦労したのでメモついでに共有.pythonができないとは言ってない
今回は色々と使い勝手が良く,お気に入りのwindowsフォームアプリケーションで作成します
環境
windows10
Visual Studio 2019
実装
過去記事と同じ手順箇所は基本端折るので,不明なところがあればそっちに飛んで頂くか,コメントしてください
特徴点の抽出まで
1.NugetからOpenCvSharp4とOpenCvSharp4.Windowsをインストール
2.まずは定義
※画像の保存先パスはC:\cs_source\img\
Matmat=newMat();//比較元画像Mattemp=newMat();//比較先画像Matoutput1=newMat();//比較元画像の特徴点出力先Matoutput2=newMat();//比較先画像の特徴点出力先Matoutput3=newMat();//DrawMatchesの出力先AKAZEakaze=AKAZE.Create();//AKAZEのセットアップKeyPoint[]key_point1;//比較元画像の特徴点KeyPoint[]key_point2;//比較先画像の特徴点Matdescriptor1=newMat();//比較元画像の特徴量Matdescriptor2=newMat();//比較先画像の特徴量DescriptorMatchermatcher;//マッチング方法DMatch[]matches;//特徴量ベクトル同士のマッチング結果を格納する配列mat=Cv2.ImRead(@"C:\cs_source\img\fish1.jpg");//比較元画像temp=Cv2.ImRead(@"C:\cs_source\img\fish2.jpg");//比較先画像
今回はAKAZEという特徴量の計算アルゴリズムを使用
OpenCvSharp4ではこのようにMatは全て初期化しないと怒られるのでめんどうですね
ちなみに今回使用するジャイアントマンタくんの画像1と画像2(https://www.pakutaso.com/)
3.特徴点を出力する
//特徴量の検出と特徴量ベクトルの計算akaze.DetectAndCompute(mat,null,outkey_point1,descriptor1);akaze.DetectAndCompute(temp,null,outkey_point2,descriptor2);//画像1の特徴点をoutput1に出力Cv2.DrawKeypoints(mat,key_point1,output1);Cv2.ImShow("output1",output1);//画像2の特徴点をoutput1に出力Cv2.DrawKeypoints(temp,key_point2,output2);Cv2.ImShow("output2",output2);
特徴量をマッチングさせる
1.今回はBruteForceという総当たりマッチングを行う
matcher=DescriptorMatcher.Create("BruteForce");matches=matcher.Match(descriptor1,descriptor2);
2.マッチングした特徴量同士を線でつなぐ
Cv2.DrawMatches(mat,key_point1,temp,key_point2,matches,output3);Cv2.ImShow("output3",output3);
実行すると下のウィンドウが新たに表示される
なにもいじってないのに精度いいですね
流石OpenCV...
(おまけ)精度を上げる
まずmatchesの中身をコンソールで確認してみると
要素の説明はDMatchの公式リファレンスを参照してください
意外と距離あった・・・
精度関係で調べたらわかりますが,沢山の工夫された方法があります
ここでは,一番初歩的(主観)な方法であるDistanceに対して閾値を設定する方法で精度を上げていきたいと思います
百聞は一見に如かず,まずはコードを見てください(注:作者未だリーダブルコード未読)
Matoutput4=newMat();//DrawMatchesの出力先intgood_match_length=0;//閾値以下の要素数を格納intthreshold=750;//閾値//閾値以下の要素数のカウントfor(inti=0;i<key_point1.Length&&i<key_point2.Length;++i){if(matches[i].Distance<threshold){++good_match_length;}}DMatch[]good_matches=newDMatch[good_match_length];//閾値以下の要素数で定義//good_matchesに格納していくintj=0;for(inti=0;i<key_point1.Length&&i<key_point2.Length;++i){if(matches[i].Distance<threshold){good_matches[j]=matches[i];++j;}}
今回はビビッときた閾値750で実行
pythonじゃないのでDMatch[] good_matches;のようにただ定義するだけだと,未割当だかなんだかですぐ怒ってきます
まぁC#の利点っちゃあ利点とも言えますね
pythonゆとり仕様なんで(エアプ)
output3(チューン前)とoutput4(チューン後)の比較
ちょっと良くなったかも?
さいごに
今回は1番単純(超主観)な方法でチューンしていきましたが,ほかの方々の方法ではもっと精度が出ていますので,これは書き方の参考にでもするくらいの感じで見て頂ければ幸いです
これをきっかけにOpenCvSharpというニッチな世界に人が増えたらうれしいですね
参考資料は少ないし,配列付近のコマンドの自由性の低さとか苦労する点が多いです
本当にみんなpythonに行っちゃいそう
自分は使えないとかじゃないんで,環境がないだけなんで.ほんとに
参考URL
「OpenCV3でAKAZE特徴量を検出する」
https://dronebiz.net/tech/opencv3/akaze
「特徴点のマッチング」
http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_feature2d/py_matcher/py_matcher.html