OpenCV 5.0.0
Open Source Computer Vision
読み込み中...
検索中...
見つかりません
🤖 AIによる機械翻訳(非公式) — これは OpenCV 5.0.0 公式リファレンス(英語)を AI (Claude) で自動翻訳したものです。訳に誤りを含む場合があります。正確な情報は 公式英語版(原文) を参照してください。
OpenCVによるAndroid開発

前のチュートリアル: Android開発入門
次のチュートリアル: Android端末でディープネットワークを実行する方法

原著者Alexander Panov, Rostislav Vasilikhin
互換性OpenCV >= 4.9.0

このチュートリアルは、Androidプロジェクト内でOpenCVライブラリを使用する手助けをするために作成された。

このガイドはUbuntuで確認されたが、プラットフォーム依存の部分は含まないため、Android StudioおよびOpenCV4Android SDKがサポートする任意のOSと互換性があるはずである。

このチュートリアルでは、以下がインストールおよび設定されていることを前提とする:

  • Android Studio
  • JDK
  • Android SDK および NDK
  • 省略可能: 公式の GitHubのリリースページ または SourceForge から入手できるOpenCV for Android SDK。上級者向け: 代替として、wikiの手順 に従ってソースコードからSDKをビルドすることもできる。

上記のいずれかについて助けが必要な場合は、Android開発入門 ガイドを参照してほしい。

これらの手順を入念に踏んだ後でエラーが発生した場合は、OpenCV フォーラム を通じて気軽に連絡してほしい。できる限り手助けする。

SDKを使ったHello OpenCVサンプル

このセクションでは、OpenCVの読み込み以外は何もしない簡単なアプリを作成する。次のセクションでは、これを拡張してカメラをサポートする。

この手順に加えて、いくつかのビデオガイドを利用できる。例えば こちら である

  1. Android Studioを開き、Empty Views Activity を選択して空のプロジェクトを作成する
  1. 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 で確認できる
  1. File -> New -> Import module... をクリックし、OpenCV SDKのパスを選択する
  1. モジュール名を OpenCV に設定し、Finish を押す
  1. 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.

    この修正方法は こちら で見つかった

  2. 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

    この修正方法は こちらこちら で見つかった

  3. Add the module to the project:
    • File -> Project structure... -> Dependencies -> All modules -> + (Add Dependency button) -> Module dependency をクリックする
  • app を選択する
  • OpenCV を選択する
  1. 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;
    }
    このように:
  1. サンプルを確認するデバイスを選択し、run ボタンを押してコードを実行する

Maven Centralを使ったHello OpenCVサンプル

OpenCV 4.9.0 以降、OpenCV for AndroidパッケージはMaven Centralで利用可能であり、Gradleの依存関係として自動的にインストールできる。このセクションでは、Maven Centralを使ってOpenCVを読み込む以外は何もしない簡単なアプリを作成する。

  1. Android Studioを開き、Empty Views Activity を選択して空のプロジェクトを作成する
  1. Setup the project:
    • Java 言語を選択する
    • Groovy DSL ビルド構成言語を選択する
    • Minumum SDK として、OpenCVがサポートするバージョン以上のバージョン番号を選択する。4.9.0 の場合、最小SDKバージョンは 21 である。
  1. build.gradle を編集し、以下のようにOpenCVライブラリをDependenciesリストに追加する:
    dependencies {
    implementation 'org.opencv:opencv:4.9.0'
    }
    4.9.0公式リリース として利用可能な任意のバージョンに置き換えることができる。
  2. 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;
    }
    このように:
  1. サンプルを確認するデバイスを選択し、run ボタンを押してコードを実行する

カメラビューのサンプル

このセクションでは、前のセクションで作成した空のOpenCVアプリを拡張し、カメラに対応させる。カメラのフレームを取得し、画面に表示する。

  1. カメラのパーミッションが必要であることをシステムに伝える。次のコードをファイル 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"/>
    このようになる:
  1. activity_main.xml レイアウトを開き、"Hello World!" というテキストを持つTextViewを削除する

これはCodeモードまたはSplitモードで、XMLファイルから TextView ブロックを削除することでも行える。

  1. レイアウトにカメラビューを追加する:

    1. レイアウトの記述にスキーマを追加する:
      xmlns:opencv="http://schemas.android.com/apk/res-auto"
    2. TextVieworg.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" />
    3. レイアウトの警告が出た場合は、android:layout_widthandroid: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" >
    <!-- [camera_view] -->
    <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" />
    <!-- [camera_view] -->
    </FrameLayout>
  2. メインクラスを org.opencv.android.CameraActivity から継承する。CameraActivityはカメラのパーミッション要求と、CVアプリケーションに必要なその他のユーティリティを実装している。オーバーライドすべき重要なメソッドは onCreateonDestroyonPauseonResumegetCameraViewList である
  3. インターフェイス org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2 を実装する。onCameraFrame メソッドはレンダリング用の内容を持つ Mat オブジェクトを返す必要がある。このサンプルはプレビュー用にカメラフレームをそのまま返すだけである: return inputFrame.rgba();
  4. Allocate org.opencv.android.CameraBridgeViewBase object:
    • これはアプリ起動時(onCreate メソッド)に生成され、このクラスをリスナーとして設定する必要がある
    • 一時停止/再開時(onPauseonResume メソッド)に無効化/有効化する必要がある
    • アプリ終了時(onDestroy メソッド)に無効化する必要がある
    • getCameraViewList で返す必要がある
  5. 必要に応じて、画面を暗くしたりロックしたりするのを禁止できる:

    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 コールバックの外で保存したり使用したりしてはならない。このオブジェクトは独自の状態を持たず、コールバック外での動作は予測できない!