簡體   English   中英

捕獲的圖像與Preview Camera2 Api不同

[英]Captured Image different from Preview Camera2 Api

問題: -Camera Preview與使用Camera2 Api捕獲的圖像不同。 並且僅在橫向模式下會出現問題。

要求:-我的要求是使用camera2 api在橫向模式下捕獲圖像.Camera Preview應該處於全屏狀態。

我已經遵循以下github示例:-https: //github.com/googlesamples/android-Camera2Basic

如果“紋理視圖”為wrap_content,則在保持寬高比的情況下,此示例在縱向模式和橫向模式下均可正常工作。

但是要全屏顯示攝像機預覽,我將TextureView更改為match_parent。 這樣,輸出就改變了。 現在,相機的預覽與捕獲的圖像有所不同。

請檢查此處附帶的圖像。

1. 相機預覽 :- 相機預覽的屏幕截圖

2.捕獲的圖像:- 點擊圖片按鈕

以下是我的代碼段:-

fragment_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,但是它沒有按預期工作。

就布局而言,TextureView可能部分位於顯示之外。
所以它被切斷了。

您可能要使用Android Studio的布局工具確認這一點

通常,除非匹配寬高比,否則無法獲得相同的圖像,因此,如果要全屏預覽,則必須選擇與屏幕匹配的JPEG高寬比。

這可能無法直接從相機獲得,因此您可能需要自己裁剪JPEG。 但是最有可能的是,您至少可以獲取16:9的預覽並且仍然相對容易地捕獲,與4:3的最大靜態捕獲大小相比,黑條相對較小。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM