opencvで文字認識その1 Tesseractラッパ

OpenCV3.0系から文字認識モジュールが搭載されるようなので使ってみる.現状の3.0 alphaや3.0 betaでは,文字認識モジュールはメインレポジトリに組み込まれておらず開発用レポジトリのopencv_contribの方に入っているようで,opencv_contribと一緒にOpenCVをビルドする必要がある.

OpenCVの文字認識モジュール

OpenCVのドキュメントによると,以下の2種類の文字認識方法があるらしい.

  1. オープンソースのOCRライブラリtesseract-ocrを呼び出す方法
  2. 隠れマルコフモデルによる認識方法

今回は,1の方法について試してみる.

文字認識モジュールの準備

tesseract-ocrのダウンロード

https://code.google.com/p/tesseract-ocr/downloads/listからVC++からtesseract-ocrを呼び出す用のライブラリをダウンロード・解凍する.「tesseract-3.xx.xx-win32-lib-include-dirs.zip」って名前のやつ.今回は「tesseract-3.02.02-win32-lib-include-dirs.zip」を使った.

https://code.google.com/p/tesseract-ocr/downloads/listからtesseract-ocr用の学習済みのデータファイルをダウンロードしておく.今回は英語で試すため「tesseract-ocr-3.02.eng.tar.gz」をダウンロード・解凍する.

opencv_contribのダウンロード

https://github.com/itseez/opencv_contribからopencv_contribをダウンロード・解凍する.

OpenCVのビルド

CMakeを使ってビルドする.ここらへんを参考に.

「OPENCV_EXTRA_MODULES_PATH」パラメータの値を「(opencv_contribのパス)/modules」にセットしてConfigureする.

すると「Tesseract_INCLUDE_DIR」と「Tesseract_LIBRARY」というパラメータが出てくるので

  • Tesseract_INCLUDE_DIR ← (tesseract-ocrのパス)/include
  • Tesseract_LIBRARY ← (tesseract-ocrのパス)/lib

とセットする.

以上の設定でGenerateしてOpenCVをビルドすると文字認識モジュールが組み込まれる.で,インストールする.

動作確認

実際に画像を入力してやってみたソースコードと結果が以下.OpenCVのMat形式の画像を使って文字認識出来るため,tesseract-ocrのAPI直接叩くよりは使いやすいと思う.

追記)文字のかたまりの位置の出力が間違っていたためソースコードと結果画像を修正した.

ソースコード
#include <opencv2/opencv.hpp>
#include <opencv2/text.hpp>

void main()
{
	// 画像読み込み
	auto image = cv::imread("moji.jpg");
	// グレースケール化
	cv::Mat gray;
	cv::cvtColor(image, gray, COLOR_RGB2GRAY);
	// 文字認識クラスのインスタンス生成
	auto ocr = cv::text::OCRTesseract::create("(言語データのパス)/tessdata", "eng");

	std::string text;
	std::vector<cv::Rect> boxes;
	std::vector<std::string> words;
	vector<float> confidences;
	// 文字認識の実行
	ocr->run(gray, text, &boxes, &words, &confidences);

	// 結果出力
	printf("%s\n", text.c_str());
	// 文字のかたまりごとに出力
	printf(" 文字      | 位置       | 大きさ     | 信頼度\n");
	printf("-----------+------------+------------+----------\n");
	for (int i = 0; i < boxes.size(); i++)
	{
		printf("%-10s | (%3d, %3d) | (%3d, %3d) | %f\n",
			words[i].c_str(),
			boxes[i].x, boxes[i].y,
			boxes[i].width, boxes[i].height,
			confidences[i]);
	}
}
実行結果

f:id:whoopsidaisies:20141112103657p:plain

C#で細線化 AForge.NET

C#で画像の細線化処理を行って線画像を作成する.コンピュータビジョン等のライブラリであるAForge.NET Frameworkには,モルフォロジー処理が実装されているのでそれを利用する.

細線化のアルゴリズムは以下のサイトあたりを参照.
パターン認識の前処理に必要な二値画像の細線化:CodeZine
細線化アルゴリズム 画像処理ソリューション
technotype

AForge.NETのインストール

Nuget経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「AForge」で検索.「AForge.Imaging」を選択してインストール.

ソースコード

ヒット・ミス演算を行うHitAndMissクラスを使う.

// using AForge.Imaging.Filters; をソースコードに書いておく

// 元画像の読み込み
var bmp = new Bitmap(@"moji.png");
pictureBox1.Image = bmp;

// 二値化処理
var gray = new Grayscale(0.2125,0.7154,0.0721).Apply(bmp);
var binary = new Threshold().Apply(gray);
pictureBox2.Image = binary;            
            
// 細線化用の8つのフィルタを作成
var filterSequence = new FiltersSequence();
filterSequence.Add(new HitAndMiss(
    new short[,] { { 0, 0, 0 }, { -1, 1, -1 }, { 1, 1, 1 } },
    HitAndMiss.Modes.Thinning));
filterSequence.Add(new HitAndMiss(
    new short[,] { { -1, 0, 0 }, { 1, 1, 0 }, { -1, 1, -1 } },
    HitAndMiss.Modes.Thinning));
filterSequence.Add(new HitAndMiss(
    new short[,] { { 1, -1, 0 }, { 1, 1, 0 }, { 1, -1, 0 } },
    HitAndMiss.Modes.Thinning));
filterSequence.Add(new HitAndMiss(
    new short[,] { { -1, 1, -1 }, { 1, 1, 0 }, { -1, 0, 0 } },
    HitAndMiss.Modes.Thinning));
filterSequence.Add(new HitAndMiss(
    new short[,] { { 1, 1, 1 }, { -1, 1, -1 }, { 0, 0, 0 } },
    HitAndMiss.Modes.Thinning));
filterSequence.Add(new HitAndMiss(
    new short[,] { { -1, 1, -1 }, { 0, 1, 1 }, { 0, 0, -1 } },
    HitAndMiss.Modes.Thinning));
filterSequence.Add(new HitAndMiss(
    new short[,] { { 0, -1, 1 }, { 0, 1, 1 }, { 0, -1, 1 } },
    HitAndMiss.Modes.Thinning));
filterSequence.Add(new HitAndMiss(
    new short[,] { { 0, 0, -1 }, { 0, 1, 1 }, { -1, 1, -1 } },
    HitAndMiss.Modes.Thinning));

// フィルタ処理の繰り返し回数を指定
var filter = new FilterIterator(filterSequence, 20);

// 細線化処理の実行
var thinned = filter.Apply(binary);
pictureBox3.Image = thinned;

実行結果.

f:id:whoopsidaisies:20140915092901p:plain

C#でGISデータ(shpファイル)を開く DotSpatialによる方法

DotSpatialは.NET向けのオープンソースの地理情報システムライブラリである.これを使ってGISで用いられるshpファイル(とセットのshxファイルとdbfファイル)を読み込む.

DotSpatialのインストール

Nuget経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「DotSpatial」で検索.たくさん出てくるが,ここでは「DotSpatial.Controls」選択してインストール.

f:id:whoopsidaisies:20140914212117p:plain

Mapコントロールの追加

GISデータ表示用のコントロールが用意されているのでそれを使ってみる.

まず,一度プロジェクトをビルドする.そうするとDotSpatialのDLLが実行ファイルのディレクトリにコピーされる.

ツールボックスの適当なところでクリックして「アイテムの選択(I)...」を選択.
f:id:whoopsidaisies:20140914212749p:plain

「.NET Framework コンポーネント」タブの「参照(B)...」ボタンを押して,「(実行ファイルのパス)\DotSpatial.Controls.dll」を選択したらOK.

f:id:whoopsidaisies:20140914212821p:plain

f:id:whoopsidaisies:20140914213930p:plain

そうすると「Map」というコントロールが追加されているのでフォームに追加する.
f:id:whoopsidaisies:20140914213818p:plain

シェープファイルの読み込み

シェープファイルは「全国市区町村界データ | データ製品 | 製品 | ESRIジャパン株式会社」でESRI Japanが配布している全国市区町村界データを使う.ダウンロードして解答したら以下のコードを追加する.

map1.AddLayer(@"D:\Users\whoops\Downloads\japan_ver72\japan_ver72.shp");

実行すると以下のように地図が表示される.

f:id:whoopsidaisies:20140914214517p:plain

属性情報の表示 Infoモード

上の状態だと地図が表示されるだけで何もできないためMapコントロールのモードを変える.以下のようにコードを追加してInfoモードにする.

map1.AddLayer(@"D:\Users\whoops\Downloads\japan_ver72\japan_ver72.shp");
map1.FunctionMode = DotSpatial.Controls.FunctionMode.Info;

これで実行すると以下のようにクリックした位置の市町村の情報を見れる.

f:id:whoopsidaisies:20140914214930p:plain

領域の選択 Selectモード

Selectモードににするとドラッグで領域指定できる.

map1.FunctionMode = DotSpatial.Controls.FunctionMode.Select;

f:id:whoopsidaisies:20140915002531p:plain

選択しただけだと何も表示されないので,TextBoxに選択された領域の情報を表示してみる.MAPコントロールのMouseUpイベントを追加して以下のコードを書き込む.

private void map1_MouseUp(object sender, MouseEventArgs e)
{
    textBox1.Text = "";
    // MAPコントロールが保持しているレイヤーデータを取得
    var featureLayer = map1.Layers[0] as DotSpatial.Symbology.FeatureLayer;
            
    // すべてのデータについてループ
    for (int i = 0; i < featureLayer.DrawnStates.Length; ++i)
    {
        // 選択されているかどうか判別
        if (featureLayer.DrawnStates[i].Selected == true)
        {
            // i番目の属性情報取得
            var feature = featureLayer.FeatureSet.GetFeature(i);

            // DataRowからフィールド名でアクセス
            textBox1.Text += System.String.Format(
                "{0} : {1} {2} {3}人",
                feature.DataRow["JCODE"],
                feature.DataRow["KEN"],
                feature.DataRow["SIKUCHOSON"],
                feature.DataRow["P_NUM"]
                )
                + System.Environment.NewLine;
        }
    }
}

選択されているかどうかはレイヤーデータのDrawnStatesプロパティに格納されている.

属性情報はFeatureSetプロパティに格納されていてGetFeatureメソッドで指定した番号のデータを取得できる.

各属性情報へは,DataRawにフィールド名を指定することで取得できる.このサンプルで使っているフィールド名は「全国市区町村界データ | データ製品 | 製品 | ESRIジャパン株式会社」を参照.

実行してドラッグで領域選択すると以下のようにTextBoxに情報が表示される.
f:id:whoopsidaisies:20140915004858p:plain

MAPコントロールなしで読み込み

MAPコントロールを配置しなくてもDataManagerクラスのOpenFileメソッドを使えばシェープファイルは読み込める.

以下にシェープファイルを読み込んで,0番目のデータの座標を出力するコードを載せる.

// シェープファイルの読み込み
var layer = DotSpatial.Data.DataManager.DefaultDataManager.OpenFile(@"D:\Users\whoops\Downloads\japan_ver72\japan_ver72.shp") 
    as DotSpatial.Data.FeatureSet;
// 0番目のデータの座標を表示
foreach (var cordinate in layer.GetFeature(0).Coordinates)
{
    Console.WriteLine(cordinate.ToString());
}

実行結果
f:id:whoopsidaisies:20140915010455p:plain

コントロールを使わない方法だけを使う場合NuGetで「DotSpatial.Data」をインストールすればできる.

SVGアニメーションで初音ミクの一筆書き

SVGによるアニメーションの勉強メモと,作った初音ミクの一筆書きアニメーション.

アニメーションをSVGのanimateMotion要素と,CSSのanimationプロパティを使った.本当はCSS使わないでやりたかったのだけどそれだと面倒くさそうだったのでCSSも使った.

元画像は以下のサイトから持ってきた.
piapro(ピアプロ)|イラスト「一筆書きで 初音ミクを 描きました」


以下が作ったアニメーション.SVGCSSのアニメーションの同期の取り方がわからなかったので,読み込みの度にタイミングが変わってしまう.

SVGファイルを置くのに借りていたレンタルサーバーの期限が切れてしまったため、暇なとき別のところにアップロードしなおします。

SVG animateMotion要素

赤い円を移動させるのには,SVGanimateMotion要素を使った.

animateMotion要素を用いると,図形をpathで指定した任意の曲線に沿って移動させることが出来る.また,mpath要素によって以下のようにpathの参照が可能.

<path d="M10,110 A120,120 -45 0,1 110 10 A120,120 -45 0,1 10,110"
      stroke="lightgrey" stroke-width="2" 
      fill="none" id="theMotionPath"/>
<circle cx="10" cy="110" r="3" fill="lightgrey"  />
<circle cx="110" cy="10" r="3" fill="lightgrey"  />

<!-- Here is a red circle which will be moved along the motion path. -->
<circle cx="" cy="" r="5" fill="red">

    <!-- Define the motion path animation -->
    <animateMotion dur="6s" repeatCount="indefinite">
       <mpath xlink:href="#theMotionPath"/>
    </animateMotion>
</circle>
animateMotion - SVG | MDN

CSS animate要素

線を描いていく様子は,CSSanimate要素を使って破線の間隔を変える方法を使った.
破線の間隔が変わることで線が伸びて行っているように見えるようだ.

How SVG Line Animation Works | CSS-Tricks

CSSに以下のように描いてやるといいようだが,stroke-dasharrayやstroke-dashoffsetの値を線の長さくらいにしなくてはならないらしく少し面倒.

path {
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  animation: dash 5s linear forwards;
}

@keyframes dash {
  to {
    stroke-dashoffset: 0;
  }
}

d3.jsで作成

初音ミクの座標データは画像からこつこつと抽出した.以下からダウンロード可能.
http://whoopsidaisies.site-station.net/blog/miku.csv

SVG直打ちでもよかったが,せっかくなのでd3.jsでCSVファイルを読み込んでSVGを吐き出した.

d3.csv("miku2.csv", function (data) {

    var line = d3.svg.line()
        .x(function (d) { return Math.round(d.x * 10) / 10; })
        .y(function (d) { return Math.round(d.y * 10) / 10; })
        .interpolate("linear");

    var svg = d3.select("body").append("svg").attr("width", 700).attr("height", 900);
        
    var path = svg.append("path")
        .attr({
            "d": line(data),
            "stroke": "black",
            "stroke-width": 2,
            "fill": "none",
            "id": "mikupath"
        });

    svg.append("circle")
        .attr({
            "cx": "",
            "cy": "",
            "r": "5",
            "fill": "red"
        })
        .append("animateMotion")
        .attr({
            "dur": "20s",
            "repeatCount": "indefinite"
        })
        .append("mpath")
        .attr("xlink:href", "#mikupath");
});


ソースコード全文は以下.
http://whoopsidaisies.site-station.net/blog/mikuanimation2.html


実行後のhtmlは以下.
http://whoopsidaisies.site-station.net/blog/mikuanimation.html

レンタルサーバーの期限が切れてしまったため、暇なとき別のところにアップロードしなおします。

PowerPointのオートシェイプで好きな関数の曲線を作る C# NetOfficeによる方法


f:id:whoopsidaisies:20140911101713p:plain
sin(x)/xのオートシェイプ

オートシェイプできれいな波形を作りたいときがたまにあるのだけど,C#を使って上の画像みたいにsin(x)/xのオートシェイプをわりときれいに作れたので手順をまとめる.

試した環境はPowerPoint2010とVisual Studio 2013.バージョンが違うと少し変わる可能性はあると思う.(わざわざC#でやらずともVBAマクロでも同じことは出来るけど,VBAは苦手なのでC#でやる.VBAでのやり方も後述します)

出来上がったPowerPointファイルを以下からダウンロードできるようにしておいた.
sinc.pptx - Google ドライブ

NetOffice.PowerPointのインストール

以前「C#でExcelファイルを作成・グラフを挿入する NetOfficeによる方法 - whoopsidaisies's diary」で紹介した,NetOfficeという.NET用のライブラリを使うとPowerPoint等にアクセスして色々出来るのでそれを利用する.

NetOfficeはNuGet経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「NetOffice.PowerPoint」を検索してインストール.

ソースコード

以下にソースコードを載せる.スライドを作ってAddCurveメソッドで曲線を追加しているだけである.

AddCurveメソッドの引数として,float[(点の数),2]に座標を格納して渡す.この点の座標を元にベジェ曲線を描くようである.点の数は3n+1個にしないと止まるので注意.

点の座標はスライドの左上が(0,0)でピクセルで指定する.スライドのオブジェクトのPageSetupプロパティにスライドの幅と高さが格納されているのでそれを元に大きさを調整した.

static void Main(string[] args)
{
    // パワーポイントを開く
    using (var app = new NetOffice.PowerPointApi.Application())
    {
        // プレゼンテーションの作成
        var presentation = app.Presentations.Add();
        // スライドの追加
        var slide = presentation.Slides.Add(1, NetOffice.PowerPointApi.Enums.PpSlideLayout.ppLayoutBlank);

        // sin(x)/xの座標を得る
        var sinc = GetSinc(presentation.PageSetup.SlideWidth, presentation.PageSetup.SlideHeight);

        // 座標からベジェ曲線を描画する
        // 引数はfloatの二次元配列.座標の数は6n+1個じゃないといけないため注意.
        slide.Shapes.AddCurve(sinc);

        // プレゼンテーションの保存
        presentation.SaveAs(@"D:\a.pptx");
        // プレゼンテーションファイルを閉じる
        presentation.Close();
        // パワーポイントの終了 作成したファイル以外も閉じられるので注意
        //app.Quit();
    }
}

/// <summary>
/// sin(x)/x関数の座標をスライドの大きさに合わせて拡大,
/// </summary>
/// <param name="slideWidth">スライドの幅</param>
/// <param name="slideHeight">スライドの高さ</param>
/// <returns>sin(x)/x関数を描くための点の座標</returns>
static float[,] GetSinc(float slideWidth, float slideHeight)
{
    // xが-4π~4πまでのsin(x)/xを求める.601点.
    var xs = Enumerable.Range(-300, 601).Select(x => x * 4 * Math.PI / 300);
    var ys = xs.Select(x => x != 0 ? Math.Sin(x) / x : 1);

    // PowerPointのスライドのサイズに合わせて移動・拡大をする
    // 中心座標
    var cx = slideWidth / 2;
    var cy = slideHeight / 2;
    // オブジェクトのだいたいの大きさ
    var width = slideWidth * 0.8;
    var height = slideHeight * 0.8;
    var pptXs = xs.Select(x => x / (4 * Math.PI) * width / 2 + cx).ToArray();
    var pptYs = ys.Select(y => -y * height / 2 + cy).ToArray();

    // AddCurveメソッドに渡すためにfloatの2次元配列に代入する
    var sinc = new float[pptXs.Length, 2];
    for (int i = 0; i < pptXs.Length; ++ i)
    {
        sinc[i, 0] = (float)pptXs[i];
        sinc[i, 1] = (float)pptYs[i];
    }
    return sinc;
}

実行すると,記事の最初の画像のpptxファイルが作成される.GetSincメソッドの部分を適当な座標を格納をするように変えれば自分の好きな曲線を引ける.

ちなみに出来た曲線はオートシェイプなので,以下の画像のように線の太さとか種類とか色とかも簡単に変えられる.
f:id:whoopsidaisies:20140911115617p:plain
拡大してもきれい.
f:id:whoopsidaisies:20140911115623p:plain

VBAマクロでのやり方

記事の最初にも述べたが,C#を使わずともVBAマクロで同じことが出来る.以下に参考になるコードを載せる(ここのサンプル見やすくしただけだけど).

これの点の座標を引きたい曲線の座標にしてやればOK.

Sub DrawCurve()
    ' 1枚目のスライドのオブジェクトを得る
    Dim slide As PowerPoint.slide
    Set slide = ActivePresentation.Slides(1)
       
    ' ベジェ曲線を引くための点の座標を配列に格納
    ' ここの座標の値を適当に変えてやれば好きな曲線が引ける
    Dim points(1 To 7, 1 To 2) As Single
    points(1, 1) = 0
    points(1, 2) = 0
    points(2, 1) = 72
    points(2, 2) = 72
    points(3, 1) = 100
    points(3, 2) = 40
    points(4, 1) = 20
    points(4, 2) = 50
    points(5, 1) = 90
    points(5, 2) = 120
    points(6, 1) = 60
    points(6, 2) = 30
    points(7, 1) = 150
    points(7, 2) = 90
    
    ' 曲線の追加
    slide.Shapes.AddCurve SafeArrayOfPoints:=points
End Sub

OpenCVでDeepFlow

opencv_contribを見てたら,DeepFlowというオプティカルフローのアルゴリズムが実装されていたので勉強ついでに使ってみる.

DeepFlow

DeepFlowはコンピュータビジョンの分野では有名な国際学会ICCV2013でWeinzaepfelらによって発表されたアルゴリズムである.
HAL - INRIA :: [hal-00873592, version 1] DeepFlow: Large displacement optical flow with deep matching

DeepFlowではDeep Matchingという画像のマッチング手法(これも同論文内で提案されている)を用いてオプティカルフローを求めている.

以下の画像にアルゴリズムの全体像がまとめられている.

f:id:whoopsidaisies:20140821140023j:plain

LEAR - DeepMatchingFlow

パワーポイントの資料はこちら

Deep Matching

Deep Matchingでは,畳み込み,プーリング,サブサンプリングを繰り返しすことで,画像間のQuasi-Denseなマッチング(日本語でなんていうかわからない.準密?)を求める.

Deep Learningで注目を集めているConvolutional Neural Networks(CNN)に似たアプローチとなっている.

Deep Matchingを使うと以下のように非剛体のマッチングもうまく出来るようである.

f:id:whoopsidaisies:20140821152916p:plainf:id:whoopsidaisies:20140821152927p:plain

Jerome Revaud

オプティカルフロー

DeepFlowでは,時間的輝度勾配と空間的輝度勾配の拘束条件に加えて,Deep Matchingで求めた対応とオプティカルフローとの差異も拘束条件として目的関数に入れることで,密でかつ大きな動きにも強いオプティカルフローを得るようである.

目的関数の最小化はSOR法という反復法で行っているようである.

DeepFlowで以下の画像みたいな感じにマッチングとオプティカルフローが得られるらしい.

f:id:whoopsidaisies:20140821180059p:plain

LEAR - DeepMatchingFlow

OpenCVで動かしてみる

DeepFlowは2014/8/21現在opencv_contribに入っているが,opencv_contribは開発用リポジトリらしいので自己責任で.

ここからソースを落としてきて,OpenCVのCMakeのオプションで「OPENCV_EXTRA_MODULES_PATH」を「(opencv_contribのパス)/modules」としてgenerate,ビルドしてやるとOpenCVにopencv_contrib内のモジュールが組み込まれる.

実際にDeepFlowを動かしてみたソースコードは以下.
DeepFlowのパラメータはここを参照.

#include <opencv2/opencv.hpp>
#include <opencv2/optflow.hpp>

void main()
{
	using namespace cv;

	// DeepFlow計算用のインスタンスを生成
	auto deepflow = optflow::createOptFlow_DeepFlow();
	// 動画読み込み
	auto capture = VideoCapture("video.mp4");
	
	// 前のフレーム保存
	// まだグレースケールしか対応してないようなので変換
	Mat prev, tmp;
	capture >> tmp;
	cvtColor(tmp, prev, COLOR_RGB2GRAY);

	while (cv::waitKey(1) == -1)
	{
		Mat curr;
		capture >> tmp;
		if (tmp.empty())
			break;
		cvtColor(tmp, curr, COLOR_RGB2GRAY);

		// オプティカルフローの計算
		Mat flow;
		deepflow->calc(prev, curr, flow);

		// 表示するようにX成分とY成分に分解
		Mat flowXY[2];
		split(flow, flowXY);

		// 極座標に変換
		Mat magnitude, angle;
		cartToPolar(flowXY[0], flowXY[1], magnitude, angle, true);

		//  色相(H)はオプティカルフローの角度
		//  彩度(S)は0~1に正規化したオプティカルフローの大きさ
		//  明度(V)は1
		Mat hsvPlanes[3];
		hsvPlanes[0] = angle;
		hsvPlanes[1] = magnitude;
		hsvPlanes[2] = Mat::ones(angle.size(), CV_32F);
		//  HSVを合成して一枚の画像にする
		Mat hsv;
		merge(hsvPlanes, 3, hsv);

		// 表示
		imshow("DeepFlow", hsv);

		// 前のフレームを保存
		prev = curr;
	}
}

結果はこんな感じ.かなり時間かかった.
ちょいちょい真っ赤になるのは仕様なのかバグなのか.


OpenCVでDeepFlow - YouTube

OpenCV3.0.0-alphaの特徴抽出・マッチングまとめ

OpenCV3.0.0-alphaのパッケージが公開されたと話題になっていたので使ってみる.

Change Logを見るとAKAZE特徴量が組み込まれている.
AKAZE特徴量の紹介と他特徴量との比較 - 遥かへのスピードランナー
によるとAKAZE特徴量は,以前のOpenCVでもakaze-opencvというパッケージを入れれば使えたが,OpenCV3.0.0-alphaでは元々組み込まれているのでそのまま使えるようだ.

逆にSIFTやSURFなんかは元々OpenCVで使えたが
OpenCV 3.0.0-alphaでSIFT/SURFを使う | .COM-POUND
によると,opencv_contribに移動されてしまいOpenCVと一緒にビルドしないと使えないようである.

OpenCV3.0.0-alphaでの変更点まとめ

以前当ブログで
OpenCVで画像の特徴抽出・マッチングを行う - whoopsidaisies's diary
にOpenCV2.4.7の画像の特徴抽出あたりをまとめた記事を書いていたので,今回はOpenCV3.0.0-alphaでの変更点をまとめてみる.

特徴点抽出(FeatureDetectorインターフェース)

FeatureDetector
OpenCV2.4.7 FAST,FASTXSTARSIFTSURF,ORB,BRISK,MSER,GFTT,HARRIS,Dense,SimpleBlob
OpenCV3.0.0-alpha FAST,ORB,BRISK,MSER,GFTT,HARRIS,SimpleBlob,KAZEAKAZE
opencv_contrib STAR,SIFT,SURF

赤字はOpenCV3.0.0-alphaで追加されたもの.
青字はopencv_contribを入れれば使えるもの.
灰色はOpenCV3.0.0-alphaでなくなってしまってopencv_contribにも入ってないもの.

FASTXとDenseはなくなってしまったようである.

特徴記述(DescriptorExtractorインターフェース)

DescriptorExtractor
OpenCV2.4.7 SIFTSURFBRIEF,BRISK,ORB,FRIEK
OpenCV3.0.0-alpha BRISK,ORB,KAZEAKAZE
opencv_contrib SIFT,SURF,BRIEF,FREAK

赤字はOpenCV3.0.0-alphaで追加されたもの.
青字はopencv_contribを入れれば使えるもの.

特徴点マッチング(DescriptorMatcherインターフェース)

DescriptorExtractor
OpenCV2.4.7およびOpenCV3.0.0-alpha BruteForce,BruteForce-L1,BruteForce-SL2,BruteForce-Hamming,BruteForce-Hamming(2),FlannBased

DescriptorMatcherに関しては変わりがないようである.

AKAZEを使ってみる

AKAZEを使ってみたかったので,OpenCV3.0.0-alphaで特徴抽出を行ってみる.ついでに他のアルゴリズムとも画像を比較してみる.特徴抽出のソースコードは以下.

cv::String detectorNames[] = {"AKAZE", "KAZE", "FAST", "ORB", "BRISK", "MSER", "GFTT", "HARRIS", "SimpleBlob",};
auto img = cv::imread("Penguins.jpg");

for (int i = 0; i < 9; i++)
{
	auto detector = cv::FeatureDetector::create(detectorNames[i]);
	std::vector<cv::KeyPoint> keyPoints;
	detector->detect(img, keyPoints); 

	cv::Mat output;
	cv::drawKeypoints(img, keyPoints, output, cv::Scalar::all(-1),cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

	cv::imwrite(detectorNames[i] + ".bmp", output);
}


AKAZE

f:id:whoopsidaisies:20140820194415j:plain


KAZE

f:id:whoopsidaisies:20140820194424j:plain


FAST

f:id:whoopsidaisies:20140820194432j:plain


ORB

f:id:whoopsidaisies:20140820194437j:plain


BRISK

f:id:whoopsidaisies:20140820194444j:plain


MSER

f:id:whoopsidaisies:20140820194454j:plain


GFTT

f:id:whoopsidaisies:20140820194459j:plain


HARRIS

f:id:whoopsidaisies:20140820194510j:plain


SimpleBlog

f:id:whoopsidaisies:20140820194515j:plain