一覧に戻る

Android ネイティブAPIのカメラ制御

2017.09.22AndroidネイティブAPI

カメラの設定

ここではWikitude SDKで可能になるカメラ設定の概要を紹介します。

カメラの位置

カメラの位置は、前面、背面、またはデフォルトのカメラを起動するかどうかを定義します。これは、NativeStartupConfiguration.setCameraPositionまたはCameraManager.setCameraPositionを使用して設定できます。

カメラのフォーカスモード

カメラのフォーカスモードは、カメラが内部的に使用するフォーカスモードを定義します。NativeStartupConfiguration.setCameraFocusModeまたはCameraManager.setFocusModeを使用して設定できます。カメラのフォーカスモードは、次のモードのいずれかになります。

  • Continuous: デバイスがサポートしている場合はデフォルトですが、このモードでは、カメラは必要に応じて自動的に再フォーカスしようとします。
  • Once: 現在のビューでカメラを再フォーカスさせることができます。フォーカスを変更する必要がある場合は、この値を再度設定できます。ONCEの値が設定されるたびに、カメラは現在のシーンに再びフォーカスします。
  • OFF: オートフォーカスを無効にし、手動のフォーカス距離が指定されていない場合は、無限遠フォーカスに設定します。このモードは、手動のフォーカス距離を設定するための前提条件です。

手動のカメラフォーカス

手動のカメラフォーカスは手動でフォーカスを設定することができ、camera2がNativeStartupConfigurationで有効になっていて、デバイスがサポートしている場合にのみ使用できます。手動のフォーカスが使用可能かどうかを確認するには、CameraManager.isManualFocusAvailableを使用します。フォーカス距離の範囲は0から1までで、0は最も近いフォーカスが可能で、1は無限遠のフォーカスです。NativeStartupConfiguration.setCameraManualFocusDistanceまたはCameraManager.setManualFocusDistanceを使用して設定できます。

Camera2 APIの使用

SDKでは、従来のカメラAPI(Android 5.0以降では非推奨)または新しいCamera2 APIを使用できます。camera2 APIは、手動フォーカスのような多くの手動カメラの機能が動作します。camera2 APIは一部のデバイスではまったく動作しないため、デフォルトでは無効になっており、NativeStartupConfiguration.setCamera2Enabledを使用して有効にすることができます。

現在、除外されているcamera2の機能:

  • 手動フォーカス

解像度

NativeStartupConfiguration.setCameraResolutionを使用して設定でき、実行時に変更することはできません。 推奨値は次のとおりです。

推奨 Geo Image Tracking Extended Tracking Cloud Recognition Instant Tracking
CameraSettings.CameraResolution AUTO AUTO SD_640x480 SD_640x480 SD_640x480

 

この設定はarmv8デバイスでのみ使用され、他のすべてのアーキテクチャはデフォルトでSD_640x480になります。

ズーム

デジタルズームは、CameraManager.setZoomLevelを使用して制御できます。 最大ズームレベルを取得するには、CameraManager.getを使用します。

フラッシュ

フラッシュは、CameraManager.enableCameraFlashLightCameraManager.disableCameraFlashLightを使用してオンとオフを切り替えることができます。

カメラ制御

CameraManagerを使用すると、フロントカメラとバックカメラの切り替え、連続フォーカスとワンショットフォーカスの切り替え、およびズームの制御ができます。activity_camera_control.xmlレイアウトファイルでは、公開されているすべての設定に対応するシンプルなUIコンポーネントが定義されています。このファイルの内容を知りたい場合は、サンプルを確認してください。

このレイアウトファイルを適切に実装すれば、UIコンポーネントやCameraManagerにすぐに接続できます。

接続する最初のコンポーネントはフラッシュのオン/オフスイッチです。以下のサンプルコードでは、匿名のOnCheckedChangeListenerを設定し、そこでWikitudeSDKからCameraManagerを取得してenableCameraFlashまたはdisableCameraFlashを呼び出し、フラッシュを有効または無効にしています。

zoomSeekBarについては、まずCameraManagerから取得した最大ズーム値を100倍して、それをSeekBarの最大値に設定します。次に、匿名のListenerを作成してユーザーインプットに反応します。最大値を100倍したので、現在のSeekbarの値を100で割ってからsetZoomLevelを呼び出してCameraManagerに再設定します。

手動フォーカスSeekBarはズームSeekBarと非常によく似ていますが、値の範囲は常に0-1です。範囲を広げるにはSeekBarの範囲を0-100に設定します。次に、匿名リスナーを設定してユーザーの入力に反応させます。値の範囲を広げた場合、setManualFocusDistanceを呼び出すことでCameraManagerに戻す前に、現在のSeekbarの値を100で割る必要があります。手動フォーカスの使用は、自動フォーカスが有効になっていない場合にのみ機能します。つまり、手動フォーカスを使用するには、カメラフォーカスモードがCameraSettings.CameraFocusMode.OFFである必要があります。手動フォーカスSeekBarは、この動作のためにフォーカスモードがCameraSettings.CameraFocusMode.OFFに設定されている場合にのみサンプルに表示されます。手動サポートは、config.setCamera2Enabled(true)を呼び出してArchitectStartupConfigurationで有効にできるcamera2 apiを使用している場合にのみ機能します。camera2 apiにはいくつかのデバイスで問題があるため、デフォルトでは無効になっています。

    @Override
    public void onCameraOpen() {

        ...

        Switch flashToggleButton = (Switch) findViewById(R.id.flashlight);
        flashToggleButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
                if (isChecked) {
                    mWikitudeSDK.getCameraManager().enableCameraFlashLight();
                } else {
                    mWikitudeSDK.getCameraManager().disableCameraFlashLight();
                }

            }
        });

        SeekBar zoomSeekBar = (SeekBar) findViewById(R.id.zoomSeekBar);
        zoomSeekBar.setMax(((int) mWikitudeSDK.getCameraManager().getMaxZoomLevel()) * 100);
        zoomSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(final SeekBar seekBar, final int progress, final boolean fromUser) {
                if (progress > 0) {
                    mWikitudeSDK.getCameraManager().setZoomLevel((float) progress / 100.0f);
                }
            }

            @Override
            public void onStartTrackingTouch(final SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(final SeekBar seekBar) {

            }
        });

        focusRow = (TableRow) findViewById(R.id.tableRow4);
        SeekBar focusSeekBar = (SeekBar) findViewById(R.id.focusSeekBar);
        focusSeekBar.setMax(100);
        focusSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(final SeekBar seekBar, final int progress, final boolean fromUser) {
                mWikitudeSDK.getCameraManager().setManualFocusDistance((float)progress/100.0f);
            }

            @Override
            public void onStartTrackingTouch(final SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(final SeekBar seekBar) {
            }
        });
    }

カメラ位置とフォーカスモードは別々のSpinnerを使用して制御しているので、匿名リスナーは使わず、アクティビティにonItemSelectedListenerを実装して両方のスピナーを同じメソッドで処理しています。カメラ位置とフォーカスモードのどちらについても、値を設定するsetterがCameraManagerに用意されています。CameraSettingsクラスで定義された適切な列挙体を使用して、使用可能な設定の中から値を選択します。

    @Override
    public void onCameraOpen() {

        ...

       Spinner cameraPositionSpinner = (Spinner) findViewById(R.id.cameraPosition);
       ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(CameraControlsActivity.this, R.array.camera_positions, android.R.layout.simple_spinner_item);
       adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
       cameraPositionSpinner.setAdapter(adapter);
       cameraPositionSpinner.setOnItemSelectedListener(CameraControlsActivity.this);

       Spinner focusModeSpinner = (Spinner) findViewById(R.id.focusMode);
       adapter = ArrayAdapter.createFromResource(CameraControlsActivity.this, R.array.focus_mode, android.R.layout.simple_spinner_item);
       adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
       focusModeSpinner.setAdapter(adapter);
       focusModeSpinner.setOnItemSelectedListener(CameraControlsActivity.this);
    }

カメラが起動していない場合はカメラに変更を加えることができないため、最初にカメラがすでに起動しているかどうかを確認します。CameraFocusModeが設定されている場合、デバイスとカメラの設定が手動フォーカスをサポートしているかどうか、また手動フォーカスSeekBarを表示するかどうかによって、使用できない理由を説明するトーストが表示されます。

    @Override
    public void onItemSelected(final AdapterView<?> adapterView, final View view, final int position, final long id) {
        if (mIsCameraOpen) {
            switch (adapterView.getId()) {
                case R.id.focusMode:
                    switch (position){
                        case 0:
                            mWikitudeSDK.getCameraManager().setFocusMode(CameraSettings.CameraFocusMode.CONTINUOUS);
                            if (focusRow != null) {
                                focusRow.setVisibility(View.GONE);
                            }
                            break;
                        case 1:
                            mWikitudeSDK.getCameraManager().setFocusMode(CameraSettings.CameraFocusMode.ONCE);
                            if (focusRow != null) {
                                focusRow.setVisibility(View.GONE);
                            }
                            break;
                        case 2:
                            mWikitudeSDK.getCameraManager().setFocusMode(CameraSettings.CameraFocusMode.OFF);
                            if (mWikitudeSDK.getCameraManager().isManualFocusAvailable()) {
                                if (focusRow != null) {
                                    focusRow.setVisibility(View.VISIBLE);
                                }
                            } else if (!mCamera2Enabled || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
                                Toast.makeText(this, "Manual Focus is not supported by the old camera API. The focus will be fixed at infinity focus if the device supports it.", Toast.LENGTH_SHORT).show();
                            } else {
                                Toast.makeText(this, "Manual Focus is not supported by this device. The focus will be fixed at infinity focus.", Toast.LENGTH_SHORT).show();
                            }
                    }
                    break;
                case R.id.cameraPosition:
                    if (position == 0) {
                        mWikitudeSDK.getCameraManager().setCameraPosition(CameraSettings.CameraPosition.BACK);
                    } else {
                        mWikitudeSDK.getCameraManager().setCameraPosition(CameraSettings.CameraPosition.FRONT);
                    }
                    break;
            }
        } else {
            Log.e("CAMERA_OPEN", "camera is not open");
        }
    }