[AndroidStudio で OpenCV をインポートする]
(https://qiita.com/ohwada/items/71eb18296aac46f9f5ee)
の続きです。
概要
Android 用 OpenCV には、
8個のサンプルが同封されている。
そのうち camerapreview は、
基本となるサンプルなので、少し詳しく説明する。
OpenCV の Java API に関するドキュメントは 下記の JavaDoc 由来のものがある。
[OpenCV Java documentation]
(https://docs.opencv.org/master/javadoc/index.html)
しかし、 Android API に関するドキュメントはないようです。
ないようです
ソースコードを解読した。
OpenCV の Mat
OpenCV で扱う画像の形式です。
参考 cv::Matの基本処理
tutorial-1-camerapreview
カメラのプレビュー画像を表示するサンプルです。
下記の説明には、
Java API または Native camera API を使用するとある
Native camera API は、古いバージョンにはあったようだが、
最新バージョン 4.1.2 には、見当たらず。
opencv.org : OpenCV4Android Samples
アプリを作成する。
(1) 新規のプロジェクトを作成する
File -> New -> New Project -> Empty Activity
(2) 前回の記事で作った Android のライブラリをインポートする
File -> New -> Import Module -> Import JAR / AAR Package
(3) 依存関係を設定する
File -> Project Structure
(4) AndroidManifest にカメラのアクセス許可を追加する。
<uses-permission android:name="android.permission.CAMERA"/>
(5) レイアウトファイルに、JavaCameraView またはJavaCamera2View を配置する。
いずれも SurFaceView を継承している。
JavaCameraView は、旧来の Camera API を使用する。
JavaCamera2View は、API 21 からサポートされた Camera2 API を使用する。
<FrameLayout >
<org.opencv.android.JavaCameraView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone"
android:id="@+id/camera_view"
opencv:show_fps="true"
opencv:camera_id="any" />
</FrameLayout>
属性 (attributes)
opencv:show_fps
true のとき、ビューの左上に、描画速度 (fps)を表示する
opencv:camera_id
カメラを指定する
front: 前面カメラ
back: 背面カメラ
any: 第1カメラを自動判定
(6) CameraActivity を継承して MainActivity.java を作成する。
public class MainActivity extends CameraActivity implements CvCameraViewListener2 {
public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
// カメラビューを取得する
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.camera_view);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
}
public void onResume()
{
// OpenCV をロードする
if (OpenCVLoader.initDebug()) {
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
public void onManagerConnected(int status) {
// カメラビューを有効にする
mOpenCvCameraView.enableView();
}
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
// カメラ画像をカラーで表示する
return inputFrame.rgba();
}
OpenCVLoader
OpenCV ライブラリの初期化を行うヘルパークラスです。
下記のメソッドを持つ。
-
public static boolean initDebug()
OpenCVライブラリをロードして初期化する。
初期化が成功した場合にtrueを返す。 -
public static boolean initDebug(boolean InitCuda)
CUDA ランタイムライブラリをロードして、
OpenCVライブラリを初期化する。 -
public static boolean initAsync(String Version, Context AppContext,
LoaderCallbackInterface Callback)
OpenCV Engine service を使用してOpenCVライブラリをロードおよび初期化する。
BaseLoaderCallback
OpenCVLoader のコールバッククラスです。
2つのメソッドを持つ。
-
public void onManagerConnected(int status)
OpenCVライブラリの初期化後に呼び出されるコールバックメソッド。
引数 status 初期化のステータス -
public void onPackageInstall(final int operation, final InstallCallbackInterface callback)
パッケージのインストールが必要な場合に呼び出されるコールバックメソッド。
引数 operationは、
InstallCallbackInterface の定数
引数 callbackは、
インストール(install)およびキャンセル(cancel)の2つメソッドを持つオブジェクト
初期化ステータス定数
-
static final int SUCCESS = 0;
OpenCVの初期化が正常に終了しました。 -
static final int MARKET_ERROR = 2;
Google Play(Google Play Market)を呼び出すことはできません。 -
static final int INSTALL_CANCELED = 3;
OpenCVライブラリのインストールはユーザーによってキャンセルされました。 -
static final int INCOMPATIBLE_MANAGER_VERSION = 4;
OpenCVマネージャーサービスのこのバージョンは、アプリと互換性がありません。
おそらく、サービスの更新が必要です。 -
static final int INIT_FAILED = 0xff;
OpenCVライブラリの初期化に失敗しました。
InstallCallbackInterface
OpenCV パッケージのインストールに関するコールバックインターフェイス。
3つのメソッドを持つ
-
public void install();
インストールが承認されました。 -
public void cancel();
インストールはキャンセルされます。 -
public void wait_install();
パッケージのインストールを待ちます。
2つの定数を持つ
-
static final int NEW_INSTALLATION = 0;
新しいパッケージのインストールが必要です。 -
static final int INSTALLATION_PROGRESS = 1;
パッケージのインストールが進行中です。
### CvCameraViewListener2
CameraView に関するListener クラス。
3つのメソッドを持つ。
-
public void onCameraViewStarted(int width, int height)
このメソッドは、カメラのプレビューが開始されたときに呼び出される。
このメソッドが呼び出された後、
onCameraFrame()コールバックを介して、カメラ画像が配信される。
引数は、配信されるカメラの幅(width)と高さ(height) -
public void onCameraViewStopped()
このメソッドは、何らかの理由でカメラのプレビューが停止したときに呼び出される。
このメソッドが呼び出された後、フレームはonCameraFrame()コールバックを介したカメラ画像の配信は停止する。 -
public Mat onCameraFrame(CvCameraViewFrame inputFrame)
このメソッドは、カメラ画像の配信を行う必要があるときに呼び出される。
引数 inputFrame は、カメラ画像。
戻り値は、Mat形式で、画面に表示される。
### CvCameraViewFrame
カメラデバイスから1つの画像を表す抽象クラスです。
onCameraFrame コールバック用に使用される。
2つのメソッドを持つ。
-
public Mat rgba();
このメソッドは、カメラ画像を カラー(RGBA) のMat形式で返す。 -
public Mat gray();
このメソッドは、カメラ画像を グレースケール(single channel gray scale ) のMat形式で返す。
### camerapreview の処理の流れ
アプリが起動すると、
CameraActivity#onStart が呼ばれる。
Activity#requestPermissions を実行して、
カメラのアクセス許可を要求する。
JavaCamera2View#enableView が実行されると、
Camera2 API と ImageReader を使用して、
カメラデバイスからカメラ画像を取得する。
カメラ画像を OpenCV の Mat 形式に変換する。
カメラ画像が更新されると、
CvCameraViewListener2#onCameraFrame を呼び出して、
SurFaceView に描画する。
少し詳しく処理の流れを追ってみた。
-
JavaCamera2View#enableView
-
CameraBridgeViewBase#enableView
-
CameraBridgeViewBase#checkCurrentState
-
CameraBridgeViewBase#processEnterState
-
CameraBridgeViewBase#onEnterStartedState
-
JavaCamera2View#connectCamera
-
JavaCamera2View#initializeCamera
CameraManager#openCamera を実行して、
カメラをオープンする。 -
JavaCamera2View#createCameraPreviewSession()
ImageReader#newInstance を実行して、
ImageReader を生成する。 -
ImageReader.OnImageAvailableListener#onImageAvailable
JavaCamera2Frame(image) を実行して、
Android の Image を OpenCV の Mat に変換する。 -
CameraBridgeViewBase#deliverAndDrawFrame
-
CvCameraViewListener2#onCameraFrame を呼び出す。
戻り値の OpenCV の Mat を Android の Bitmap に変換する。
Bitmap を SurFaceView の Canvas に描画する。
アプリを実行する
analyze_apk すると、
下記の2つが同封されていることが確認できる。
- libopencv_java4.so
- libc++_shared.so
アプリが起動すると、
カメラのアクセス許可を要求する。
「許可」すると、カメラのプレビュー画像を表示する
サンプルコードをgithub に公開した。
https://github.com/ohwada/Android_Samples/tree/master/Opencv42