camera2 pictures taken are blurred

孤者浪人 提交于 2019-12-23 02:59:24

问题


I'm experiencing a bad behavior when capturing a photo on a Samsung Galaxy S7 edge device.

I wait simultaneously for focus and exposure before taking the picture but at the end I have a kind of blurred image compared to the native camera app output.

The problem is especially visible on zoomed images but is present also when not zoomed. I've also tried to enable the optical image stabilization but the problem isn't fixed.

Below are linked sample images explaining the problem.

Native camera image

My camera image

Here is the code:

Method for picture capture step 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;
}

Method for triggering focus and exposure:

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) {
    }
}

Methods for waiting focus and exposure:

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;
}

Method for picture capture step 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:


I've found the fix. captureBuilder automatically sets CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY and CaptureRequest.EDGE_MODE_HIGH_QUALITY but in my case the device has some problem handling these options. Setting CaptureRequest.NOISE_REDUCTION_MODE_FAST and CaptureRequest.EDGE_MODE_FAST fixes the problem.



来源:https://stackoverflow.com/questions/39829528/camera2-pictures-taken-are-blurred

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!