Захваченное изображение отличается от Preview Camera2 Api - PullRequest
0 голосов
/ 16 октября 2018

Проблема: - Предварительный просмотр камеры отличается от изображения, полученного с помощью Camera2 Api.И проблема возникает только в ландшафтном режиме.

Требование: - Мое требование - захватить изображение в ландшафтном режиме с использованием camera2 api.Camera Preview должно быть в полноэкранном режиме.

Я использовал следующий пример github: - https://github.com/googlesamples/android-Camera2Basic

Этот пример отлично работает как в портретном, так и в ландшафтном режиме, если для Texture View установлено значение wrap_content при сохранении соотношения сторон.

Но чтобы отобразить предварительный просмотр камеры в полноэкранном режиме, я изменил TextureView на match_parent.Благодаря этому выход изменился.Теперь предварительный просмотр камеры отличается от полученного изображения.

Пожалуйста, проверьте изображения, прикрепленные здесь.

1. Предварительный просмотр камеры: - Снимок экрана предварительного просмотра камеры

2.Изображение получено: - При нажатии кнопки «Изображение»

Ниже приведен мой фрагмент кода: -

фрагмент_camera2_basic.xml

<RelativeLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.example.android.camera2basic.AutoFitTextureView
    android:id="@+id/texture"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentStart="true"
    android:layout_alignParentTop="true" />

<FrameLayout
    android:id="@+id/control"
    android:layout_width="match_parent"
    android:layout_height="112dp"
    android:layout_alignParentBottom="true"
    android:layout_alignParentStart="true"
    android:background="@color/control_background">

    <Button
        android:id="@+id/picture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/picture" />

    <ImageButton
        android:id="@+id/info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|right"
        android:padding="20dp"
        android:src="@drawable/ic_action_info" />

</FrameLayout>

</RelativeLayout>

Подписанкод для захвата изображения: -

 /**
 * Initiate a still image capture.
 */
private void takePicture() {
    lockFocus();
}

/**
 * Lock the focus as the first step for a still image capture.
 */
private void lockFocus() {
    try {
        // This is how to tell the camera to lock focus.
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
                CameraMetadata.CONTROL_AF_TRIGGER_START);
        // Tell #mCaptureCallback to wait for the lock.
        mState = STATE_WAITING_LOCK;
        mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
                mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

/**
 * Run the precapture sequence for capturing a still image. This method should be called when
 * we get a response in {@link #mCaptureCallback} from {@link #lockFocus()}.
 */
private void runPrecaptureSequence() {
    try {
        // This is how to tell the camera to trigger.
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
                CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
        // Tell #mCaptureCallback to wait for the precapture sequence to be set.
        mState = STATE_WAITING_PRECAPTURE;
        mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
                mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

/**
 * Capture a still picture. This method should be called when we get a response in
 * {@link #mCaptureCallback} from both {@link #lockFocus()}.
 */
private void captureStillPicture() {
    try {
        final Activity activity = getActivity();
        if (null == activity || null == mCameraDevice) {
            return;
        }
        // This is the CaptureRequest.Builder that we use to take a picture.
        final CaptureRequest.Builder captureBuilder =
                mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        captureBuilder.addTarget(mImageReader.getSurface());

        // Use the same AE and AF modes as the preview.
        captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
        setAutoFlash(captureBuilder);

        // Orientation
        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
        captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));

        CameraCaptureSession.CaptureCallback CaptureCallback
                = new CameraCaptureSession.CaptureCallback() {

            @Override
            public void onCaptureCompleted(@NonNull CameraCaptureSession session,
                                           @NonNull CaptureRequest request,
                                           @NonNull TotalCaptureResult result) {
                showToast("Saved: " + mFile);
                Log.d(TAG, mFile.toString());
                unlockFocus();
            }
        };

        mCaptureSession.stopRepeating();
        mCaptureSession.abortCaptures();
        mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

/**
 * Retrieves the JPEG orientation from the specified screen rotation.
 *
 * @param rotation The screen rotation.
 * @return The JPEG orientation (one of 0, 90, 270, and 360)
 */
private int getOrientation(int rotation) {
    // Sensor orientation is 90 for most devices, or 270 for some devices (eg. Nexus 5X)
    // We have to take that into account and rotate JPEG properly.
    // For devices with orientation of 90, we simply return our mapping from ORIENTATIONS.
    // For devices with orientation of 270, we need to rotate the JPEG 180 degrees.
    return (ORIENTATIONS.get(rotation) + mSensorOrientation + 270) % 360;
}

/**
 * Unlock the focus. This method should be called when still image capture sequence is
 * finished.
 */
private void unlockFocus() {
    try {
        // Reset the auto-focus trigger
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
                CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
        setAutoFlash(mPreviewRequestBuilder);
        mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
                mBackgroundHandler);
        // After this, the camera will go back to the normal state of preview.
        mState = STATE_PREVIEW;
        mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback,
                mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

Я попытался установить CaptureRequest.SCALER_CROP_REGION в построителе предварительного просмотра камеры и в программе чтения изображений, но он не работал должным образом.

1 Ответ

0 голосов
/ 16 октября 2018

С точки зрения макета, TextureView, вероятно, частично находится за пределами экрана.
Таким образом, он обрезается.

Вы можете подтвердить это с помощью инструментов макета Android Studio

В общем, вы не можете получить идентичные изображения, если не сопоставите пропорции, поэтому, если вы хотите получить полноэкранный предварительный просмотр, вам нужно будет выбрать соотношение сторон JPEG, соответствующее экрану.

Это может быть недоступно непосредственно с камеры, поэтому вам может потребоваться обрезать JPEG самостоятельно.Но, скорее всего, вы можете по крайней мере получить предварительный просмотр 16: 9 и по-прежнему делать снимки относительно легко, которые будут иметь относительно маленькие черные полосы по сравнению с максимальным размером снимка 4: 3.

...