camera2拍摄的照片模糊不清

时间:2016-10-03 10:31:15

标签: android android-camera2

我在三星Galaxy S7边缘设备上拍摄照片时遇到了不良行为。

在拍摄照片之前,我会同时等待对焦和曝光,但最后我与原生相机应用输出相比,有一种模糊的图像。

问题在缩放图像上尤其明显,但在未缩放时也存在。我也试图启用光学防抖,但问题并未解决。

以下是解释问题的链接样本图片。

Native camera image

My camera image

以下是代码:

图片捕获方法步骤1:

public void capturePicture() {
    CameraState state = getState();
    if (state != IDLE && state != CLOSING && state != TAKE_PICTURE) {
            boolean af = false;
            boolean ae = false;
            if (isAFEnabled()) {
                af = true;
            } else if (isAEEnabled()) {
                ae = true;
            }

            if (!af && !ae) {
                takePicture();
            } else {
                triggerFocusAndExposure(true);
            }
    }

    return;
}

触发对焦和曝光的方法:

private void triggerFocusAndExposure(boolean picture) {
    setState(WAIT_PRECAPTURE_PICTURE);

    if (isAFEnabled()) {
        previewBuilder.set(CONTROL_AF_TRIGGER, CONTROL_AF_TRIGGER_START);
    }

    if (isAEEnabled()) {
        previewBuilder.set(CONTROL_AE_PRECAPTURE_TRIGGER, CONTROL_AE_PRECAPTURE_TRIGGER_START);
    }

    try {
        cameraSession.capture(previewBuilder.build(), new SCameraCaptureSession.CaptureCallback() {
            @Override public void onCaptureCompleted(SCameraCaptureSession session, SCaptureRequest request, STotalCaptureResult result) {
                setState(PRECAPTURE_TRIGGERED_PICTURE);
            }
        }, backgroundHandler);
    } catch (CameraAccessException e) {
        return;
    }

    try {
        previewBuilder.set(CONTROL_AF_TRIGGER, CONTROL_AF_TRIGGER_IDLE);
        previewBuilder.set(CONTROL_AE_PRECAPTURE_TRIGGER, CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);
        cameraSession.setRepeatingRequest(previewBuilder.build(), mSessionCaptureCallback, backgroundHandler);
    } catch (CameraAccessException e) {
    }
}

等待焦点和曝光的方法:

private void waitPrecapture(STotalCaptureResult result, boolean picture) {
    // Check if AF/AE triggered and/or finished
    if ((!isAFTriggered(result) || isAfFinished(result)) && (!isAETriggered(result) || isAEFinished(result))) {
        takePicture();
    }
}

private boolean isAFTriggered(STotalCaptureResult result) {
    Integer afMode = result.get(SCaptureResult.CONTROL_AF_MODE);
    return afMode != CONTROL_AF_MODE_OFF &&
            afMode != CONTROL_AF_MODE_EDOF;
}

private boolean isAfFinished(STotalCaptureResult result) {
    int afState = result.get(SCaptureResult.CONTROL_AF_STATE);
    return afState == CONTROL_AF_STATE_FOCUSED_LOCKED || afState == CONTROL_AF_STATE_NOT_FOCUSED_LOCKED
            || afState == CONTROL_AF_STATE_PASSIVE_FOCUSED || afState == CONTROL_AF_STATE_PASSIVE_UNFOCUSED;
}

private boolean isAETriggered(STotalCaptureResult result) {
    boolean aeMode = result.get(SCaptureResult.CONTROL_AE_MODE) != SCaptureResult.CONTROL_AE_MODE_OFF;
    return aeMode && cameraCharacteristics.get(SCameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)
            != SCameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
}

private boolean isAEFinished(STotalCaptureResult result) {
    Integer aeState = result.get(SCaptureResult.CONTROL_AE_STATE);
    return aeState == null || aeState == SCaptureResult.CONTROL_AE_STATE_CONVERGED || aeState == SCaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED
            || aeState == SCaptureResult.CONTROL_AE_STATE_LOCKED;
}

图片捕获方法步骤2:

public void takePicture(){
    imageReader.setOnImageAvailableListener(reader -> {
        Image image = reader.acquireLatestImage();
        ByteBuffer buffer = image.getPlanes()[0].getBuffer();
        byte[] bytes = new byte[buffer.remaining()];
        buffer.get(bytes);
        image.close();
        singleSubscriber.onSuccess(bytes);
    }, imageSavingHandler);

    try {
        cameraSession.capture(captureBuilder.build(), new SCameraCaptureSession.CaptureCallback() {
             @Override
             public void onCaptureCompleted(SCameraCaptureSession session, SCaptureRequest request, STotalCaptureResult result) {
                 if (getState() == CameraState.CLOSING) {
                     return;
                 }
                 cancelAF();
             }

             @Override
             public void onCaptureStarted(SCameraCaptureSession session, SCaptureRequest request, long timestamp, long frameNumber) {
                 super.onCaptureStarted(session, request, timestamp, frameNumber);
                 shutterCallback.call();
             }    

             @Override public void onCaptureFailed(SCameraCaptureSession session, SCaptureRequest request, SCaptureFailure failure) {
                  singleSubscriber.onError(new RuntimeException("Error taking picture, onCaptureFailed"));
                  if (getState() == CameraState.CLOSING) {
                      return;
                  }
                  cancelAF();
             }
         }, backgroundHandler);

         setState(CameraState.TAKE_PICTURE);
     } catch (CameraAccessException e) {
         singleSubscriber.onError(new RuntimeException("Error capturing image", e));
     }
}

1 个答案:

答案 0 :(得分:8)

我找到了解决办法。 captureBuilder会自动设置CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITYCaptureRequest.EDGE_MODE_HIGH_QUALITY但在我的情况下,设备在处理这些选项时会遇到一些问题。设置CaptureRequest.NOISE_REDUCTION_MODE_FASTCaptureRequest.EDGE_MODE_FAST可以解决问题。