Android OpenCV4.11.0のカメラプレビュー(java)
2025.2.21 2020.1.4 Coskx Lab
1 はじめに
OpenCV4.11.0 android-sdkのcamera2API対応クラスを使用して,カメラプレビューアプリを作ります。
OpenCV android-sdkはhardware.camera,hardware.camera2のどちらのAPIでも使えるようになっています。
しかしAndroid5.0以降ではhardware.camera APIは非推奨になっています。
そのためhardware.camera2 APIを使用します。
4.9から4.10への変更でCameraBridgeViewBase.java,JavaCamera2View.java,JavaCameraView.javaの3つが変更されました。
それにより,OpenCV4.10以降ではAndroidDeviceを縦位置にしても横位置にしても正しく表示できるようになりました。
kotlin版は,次のリンクを参照してください。
OpenCV4.11.0のカメラプレビュー(kotlin) ≫
2 使用環境
- Windows 11 64-bit
- Android Studio Ladybug Feature Drop | 2024.2.2 Patch 1
Build #AI-242.23726.103.2422.13016713, built on February 6, 2025
Runtime version: 21.0.5+-12932927-b750.29 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
Toolkit: sun.awt.windows.WToolkit
- java (JavaVersion.VERSION_11)
- Build Target 35 (24以降で動作検証済)
- OpenCV 4.11.0
3 準備
3.1 Android Studio
インストール済とします。
3.2 OpenCVのダウンロード
次のところからアンドロイド版をダウンロードします。
https://opencv.org/releases/
(この説明ではカレントのOpenCV 4.11.0を使っていますが,適当に変えて読みかえてください。)
opencv-4.11.0-android-sdk.zip
がダウンロードされるので,解凍すると
OpenCV-android-sdkという名前のディレクトリができます。
この中には
ファイル LICENSE
ファイル README.android
ディレクトリ samples
ディレクトリ sdk
が入っています。
OpenCV-android-sdk を適当な場所に置いてください。
(この説明ではCドライブのルートに置きました。)
4 Android Studio で新しいproject
Android Studio で新しいprojectを作ります。新しいプロジェクトでカメラプレビューアプリを作ります。
・(ファイルメニュー File -> New ->) New Project --> Empty Views Activity
・New Project の名前は OCVCamera とします。(別の名前でもOK)
・AppおよびOPenCVモジュールでjavaを使用するので,
Language → Java
Build configuration language → Groovy DSL(build.gradle)
とします。
・パッケージ名は「jp.gr.java_conf.coskx.ocvcamera」(この文書での)です。デフォルトのパッケージ名のままでOKです。
パッケージ名はこの後,何回か出てきます。
・他の設定はそのまま -> Finish
ここで,MainActivity.javaを開くと,先頭がpackage名設定行で,ここに書いてあるのがパッケージ名です。
この文書でのパッケージ名は「jp.gr.java_conf.coskx.ocvcamera」です。
この後,何回か使いますので,作業中のパッケージ名をメモを取っておくとよいと思います。
出来上がったプロジェクトはそのまま(メニューバーのRun -> Run'App' を選び)実行すると,「Hello world!」を表示するアプリが実行されます。
5 OpenCVのライブラリをモジュールとして取り込む
OpenCVのライブラリをモジュールとして取り込む作業では,C:\OpenCV-android-sdk\sdkを取り込みます。
(1)android studio メニューバーのFile -> `New -> Import Module を選ぶ。
(2)Source directory に,C:\OpenCV-android-sdk\sdk を指定し,OK。

ここでModule nameボックスが現れるので,Module nameをsdkからOpenCVに変更します。
(実際にはバージョン番号まで入れると後から,都合がよいです。)
変更しなかった時には,この後もモジュール名は「sdk」のままになります。

なお,この段階で,ファイルOpenCV\build.gradle,あるいはbuild.gradle(:OpenCV))内の compileSdkVersion targetSdkVersion などを新しい記述に変更し,
値も適当なバージョン(2025.2.21時点では35)に変更しておくと良いと思います。
compileSdkVersion 31 → compileSdk 35
minSdkVersion 21 → minSdk 24
targetSdkVersion 31 → targetSdk 35
targetSdk 35 のところに警告が出ますが,そのままにしておきます。
右上の青い字の「Sync Now」でsyncします。
6 依存関係の設定
ここでの説明用画面の表示が古いままのものですが,似ているので読み替えてください。
プロジェクトOCVCameraがOpenCVのモジュールを使うこと(に依存していること)を設定します。ただし,OpenCVのモジュール名は「OpenCV」となっています。
(1)メニューバーのFile -> Project Structure を選ぶ。
(2)左側のDependenciesを選び,Modulesでapp を選ぶ。
(この段階ではModule appのDeclared Dependencies中にモジュール「OpenCV」は無い)

(3)Declared Dependencies の+-と書いてあるところで,+(add) をクリックし、3: Module dependenciy を選ぶ。

(4)Add Module Dependenciesダイアログで モジュール「OpenCV」にチェックを入れて(選らんで),OK。

Module appのDeclared Dependencies中のapp中にモジュール「OpenCV」が増えている。
(プロジェクトOCVCameraのappがモジュール「OpenCV」を使うことが設定された。)

(5)OK。
(Syncが終了するまで待つ 黄色の帯にTry Againが表示されたらそれをクリック)
Gradle Script/build.gradle(Module.app)のDependencies内に
implementation project(':OpenCV')
が追加されていればOK。
Android Studio左側project中にapp, OpenCVが並んで表示されたらOK

★ 実は,上記の(1)から(5)の作業は,
Gradle Script/build.gradle(Module.app)のDependencies内に
implementation project(':OpenCV')
を追加する作業なので,この1行を追加しSyncすれば良いようです。
7 OCVCameraの編集
OCVCameraのProjectでは次の3点を編集します。
- app/manifests/AndroidManifast.xml
- app/res/layout/activity_main.xml
- MainActivity.java
7.1 AndroidManifast.xmlの編集
app/manifests/AndroidManifast.xmlにおいて,カメラを使うことを宣言します。次のように6行追加になります。
AndroidManifast.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!--↓追加 -->
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera2" android:required="false"/>
<uses-feature android:name="android.hardware.camera2.autofocus" android:required="false"/>
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<!--↑追加-->
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.OCVCamera"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
7.2 activity_main.xmlの編集
app/res/layout/activity_main.xmlを編集します。
「Hello World!」を表示するような画面設定(Textview)を消して,camera2APIを使用したJavaCamera2Viewのカメラビューを表示する設定に直します。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- JavaCamera2View was placed instead of TextView -->
<org.opencv.android.JavaCamera2View
android:id="@+id/camera_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:camera_id="back"
app:show_fps="true"/>
</androidx.constraintlayout.widget.ConstraintLayout>
ここで,layoutの設定にactivity_main.xmlという名前のファイルを使っています。
その中の表示領域のIDとしてcamera_viewという名前を使いました。
この2つの名前を後でMainActivity.javaの編集で使います。
(app:camera_id="back" のところを app:camera_id="front" と変更すると,スクリーン側のカメラが使えます。)
7.3 MainActivity.javaの編集
(1) onCreate()中でlayoutのIDの記述の整合性を取る。(layout/activity_main.xmlへの依存)
- setContentView(R.layout.activity_main);
- mOpenCvCameraView = findViewById(R.id.camera_view);
(2) onCreate()中でOpenCVをロードする。
(3) パーミッションを取得し,mOpenCvCameraViewに取得を知らせる。
onStart()中でパーミッションを確認
- 確認出来なかったら,requestPermissionsでパーミッションを要求。
実行時ダイアログでパーミッションが得られたら,onRequestPermissionsResult()が,
mOpenCvCameraView.setCameraPermissionGranted();でmOpenCvCameraViewに取得を知らせる。
- 確認できていたら,mOpenCvCameraView.setCameraPermissionGranted();でmOpenCvCameraViewに取得を知らせる。
MainActivity.java
package jp.gr.java_conf.coskx.ocvcamera;
import static android.Manifest.permission.CAMERA;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
public class MainActivity extends Activity implements CameraBridgeViewBase.CvCameraViewListener2 {
private static final String TAG = "MainActivity";
private static final int CAMERA_PERMISSION_REQUEST_CODE = 200;
private CameraBridgeViewBase mOpenCvCameraView;
@Override
protected void onStart() {
super.onStart();
boolean havePermission = true;
if (checkSelfPermission(CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
havePermission = false;
}
if (havePermission) {
mOpenCvCameraView.setCameraPermissionGranted();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == CAMERA_PERMISSION_REQUEST_CODE && grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mOpenCvCameraView.setCameraPermissionGranted();
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
if (OpenCVLoader.initLocal()) {
Log.d(TAG,"OpenCV Version: " + OpenCVLoader.OPENCV_VERSION);
} else {
Log.i(TAG,"ERROR: OpenCV Load Failed");
}
setContentView(R.layout.activity_main);
mOpenCvCameraView = findViewById(R.id.camera_view);
mOpenCvCameraView.setCvCameraViewListener(this);
}
@Override
public void onResume() {
super.onResume();
if (mOpenCvCameraView != null)
mOpenCvCameraView.enableView();
}
@Override
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
public void onCameraViewStarted(int width, int height) { }
public void onCameraViewStopped() { }
public Mat onCameraFrame(@NonNull CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
return inputFrame.rgba();
}
}
ここまでで,buildすると,とりあえず動作するはずです。
プレビュー表示が,スマホなどのデバイスの画面を有効に使っていない(画面に比べて狭い)と感じたら,
もう少し広くすることができます。
public void onCreate(Bundle savedInstanceState) {
:
}
の最後の行は
mOpenCvCameraView.setCvCameraViewListener(this);
ですが,その直後に
//requesting preview size option (maxWidth > maxHeight)
mOpenCvCameraView.setMaxFrameSize(1280, 720);
を加えてみてください。画面サイズを1280x720に近い都合の良いサイズで表示してくれます。
あまり大きな値にするとfps(表示速度)が遅くなります。
★ bulid時に"org.opencv.BuildConfig"が見つからないというエラーが出たときの対処
何度もMake ProjectやRebuild Projectを行っても,"org.opencv.BuildConfig" が見つからないというエラーが出ているときは
Gradle Scripts/gradle.properties(Project Properties)を開いて最下行付近を見てください。
もし
android.defaults.buildfeatures.buildconfig=true
の行が無かったら,付け加えてください。
8 画像処理例
onCameraFrame() はカメラが1フレーム取得するたびに呼ばれる関数です。
引数(inputFrame)にカメラからの入力フレーム画像が入り,戻り値で表示したいMatを戻します。
Mat mMatを用意して,初期化と廃棄をするようにして,関数onCameraFrame()を次のように変更すると,ネガポジ反転で表示します。
複数の表示方法の中から1つだけ選ぶことができます。
public void onCameraViewStarted(int width, int height) {
mMat = new Mat(height, width, CvType.CV_8UC4);
}
public void onCameraViewStopped() {
mMat.release();
}
private Mat mMat;
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
//mMat= inputFrame.rgba(); //color
//mMat= inputFrame.gray(); //grayscale
Core.bitwise_not(inputFrame.rgba(), mMat); //reversed
//Core.bitwise_not(inputFrame.gray(), mMat); //grayscale reversed
//Imgproc.Canny(inputFrame.gray(), mMat, 100, 200); //grayscale canny filtering
//Imgproc.threshold(inputFrame.gray(), mMat, 0.0, 255.0, Imgproc.THRESH_OTSU); //grayscale binarization with Ohtsu
return mMat;
}
 |
 |
カラー画像 |
グレースケール画像 |
 |
 |
カラー画像リバース |
グレースケール画像リバース |
 |
 |
グレースケール画像Cannyフィルタ |
グレースケール画像二値化 |
この変更では,MainActivity.javaの先頭部分に
・import org.opencv.core.Core;
・import org.opencv.core.Mat;
・import org.opencv.imgproc.Imgproc;
が必要になりますが,android studioがうまく解決してくれます。
9 終わりに
・Android StudioでOpenCV4.11.0のカメラプレビューテストアプリを作る手順をまとめました。
補足1 アクションバーを付ける
MainActivityはActivityからextendsされているため,アクションバーなどAppCompatActivityの機能がありません。
必要ならActivityをAppCompatActivityからextendsします。(ただし,横位置の場合表示領域が狭くなります。)
補足2 JavaCameraView, JavaCamera2View, CameraBridgeViewBase
OpenCVのandroid向けライブラリでは,java/org.opencv/androidの中にカメラビュー向けのクラスがあります。
CameraBridgeViewBaseはSurfaceViewを継承していて,カメラのハードウェアに依存しない(デバイスの表示機能)部分を担当しています。
カメラのハードウエアに近い部分は,JavaCameraViewあるいはJavaCamera2Viewが担当していています。
JavaCameraView, JavaCamera2ViewはともにCameraBridgeViewBaseを継承していて,カメラのハードウェアに依存している部分を担当しています。
カメラビューアプリではJavaCameraView, JavaCamera2Viewのうちどちらか片方が使用されます。
JavaCameraViewは古いAPI(hardware.Camera)が使用されていて,Android5.0(Lollipop)以降(APIレベル21以降)では非推奨となっています。
android studioでJavaCameraView.javaをみると,取り消し線だらけになります。)
JavaCamera2ViewはJavaCameraViewと同等の役割を果たしていて,APIレベル21以降でも問題なく使用できるAPI(hardware.camera2)が使われています。