LoginSignup
20
25

More than 5 years have passed since last update.

AndroidでOpenCV3.0を使ってカメラ映像をグレースケールにする

Posted at

やりたいこと

画像認識、画像処理ライブラリOpenCVをAndroidのプロジェクトに組み込んで、カメラ映像に簡単な処理を加えてみます。一度組み込みに成功すれば、画像処理は変更可能と思いますので、簡単な例としてカメラ映像をグレースケールで出力する例を記述致します。

準備

以下のサイトからダウンロード可能です
http://sourceforge.net/projects/opencvlibrary/files/opencv-android/

今回は Version 3.0.0を選択しました。

準備は以下のサイトがとても詳しいので、以下の記事を参考にして頂き、OpenCVを使いたいプロジェクトにライブラリを追加します。
http://smartphone-zine.com/android/use-opencv-for-android-in-the-android-studio.html

1点異なる点は、この記事ではjniLibraryをコピーしているのですが、OpenCV Managerをインストールすれば動作可能なので必要ありません。jniLibraryを組み込むとアプリケーションサイズが大きくなってしまいますので、OpenCV Managerの使用をオススメします。

アプリケーション実行前にインストールしても良いですが、インストールされていない場合も、OpenCVの機能を使う前に以下のようなダイアログが表示されますので、そこからインストールが可能です。

スクリーンショット 2015-10-29 18.33.51.png

アプリケーションの作成

カメラを使いますのでPermissionの追加をAndroidManifest.xmlに行います。

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />

次にカメラの映像をOpenCVライブラリに渡す方法なのですが、OpenCV SDKには専用のViewが用意されています。ActivityもしくはFragmentのレイアウトファイルにJavaCameraViewを追加して下さい。

    <org.opencv.android.JavaCameraView
        android:id="@+id/camera_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="visible"/>

今回はFragmentにJavaCameraViewを貼付けた場合の例でコードを追記していきます。

まず、Viewが生成後にJavaCameraViewのインスタンスを取得します。またカメラのフレームを受けるためにリスナーを追加します。ここでは、Fragment自体でCvCameraViewListener2を実現します。Fragmentクラスの定義は以下のようになります

public class HogeFragment extends Fragment implements CvCameraViewListener2 {
...
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mCameraView = (CameraBridgeViewBase)view.findViewById(R.id.camera_view);
        mCameraView.setCvCameraViewListener(this);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mCameraView = null;
    }
    @Override
    public void onCameraViewStarted(int width, int height) {
    }

    @Override
    public void onCameraViewStopped() {
    }

    @Override
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        ...
    }

次にonResumeの段階でOpenCVライブラリの読み込みを行います。読み込みが完了した時点で、JavaCameraViewをEnableにしてフレームを受信し始めます。読み込み完了を知るためにはListenerを登録する必要があります。

    private static class OpenCVLoaderCallback extends BaseLoaderCallback {
        private final CameraBridgeViewBase mCameraView;
        private OpenCVLoaderCallback(Context context, CameraBridgeViewBase cameraView) {
            super(context);
            mCameraView = cameraView;
        }

        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                    mCameraView.enableView();
                    break;
                default:
                    super.onManagerConnected(status);
                    break;
            }
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, getActivity(),
                new OpenCVLoaderCallback(getActivity(), mCameraView));
    }

    @Override
    public void onPause() {
        super.onPause();
        mCameraView.disableView();
    }

これでonCameraFrameにフレームがきます。グレーアウトする場合は、実は何もする必要がなくて、入力されたフレームからグレースケールのデータだけを以下のように返せば実現が可能です。

    @Override
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        return inputFrame.gray();
    }
20
25
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
20
25