AIをARに応用するぞ会 → (第8回) ~実装1 カメラを管理するインスタンス取得~
こんにちは松原です。
夏休みですが外出できないので暇です。
安くなっていたので、DQ11を買ってやっています。
面白い。
0. 今回の内容
現在スマホアプリを作成しようとしています。
基本設計は済んだので、あとは一つ一つ実装していくだけ。
今回はその第一段階として、
「androidカメラにアクセスし、カメラの映像を画面に描画する」
という処理を実装しようとしました。
で、今回進んだのは「androidカメラにアクセス」の部分までですね。
かなり複雑な手順が必要だったため、丁寧に説明していこうと思います。
1. 処理概要
さて、androidカメラにアクセスし、カメラの映像を画面に描画していきます。
最初は下記公式ドキュメントを参考にしようとしました。
ですがここで紹介されているクラス、よくみるとAndroid 5.0までで推奨されている形。
それ以降は下記クラスを利用しろとあります。
android.hardware.camera2 | Android デベロッパー | Android Developers
全部英語なうえに、日本語だったとしてもかなり難解。
そこで下記サイト等も参考にしながら、なんとかかみ砕いていきました。
AndroidのCamera2 APIを触ってみた - woshidan's blog
Androidアプリにおける最小限のカメラ機能の実装|システム開発のブログ|株式会社ベルソフト
かみ砕いた結果、必要な処理フローがこれ。
3つのクラスがややこしくかかわりあうので、並行でそれぞれの状態を記入しておきました。
こう書くと簡単だけど、公式ドキュメントから読み解くの無理では……
1. ソースコード
上記を実装してあるのがこれ。
カメラ利用許可を取る処理の場所がおかしいけど、そのうち直します。
package com.example.myapplication_test; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.Manifest; import android.content.pm.PackageManager; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CameraAccessException; import android.media.MediaPlayer; import android.os.Bundle; import android.widget.Button; import android.widget.TextView; import android.content.Context; public class MainActivity extends AppCompatActivity { private TextView textView; private boolean buttonTap = false; final int CLASS_NUM = 2; final int IMG_WIDTH = 224; final int IMG_HEIGHT = 224; MediaPlayer mp = null; Button button1; static final int REQUEST_CODE = 1; Context globalContext = MainActivity.this; /* コンテキスト */ CameraManager manager; /* カメラマネージャー */ CameraDevice mCameraDevice = null; /* カメラデバイス */ String[] cameraIdList; /* カメラマネージャーから取得するカメラID */ /* カメラ起動時やエラー時の処理セット */ private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { @Override /* この処理によって、カメラ起動時にそのカメラをメンバであるmCameraDeviceで制御できるよう結び付ける */ public void onOpened(@NonNull CameraDevice cameraDevice) { mCameraDevice = cameraDevice; } @Override public void onDisconnected(@NonNull CameraDevice cameraDevice) { cameraDevice.close(); mCameraDevice = null; } @Override public void onError(@NonNull CameraDevice cameraDevice, int error) { cameraDevice.close(); mCameraDevice = null; } }; private void setCamera() { /* カメラマネージャーのインスタンスをcontextから取得 */ manager = (CameraManager) globalContext.getSystemService(Context.CAMERA_SERVICE); /* カメラの利用許可を利用者に求める。挙動が変。場所をのちのち変える予定 */ ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.CAMERA }, REQUEST_CODE); /* カメラマネージャーから、デバイスのカメラID一覧を取得 */ { try { cameraIdList = manager.getCameraIdList(); System.out.println("------------------success getting cameraIDList"); } catch (CameraAccessException e) { e.printStackTrace(); System.out.println("------------------cant get cameraIDList"); } } /* ユーザーからの許可が下りてる場合にはカメラの取得 */ try { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { System.out.println("------------------Permission error"); return; } else{ /* カメラの起動。mStateCallbackを引数に渡していることで、今回起動したカメラの制御をmCameraDeviceで行うように設定している */ manager.openCamera(cameraIdList[0], mStateCallback, null); System.out.println("------------------success opening camera"); } } catch (CameraAccessException e) { e.printStackTrace(); System.out.println("------------------cant open camera"); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /* ボタンを設定 */ button1 = findViewById(R.id.button); /* カメラのインスタンスをmCameraDeviceに代入 */ setCamera(); } }
一応コンソールでは"------------------success opening camera"と出るので、カメラ起動の部分には問題なく入っています。
あとは実際に描画してみて、本当にカメラ取得ができているのか確認ですね。
2. androidの設定
カメラの利用ですが、ソースコードだけ書けばいいという訳ではありません。
下記処理が必要です。
1. マニフェストにカメラの利用許可を記入
2. エミュレータ上で、web camをデバイスのカメラと認識してもらうように設定
3. 最低APIを23に変更
1については、ユーザーやgoogle playにカメラ使うよと伝えるための宣言です。
カメラの利用許可の方法は下記参照。
Camera API | Android デベロッパー | Android Developers
2についてはエミュレータのデバイスには実際のカメラがないので、ウェブカメラをデバイスのカメラと思ってもらう処置です。
下記参照。
[Android]エミュレータでPCのウェブカメラを使う(Android Studio3.5) | ntの備忘録
3については、API 23以下では使えないクラスなどを使うので、利用できる最低のバージョンをそこに合わせようという話です。
API 21だったかもしれない。下記参照。
Android StudioでAPIレベルを下げる - Qiita
3. あとがき
今回はかなりてこずりました。
でもこういうのを読み解くのが楽しいんだよなあ。
という訳で、次回は取得したカメラからの映像を実際に描画してみます。
それではまた次回。