読者です 読者をやめる 読者になる 読者になる

自習室

こもります

UnityでOpenCVSharpをつかってOpenCVする。マルチスレッドにもしてみる。 (Windows)

.Unity .OpenCV

はじめに

顔認識させつつ、ビデオスルーが遅れていないことを示そうとしたら、思いがけずEXILEっぽくなりました。こんばんは。

動機

OVRVISIONをしばらく前に手に入れて放置していたのですが、何か遊ぼうと思い、OpenCVを使ってみたくなりました。カメラ画にエフェクトかけてみたり。

@hecomi 先生のこれがど直球。これこれ。

Ovrvision で色んなエフェクト試してみた - 凹みTips

下調べ

最終的にOculus Riftとつなぎたいので、Unityでやります。 UnityでOpenCVを使う口のすてきな紹介記事様がこちら

UnityでOpenCVまとめ - 株式会社CFlatの明後日スタイルのブログ

  • OpenCVSharpが使いやすそう。こまめにアップデートされてるので安心感もある

  • しかしパフォーマンス落ちそうな気がするのとOpenCVならC++で書きたい、ってのとで、Unityのnative plugin化して使うのも押さえておきたい

というわけで二方向からトライすることにしました。今回はOpenCVSharpを使ってみます。

環境

ソフト
ハード

3年前のミドルエンド、のつもりデスクトップです。

基本をやってみる

まずは @kaorun55 先生

UnityでOpenCVを使う(Windowsアプリ)

これでとりあえずOpenCVSharpでカメラ画像を撮ってきてUnityで表示するとこまでできました

からの @kaorun55 先生!

せっかくだから顔認識とかしたいです。ここも @kaorun55 先生です。

OpenCVで顔検出した場所にUnityのGameObujectを追従させる

ありがとうございます、できました。

しかし、私の環境では 5~6 fps しか出ませんでした。これはつらいです。

顔認識のマルチスレッド化

認識に足を引っ張られて動画がかくかくなのはかっこわるいので、撮ってきた画像を表示しつつUnityのオブジェクトを描画するスレッドと、顔認識をするスレッドを分けましょう。

お勉強

C# のマルチスレッドの書き方を全く知らなかったのでそこの勉強からです

lockステートメントが大変便利ってことがわかった!

やってみる(本記事のメイン)

Post Position 【Unity】 スレッドを使う 記事様のやり方で二つスレッドをたて、 OpenCVで顔検出した場所にUnityのGameObujectを追従させる 記事様でやっているカメラ画像の取得と顔認識の処理をそれぞれのスレッドでやる、という方針です。

詳細はこのあたりのコードをご覧ください

UnityOpenCVSharp/FaceDetectThreaded.cs at master · izmhr/UnityOpenCVSharp · GitHub

一考

結局顔認識が 5~7 fps なのは変わっていません。

ビデオスルーがなめらかになったのは良かったのですが、顔認識が遅れているので、顔とは異なる場所にCubeが表示されてしまいます。「顔を隠す」などアプリ次第では、ビデオスルーを遅くしてでも顔認識と画像が同期している方が適切な場合もあるかもしれません。

逆に、遅い顔認識の結果を補間(予測)して使う、という方向性もあるかと思いますが、難しそうなのでまたいつか。

(おまけ) カメラ画像が崩れているのを修正

@kaorun55 さんの記事では、CVのカメラで撮ってきた画像をUnityのオブジェクトに貼り付ける際に、bmpにしたところで画像が乱れていました。これはOpenCVSharpのバグなのでしょうか…*1

f:id:AMANE:20141206230112j:plain

試行錯誤の結果なので最適とはいえませんが、修正の仕方を見つけたので報告いたします。

Jpegを経由する

実際はばらばらの場所で行っていますが、行った処理だけ抜粋します

// カメラ画像取得
// static Mat capImage;
video.Read (capImage );

// jpegのバイナリに変換
// static byte[] cvtImageJpeg;
cvtImageJpeg = capImage.ImEncode(".jpg");

// テクスチャデータとする
texture.LoadImage(cvtImageJpeg);
texture.Apply();

これでテクスチャ内での画像ずれが無くなりました

さいごに

今回のコードはGitHubにあげてあります。

izmhr/UnityOpenCVSharp · GitHub

OpenCVSharp/OpenCV の dll のたぐいは @kaorun55 さんの記事 UnityでOpenCVを使う(Windowsアプリ) を参考に入れ直してください。

*1: ちょうど最新のリリースで Mat -> Bitmap 変換のバグの修正が入ったようなのですが、これが関係しているのでしょうか…? Release 2.4.10 (11 Nov., 2014) · shimat/opencvsharp · GitHub