前のチュートリアル: Android開発入門
次のチュートリアル: Android端末でディープネットワークを実行する方法
| |
| 原著者 | Alexander Panov, Rostislav Vasilikhin |
| 互換性 | OpenCV >= 4.9.0 |
このチュートリアルは、Androidプロジェクト内でOpenCVライブラリを使用する手助けをするために作成された。
このガイドはUbuntuで確認されたが、プラットフォーム依存の部分は含まないため、Android StudioおよびOpenCV4Android SDKがサポートする任意のOSと互換性があるはずである。
このチュートリアルでは、以下がインストールおよび設定されていることを前提とする:
上記のいずれかについて助けが必要な場合は、Android開発入門 ガイドを参照してほしい。
これらの手順を入念に踏んだ後でエラーが発生した場合は、OpenCV フォーラム を通じて気軽に連絡してほしい。できる限り手助けする。
SDKを使ったHello OpenCVサンプル
このセクションでは、OpenCVの読み込み以外は何もしない簡単なアプリを作成する。次のセクションでは、これを拡張してカメラをサポートする。
この手順に加えて、いくつかのビデオガイドを利用できる。例えば こちら である
- Android Studioを開き、Empty Views Activity を選択して空のプロジェクトを作成する
- Setup the project:
- Java 言語を選択する
- Groovy DSL ビルド構成言語を選択する
- Choose Minumum SDK with the version number not less than was used during OpenCV 4 Android build
- もし分からない場合は、
OpenCV-android-sdk/sdk/build.gradle ファイルの android -> defaultConfig -> minSdkVersion で確認できる
- File -> New -> Import module... をクリックし、OpenCV SDKのパスを選択する
- モジュール名を
OpenCV に設定し、Finish を押す
OpenCVは実験的なKotlinサポートも提供している。Android Kotlinプラグインを MyApplication/OpenCV/build.gradle ファイルに追加してほしい:
plugins {
id 'org.jetbrains.kotlin.android' version '1.7.10' #version may differ for your setup
}
このように: 
これを行わないと、エラーが発生することがある:
Task failed with an exception.
-----------
* Where:
Build file '/home/alexander/AndroidStudioProjects/MyApplication/opencv/build.gradle' line: 4
* What went wrong:
A problem occurred evaluating project ':opencv'.
> Plugin with id 'kotlin-android' not found.
この修正方法は こちら で見つかった
OpenCVプロジェクトは buildConfig 機能を使用する。MyApplication/OpenCV/build.gradle ファイルの android ブロックでこれを有効にしてほしい:
buildFeatures{
buildConfig true
}
このように: 
これを行わないと、エラーが発生することがある:
JavaCameraView.java:15: error: cannot find symbol import org.opencv.BuildConfig; ^ symbol: class BuildConfig location: package org.opencv
この修正方法は こちら と こちら で見つかった
- Add the module to the project:
- File -> Project structure... -> Dependencies -> All modules -> + (Add Dependency button) -> Module dependency をクリックする
- OpenCVの関数を使用する前に、まずライブラリを読み込む必要がある。アプリケーションに他のOpenCV依存のネイティブライブラリが含まれている場合は、OpenCVの初期化 後 にそれらを読み込むべきである。アプリ起動時にライブラリを読み込むため、以下のコードを追加する:
if (OpenCVLoader.initLocal()) {
Log.i(TAG, "OpenCV loaded successfully");
} else {
Log.e(TAG, "OpenCV initialization failed!");
(Toast.makeText(this, "OpenCV initialization failed!", Toast.LENGTH_LONG)).show();
return;
}
このように: 
- サンプルを確認するデバイスを選択し、
run ボタンを押してコードを実行する
Maven Centralを使ったHello OpenCVサンプル
OpenCV 4.9.0 以降、OpenCV for AndroidパッケージはMaven Centralで利用可能であり、Gradleの依存関係として自動的にインストールできる。このセクションでは、Maven Centralを使ってOpenCVを読み込む以外は何もしない簡単なアプリを作成する。
- Android Studioを開き、Empty Views Activity を選択して空のプロジェクトを作成する
- Setup the project:
- Java 言語を選択する
- Groovy DSL ビルド構成言語を選択する
- Minumum SDK として、OpenCVがサポートするバージョン以上のバージョン番号を選択する。4.9.0 の場合、最小SDKバージョンは 21 である。
build.gradle を編集し、以下のようにOpenCVライブラリをDependenciesリストに追加する: dependencies {
implementation 'org.opencv:opencv:4.9.0'
}
4.9.0 は 公式リリース として利用可能な任意のバージョンに置き換えることができる。
- OpenCVの関数を使用する前に、まずライブラリを読み込む必要がある。アプリケーションに他のOpenCV依存のネイティブライブラリが含まれている場合は、OpenCVの初期化 後 にそれらを読み込むべきである。アプリ起動時にライブラリを読み込むため、以下のコードを追加する:
if (OpenCVLoader.initLocal()) {
Log.i(TAG, "OpenCV loaded successfully");
} else {
Log.e(TAG, "OpenCV initialization failed!");
(Toast.makeText(this, "OpenCV initialization failed!", Toast.LENGTH_LONG)).show();
return;
}
このように: 
- サンプルを確認するデバイスを選択し、
run ボタンを押してコードを実行する
カメラビューのサンプル
このセクションでは、前のセクションで作成した空のOpenCVアプリを拡張し、カメラに対応させる。カメラのフレームを取得し、画面に表示する。
- カメラのパーミッションが必要であることをシステムに伝える。次のコードをファイル
MyApplication/app/src/main/AndroidManifest.xml に追加する: <uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>
このようになる: 
activity_main.xml レイアウトを開き、"Hello World!" というテキストを持つTextViewを削除する
これはCodeモードまたはSplitモードで、XMLファイルから TextView ブロックを削除することでも行える。
レイアウトにカメラビューを追加する:
- レイアウトの記述にスキーマを追加する:
xmlns:opencv="http://schemas.android.com/apk/res-auto"
TextView を org.opencv.android.JavaCameraView ウィジェットに置き換える: <org.opencv.android.JavaCameraView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone"
android:id="@+id/tutorial1_activity_java_surface_view"
opencv:show_fps="true"
opencv:camera_id="any" />
- レイアウトの警告が出た場合は、
android:layout_width と android:layout_height プロパティの fill_parent の値を match_parent に置き換える
次のようなコードになる:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:opencv="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<org.opencv.android.JavaCameraView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone"
android:id="@+id/tutorial1_activity_java_surface_view"
opencv:show_fps="true"
opencv:camera_id="any" />
</FrameLayout>
- メインクラスを
org.opencv.android.CameraActivity から継承する。CameraActivityはカメラのパーミッション要求と、CVアプリケーションに必要なその他のユーティリティを実装している。オーバーライドすべき重要なメソッドは onCreate、onDestroy、onPause、onResume、getCameraViewList である
- インターフェイス
org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2 を実装する。onCameraFrame メソッドはレンダリング用の内容を持つ Mat オブジェクトを返す必要がある。このサンプルはプレビュー用にカメラフレームをそのまま返すだけである: return inputFrame.rgba();
- Allocate
org.opencv.android.CameraBridgeViewBase object:
- これはアプリ起動時(
onCreate メソッド)に生成され、このクラスをリスナーとして設定する必要がある
- 一時停止/再開時(
onPause、onResume メソッド)に無効化/有効化する必要がある
- アプリ終了時(
onDestroy メソッド)に無効化する必要がある
getCameraViewList で返す必要がある
必要に応じて、画面を暗くしたりロックしたりするのを禁止できる:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
最終的に、次のようなソースコードになる:
package org.opencv.samples.tutorial1;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.Toast;
import java.util.Collections;
import java.util.List;
public class Tutorial1Activity extends CameraActivity implements CvCameraViewListener2 {
private static final String TAG = "OCVSample::Activity";
private CameraBridgeViewBase mOpenCvCameraView;
public Tutorial1Activity() {
Log.i(TAG, "Instantiated new " + this.getClass());
}
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
if (OpenCVLoader.initLocal()) {
Log.i(TAG, "OpenCV loaded successfully");
} else {
Log.e(TAG, "OpenCV initialization failed!");
(Toast.makeText(this, "OpenCV initialization failed!", Toast.LENGTH_LONG)).show();
return;
}
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.tutorial1_surface_view);
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
}
@Override
public void onPause()
{
super.onPause();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
@Override
public void onResume()
{
super.onResume();
if (mOpenCvCameraView != null)
mOpenCvCameraView.enableView();
}
@Override
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}
@Override
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
@Override
public void onCameraViewStarted(int width, int height) {
}
@Override
public void onCameraViewStopped() {
}
@Override
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
return inputFrame.rgba();
}
}
これで完成である。あとはデバイス上でコードを実行して動作を確認できる。
いくつかの最も重要なステップについて見ていこう
UIを持つすべてのAndroidアプリケーションはActivityとViewを実装しなければならない。最初のステップでは、空のActivityとデフォルトのViewレイアウトを作成する。最もシンプルなOpenCV中心のアプリケーションでは、OpenCVの初期化を行い、カメラからのプレビューを表示するためのViewを作成し、カメラからフレームを取得して処理するために CvCameraViewListener2 インターフェイスを実装する必要がある。
まず、XMLレイアウトを使ってアプリケーションのViewを作成する。このレイアウトは org.opencv.android.JavaCameraView クラスのフルスクリーンコンポーネント1つだけで構成される。このOpenCVクラスは、SurfaceView を拡張した CameraBridgeViewBase を継承しており、内部では標準のAndroidカメラAPIを使用している。
CvCameraViewListener2 インターフェイスを使うと、カメラからフレームを取得した後、画面に描画される前に処理ステップを追加できる。最も重要なメソッドは onCameraFrame である。これはコールバック関数であり、カメラからフレームを取得したときに呼び出される。onCameraFrame 関数は、画面に描画されるRGBAフレームを返すことが期待される。
コールバックは、カメラからのフレームを CvCameraViewFrame クラスのオブジェクトとして自分のクラスに渡す。このオブジェクトには rgba() と gray() メソッドがあり、カラーフレームまたは1チャンネルのグレースケールフレームを Mat クラスのオブジェクトとして取得できる。
- 覚え書き
CvCameraViewFrame オブジェクトを onCameraFrame コールバックの外で保存したり使用したりしてはならない。このオブジェクトは独自の状態を持たず、コールバック外での動作は予測できない!