OpenCV for Androidでキャプチャしたカメラ画像にフレームを合成
卒業研究も無事に終わり、中途半端に終わってしまったソースコードの手直しとかしてました。
卒業研究周りはこの辺がもう少し落ち着いたらまた手を付けて行きたいなぁと。
その時に解決できた事柄を1個メモ。
OpenCV for Android 2.4.6のサンプル OpenCV Tutorial 1 -Camera Previewを使って枠付きの写真を撮影する作ってみます。
自分がメモしたいと思ったところのみに絞るのでプロジェクトの追加方法は割愛します(閲覧している方は0に近いと思いますが、もし気になる方いらっしゃればご一報を。追記します)
Tutorial1Activity.javaの中にOnCameraFrameメソッドがあります。
この中に記述を追記することで、表示するカメラの映像に編集を加えます。
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
return inputFrame.rgba();
}
元々これだけの記述しかありませんが、これを色々変えていじります。
かぶせる枠はresフォルダ-drawableフォルダの中へ。
こんな具合です。sunset.pngが枠の画像です。
以下のコードを記述することでsunset.pngの画像ファイル(PNG)をビットマップとして取り込むことができます。(要import android.graphics.BitmapFactory;記述)
Resources r = getResources();
Bitmap bmp_frame = BitmapFactory.decodeResource(r, R.drawable.sunset);
例えば、今回のsunset.pngというファイル名であれば、
R.drawable.sunset
という名前のidの変数をdecodeResource関数のid部分に記述します。
後で画像を合成する際に、サイズを合わせる必要があるため
Bitmap型の時点でサイズの変換を行います。今回取り込むカメラ画像は640x480なのでそれに合わせます。
bmp_frame = Bitmap.createScaledBitmap(bmp_frame, 640, 480, false);
これでPNGの画像はBitmap型になります。
しかしBitmap型のままでは合成ができないので、bitmapToMat関数を使ってMat型に変換します。(要import org.opencv.android.Util;記述?<筆者はimport.org.opencv.android.*;で対処>)
Mat mat = new Mat(3,3,CvType.CV_32F);
Utils.bitmapToMat(bmp_frame, mat);
変換した後の置き場として変数matを作りました。
ちなみにブランクのMatを作ろうとしてずっとnullでやってエラー吐いてました...
ちゃんとコンストラクタで定義しましょう。(恥ずかしい)
Mat mat2 = new Mat(3,3,CvType.CV_32F);
mat2 = inputFrame.rgba();
カメラ画像用のMatも用意しておきます。このサンプルコードだと、
inputFrame.rgba();
でカメラ画像のMatを取得することができます。
そして、Coreクラスのaddメソッドで2つのMatを合成します。
Core.add(mat2, mat, mat);
ここまでの流れをざっと示すと以下のソースコードになるはずです。
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
Resources r = getResources();
Bitmap bmp_frame = BitmapFactory.decodeResource(r, R.drawable.sunset);
bmp_frame = Bitmap.createScaledBitmap(bmp_frame, 640, 480, false);
Mat mat = new Mat(3,3,CvType.CV_32F);
Utils.bitmapToMat(bmp_frame, mat);
Mat mat2 = new Mat(3,3,CvType.CV_32F);
mat2 = inputFrame.rgba();
Core.add(mat2, mat, mat);
return mat;
}
これを記述して起動するとこんな感じになります。枠の画像は某フォロワさん作。
んー、このコードだと半透明になってしまうのが...元の画像にアルファ値含まれているんだろうか。
アルファ値削除か、マスク画像使う手法を試していないので後でやってみます。
============================
【ここから反省会】
Matを合成する部分?でエラーを吐いていたのですがその原因が分からず滞っていました。
こんなの。
02-22 04:02:22.634: E/cv::error()(18106): OpenCV Error: Assertion failed (src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols) in void Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv*, jclass, jlong, jobject, jboolean), file /home/reports/ci/slave_desktop/50-SDK/opencv/modules/java/generator/src/cpp/utils.cpp, line 97
02-22 04:02:22.634: E/org.opencv.android.Utils(18106): nMatToBitmap catched cv::Exception: /home/reports/ci/slave_desktop/50-SDK/opencv/modules/java/generator/src/cpp/utils.cpp:97: error: (-215) src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols in function void Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv*, jclass, jlong, jobject, jboolean)
02-22 04:02:22.634: E/CameraBridge(18106): Mat type: Mat [ 825*675*CV_8UC4, isCont=true, isSubmat=false, nativeObj=0xab5160, dataAddr=0x5d916010 ]
02-22 04:02:22.634: E/CameraBridge(18106): Bitmap type: 640*480
02-22 04:02:22.634: E/CameraBridge(18106): Utils.matToBitmap() throws an exception: /home/reports/ci/slave_desktop/50-SDK/opencv/modules/java/generator/src/cpp/utils.cpp:97: error: (-215) src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols in function void Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv*, jclass, jlong, jobject, jboolean)
これが、2つのMatファイルのサイズの相違を示していたなんて...
02-22 04:02:22.634: E/CameraBridge(18106): Mat type: Mat [ 825*675*CV_8UC4, isCont=true, isSubmat=false, nativeObj=0xab5160, dataAddr=0x5d916010 ]
これが枠の画像(825*675)で
02-22 04:02:22.634: E/CameraBridge(18106): Bitmap type: 640*480
bmp_frame = Bitmap.createScaledBitmap(bmp_frame, 640, 480, false);
MacでLaTeX
MacBookにはTeXShopっていう名前のエディタがあるようで、
これを使うとTeXファイルの編集、pdfファイルへの出力ができます。
ただ、なんかウチの大学のMacBook、LaTeX環境設定の部分でポカったらしいので対処法とか載せときます。
今のところ確認しているのは2つ。
1. LaTeXのコマンドファイルのパスの形式がおかしい(多分みんなこれ)
2.X11をインストールしたため、必要なライブラリファイルが移動されていた(一部の人?GIMP入れた人も相当?)
このエラーが仰るとおりパスが正しく設定されてません
...というか元のファイルの名前が間違っています。
なので、元のファイルの名前を書き替えてしまいます。
ファイルがあるはずです。
その名も、「pltex2pdf-utf8」です。
寝よ
Mac OSX SnowLeopardXcode 3.2.6 C++でのLeap Motionの環境構築
自分のための忘備録。
そもそもがSnowLeopardが推奨環境じゃないので、多分参考になるのはごくわずかな人
なんだろうなぁとか考えてますが、まあ忘れないようにと書いておきます。
Xcodeの設定画面がver 4.〜とver.3〜では全く違っていたので、
そこだけです。実際のところ。
さて、順番を一通り書いていきます。
プロジェクトの作成はコマンドラインツールで。
名前は今回は「leapDemo」とします。
プロジェクトを作成できたら、/LeapSDK/libにある、「libLeap.dylib」を
Xcodeの「グループとファイル」の欄にドラッグ&ドロップします。
で、このdylibのパスを環境変数として書き込まなければならないんですが、
その場所がイマイチ分かりづらくて...
実行可能ファイルの中身を右クリックして「情報を見る」にあるんですね。
これで1時間近くも迷ってました... ははは
ここは、下の欄の「環境に設定される変数」に
名前を「DYLD_LIBRARY_PATH」として、値は先ほど入れたlibLeap.dylibのあるディレクトリのパスを入れればよいです。
(注!9/29追記・変更)
変更するまでは、libLeap.dylibのパスを指定してました。 つまり /Users/k10105kk/Documents/LeapSDK/lib/libLeap.dylib です。
正しくは/Users/k10105kk/Documents/LeapSDK/lib です。
あのままだとビルド時に下記のエラーが出ます。
dyld: Library not loaded: @loader_path/libLeap.dylib
Referenced from: /Users/k10105kk/Documents/workspace/kenshouLeap/build/Debug/kenshouLeap
Reason: no suitable image found. Did find:
/Users/k10105kk/Documents/LeapSDK/lib/libLeap.dylib/libLeap.dylib: stat() failed with errno=20
フォーラム見てみると困ってらっしゃる方とかいらしてたみたいなので、念のため。
このエラーが出てたら一度DYLD_LIBRARY_PATHの値をチェックすると良いかもしれません。
あとは/LeapSDK/include/leap.hを入れて、
プロジェクトの情報を開いて、
ユーザー定義の設定をします。
これがまた分かりにくいかったね。
んで、設定(名前)をLEAPSDK_PATHとして、値にはLeapSDKのパスを指定。
そして、ヘッダ検索パスには、$(LEADSDK_PATH)/include を、
ライブラリ検索パスには $(LEADSDK_PATH)/lib を入力して準備バッチリ。
あとはmain.cppにソースコードを書き込んで実行すれば動きます。
LeapSDK/samples/Sample.cpp をコピペするなりすれば大丈夫かと。
多分またわかんなくなったりしたら書き直すと思います。多分。
さて、モチベも戻ったので進捗の資料作りに戻らねば...
横置きLeapMotion
なんとかいけました!
どうやらLeapmotionは、USB接続したその時に、
自動的に位置の初期設定を行っているようで、
こういう状態にしたままUSB接続にするとうまくいくようです。
シュミレータだとXYZ軸が実際と異なるためか、
方向が違って見えますが、まあそうでしょう。
その都度座標データに合わせればいいか。
Leap Motionを手話認識として使う為には。
現在卒業研究で手話認識の研究を進めています。
たまたま紹介でこの機器を紹介してもらったのですが、
生憎時期が合わず、研究費では買わず、個人的に扱うことにしました。
まあ趣味で楽しもうかなぁ...って思ったんですが、これが意外と精度がよかったんですね。
ちゃんと指先まで捉えてくれます。
さらに手の裏表や、指の動き(スワイプ)も認識してくれるので、これはもしかしたら本当に研究材料として使えるかもしれない!
と思ったんですが、それがどうもうまくいかないわけでして。
結局趣味の範囲でやってることで、研究室の進捗報告でも発表できなく、お流れになってしまう可能性大なのでざざっとこっちで書いてしまおうか。
下から撮っているという特性上、LEAP Motionはこういう手の形はしっかりとくれます。
LEAP Motion機器と平行にあるような向きの形です。
セッティングのビジュアライザを使うとこんな感じ。 指先までクッキリです。
この手の形を縦にしてみましょう。
こんな感じ。 今度はモニターに平行になる形です。
すると...
んー、なかなかいい精度は出てこないようです...
手の裏表は正確に捉えているようですが...。
実は手話はこの手の向きの形の単語が多いです。
つまり、LEAP Motion機器と垂直の位置にある形です。
もちろん、前者のように、平行になる形の手の形もあるのですが... むしろどちらも捉えられなければ。
また、手話の一種である、指のポーズで文字1文字を表す、指文字も、多くがこの形です。
しかし、自分が調べた中では、指文字はほとんどがLEAP Motion機器に垂直の位置の手の形がほとんどです。
手話のようにオールマイティである必要性は少ないので、もしかしたら有用性はあるのかも...?
動きが必要である「の」や「ん」も捉えられるので、うまくいけばかなり精度がいいものが作れるのかもしれません。問題は指文字をどうつかうのーってところなんですが。
んー、しかしLEAP Motionを置く位置を変えたとして、
キャリブレーションの設定はいかにすればいいのか。
こうなればいいのかな...
はてさて。どうすればいいのやら。
もしかしたら自分の動作環境(Mac OS X Snow Lepard<推奨環境対象外>)なのが悪いのかもしれませんが、
記憶が正しければ、研究室のPC(Windows 7、Core i7<推奨環境対象>)
でも同じだったような感じだったと思います。
んー、どうしましょ。
Leapmotionが家にやってきた!
やって参りました。
ドライバもインストールできるようになったので、いろいろと試しています。
Leap Motion
結局研究の対象にしようか迷ったまんま、注文だけはしてそのままにしてたけど
そろそろ出荷スタートらしい。
amazon で買うと13800円かぁ。
公式で買うと送料込で99ドルくらいだったかなぁと思って計算してみたけど、
そんなに違うんだ...
個人的にやってみようと思ってSDKもあらかじめダウンロードしてみました。
ちょっとだけ楽しみ。