Edited at

THETAの中でOpenCVを動かす【プレビューフレーム応用編】


はじめに

こんにちは、リコーの@roohii_3です。

これまでTHETAの中でOpenCVを動かすことに関して記事を書いてきました。

本記事は「THETAの中でOpenCVを動かす【プレビューフレーム取得編】」の応用編です。

プレビューフレームから「動体検知」し、何か動くものを認識したら写真を撮る、といったようにTHETAを監視カメラ的なものに改造してみました。

image.png

コードは以下で公開しています。

https://github.com/theta-skunkworks/theta-plugin-opencv-detection-sample

※ 実装はいろいろと手を抜いてます。流用する場合はご注意を…。


開発環境


  • OpenCV Android pack ver. 3.4.5

  • Android Studio ver. 3.3+

  • gradle ver. 5.1.1

  • RICOH THETA V Firmware ver. 3.00.1


実装

事前準備・OpenCVの導入手順などは前回記事の「事前準備」を見てください。

実装は、前回のコードをベースに動体認識静止画撮影の処理を追加しています。


動体認識

動体認識アルゴリズムは以下のような流れです。

それぞれの処理はOpenCVのチュートリアルに載っているようなものです。

対象言語はPythonですが、OpenCV-Pythonチュートリアル(日本語訳版)も参考になります。


  1. 背景差分

  2. 二値化

  3. モルフォロジー(ノイズ除去)

  4. 領域検出

  5. バウンダリーボックスの取得

実際にどう実装しているかは、GitHubから MainActivity.javaonCameraFrame() メソッドを見てみてください。


静止画撮影

静止画撮影処理の部分は、OpenCVの tutorial-3-cameracontrolTHETA Plug-in: CameraAPI Capture Plugin を参考にしました。

どちらとも takePicture()Camera.PictureCallback という静止画撮影に必要なメソッドの実装がされていますが、本記事のコードでは ThetaController.java で実装しています。


Camera APIパラメータ

前回記事でも触れたように、THETAには独自のCamera APIパラメータがあります。

たとえば撮影時には、以下のパラメータを設定しています。

Camera.Parameters params = mCamera.getParameters();

// 画像サイズ
params.setPictureSize(5376, 2688);

// 静止画撮影モード
params.set("RIC_SHOOTING_MODE", "RicStillCaptureStd");

// 自動露出モード
params.set("RIC_EXPOSURE_MODE", "RicAutoExposureP");

// スティッチングの種類を"DynamicStitching"に設定
params.set("RIC_PROC_STITCHING", "RicDynamicStitchingAuto");


スティッチング

上のコード例の一番最後にあるように、ここでは「スティッチングの種類」のパラメータに"RicDynamicStitchingAuto"を設定しています。

これは被写体に応じて精密なスティッチングを行うものですが、少し処理時間がかかります。

「スティッチングは簡易的で良いので、処理時間を速くしたい」という方は"RicStaticStitching"を使うと良いと思います。

他にもスティッチングの種類を示すパラメータがあるので、作るものに応じて使い分けてみてください。

パラメータ値と特徴を以下にまとめておきます。

(参考: THETA Plug-inドキュメント > Camera API

パラメータ値
特徴

“RicNonStitching”
スティッチングしない(魚眼画像が横に2枚並んだ状態になる)。

“RicStaticStitching”
簡易的にスティッチングを行う。

“RicDynamicStitchingAuto”
被写体に応じて精密にスティッチングを行う。
ちょっと処理時間がかかる。

“RicDynamicStitchingSave”
精密にスティッチングするときの「スティッチングの仕方(つなぐ位置など)」の情報を保持する。
連続撮影するときに便利。
1枚目はこのパラメータ値を使い、2枚目以降は“RicDynamicStitchingLoad”を使うようにすると、1枚目と同じ具合にスティッチングできる。

“RicDynamicStitchingLoad”
RicDynamicStitchingSave”と合わせて使う。


画像サイズ

ここでは THETA V 用のプラグインを想定していますが、THETA Z1 では画像サイズを 6720x3360 に設定する必要があります。

// Z1で動かすときは、6720x3360 を設定する

params.setPictureSize(6720, 3360);

また、スティッチングの種類を示すパラメータに“RicNonStitching”を設定したときも、画像サイズが変わります。

THETA V5792x2896THETA Z17296x3648を設定します。


注意点

記事の最初に書いたように、本記事のコードはいろいろと手を抜いてます。

たとえば…


  • 静止画にExif情報が付与されない

  • THETAが動いたり、露出が変わるだけでも敏感に動体認識が反応してしまう

  • 認識処理~撮影~画像保存が単一スレッド上で行われている(本来であれば、保存など処理が重い部分は別スレッドに分けるべし)

  • 容量がいっぱいになっても撮り続けようとする(本来であれば、ストレージ容量に応じて撮影制限する必要あり)

  • (たぶん他にもある)

もし本コードを何かに流用する場合は、その辺りも注意して実装お願いします…。


実行

一番最初にプラグインを動かすときは、Vysor等を使ってパーミッションの設定をします。

プラグインストアからインストールしたプラグインは、パーミッション設定は不要です。


パーミッションの設定

Vysor等を使ってSettingsアプリを開き、"Motion Detector > Permissions"より、"Camera"、"Storage"の許可をONにします。

permissions.jpg


実行してみた様子

Vysorを使ってプラグインを実行したときは、リアルタイムで動体認識の様子を見られるようにしました。

緑色の四角で囲まれた部分が動体認識した箇所です。

screenshot.jpg

THETAの前で手を振ってみましたが、ちゃんと手が認識されました。


処理速度など

OpenCVの出力文によると、27~30fpsくらい出ていました。

fps.png

今回はプレビューのフレームサイズを最小の640x320にしました。フレームサイズによってはフレームレートが下がってしまいます。作るものに応じてフレームサイズを調整すると良いと思います。

フレームサイズを変更するには、"RIC_SHOOTING_MODE"のパラメータ値を変更します。

パラメータ値はTHETA Plug-in ドキュメント > Camera APIShooting Modeを参考にしてください。


example.java

Camera.Parameters params = mCamera.getParameters();

// プレビューのフレームサイズを 1920x960 に設定
params.set("RIC_SHOOTING_MODE", "RicMoviePreview1920");


保存ファイル

PCにTHETAを繋いで中身を確認すると、"DCIM"の下に"MotionDetector"フォルダができています。

その中に [1]動体認識したときの撮影画像 と、[2]認識したものを矩形で示した画像 が保存されます。

save_folder.png

※ 例によって手抜き実装なので、[1]、[2]の画像が保存されるタイミングがズレてます…。


おわりに

THETAの中で、果たしてリアルタイム画像処理なんてできるのかな?、と思っていましたが案外動いちゃいました。

THETA+Computer Visionに興味ありなユーザーさんがもしいたら、本記事が参考になれば幸いです。


参考


RICOH THETAプラグインパートナープログラムについて

THETAプラグインに興味を持たれた方がいれば、以下の記事もぜひご覧ください。

RICOH THETAプラグイン開発者コミュニティでは、他にも記事を書いています。

RICOH THETAプラグインについてはこちら。興味を持たれた方はtwitterのフォローとTHETAプラグイン開発コミュニティ(slack)への参加もぜひどうぞ。