4
8

More than 3 years have passed since last update.

Android で OpenCV のサンプル camerapreview を試す

Last updated at Posted at 2019-11-23

AndroidStudio で OpenCV をインポートする
の続きです。

概要

Android 用 OpenCV には、
8個のサンプルが同封されている。

そのうち camerapreview は、
基本となるサンプルなので、少し詳しく説明する。

OpenCV の Java API に関するドキュメントは 下記の JavaDoc 由来のものがある。

OpenCV Java documentation

しかし、 Android API に関するドキュメントはないようです。
ないようです
ソースコードを解読した。

OpenCV の Mat

OpenCV で扱う画像の形式です。

参考 OpenCV の Mat ってやつの話

参考 cv::Matの基本処理

参考 OpenCVのMatとbyte[]の相互変換

tutorial-1-camerapreview

カメラのプレビュー画像を表示するサンプルです。

下記の説明には、
Java API または Native camera API を使用するとある
Native camera API は、古いバージョンにはあったようだが、
最新バージョン 4.1.2 には、見当たらず。

opencv.org : OpenCV4Android Samples

参考 NativeCameraViewはまだ存在しますか?

アプリを作成する。

(1) 新規のプロジェクトを作成する
File -> New -> New Project -> Empty Activity

(2) 前回の記事で作った Android のライブラリをインポートする
File -> New -> Import Module -> Import JAR / AAR Package

(3) 依存関係を設定する
File -> Project Structure

(4) AndroidManifest にカメラのアクセス許可を追加する。

AndroidManifest.xml
    <uses-permission android:name="android.permission.CAMERA"/>

(5) レイアウトファイルに、JavaCameraView またはJavaCamera2View を配置する。

いずれも SurFaceView を継承している。
JavaCameraView は、旧来の Camera API を使用する。
JavaCamera2View は、API 21 からサポートされた Camera2 API を使用する。

activity_main.xml
<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 を作成する。

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ライブラリをロードおよび初期化する。

参考 wikipedia : CUDA

参考 github : OpenCV Engineサービス

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

opencv42_analyze_apk.png

アプリが起動すると、
カメラのアクセス許可を要求する。

opencv42_permission.png

「許可」すると、カメラのプレビュー画像を表示する

opencv42_preview.png

サンプルコードをgithub に公開した。
https://github.com/ohwada/Android_Samples/tree/master/Opencv42

4
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
8