Android 如何检测相机何时完成曝光初始化? 背景

Android 如何检测相机何时完成曝光初始化? 背景,android,camera,android-camera,Android,Camera,Android Camera,当我开始相机预览时,尤其是在室内,使用takePicture拍摄的预览帧和照片最初是黑色的。在接下来的一秒钟内,相机的曝光会自动调整,直到曝光达到最佳状态。当我打开手机上的摄像头应用程序时,也会发生这种行为 问题 一旦曝光正确,我会尽快拍照。最好我可以注册一个回调,以便在曝光良好时调用。我该怎么做 我试过的 将相机的曝光补偿配置为最大值。(没有帮助;预览开始后,相机仍然需要大约一秒钟的时间才能获得正确的曝光。) 自动对焦API,但由于相机不支持自动对焦,因此无法正常工作 硬编码一秒钟的延迟以等

当我开始相机预览时,尤其是在室内,使用
takePicture
拍摄的预览帧和照片最初是黑色的。在接下来的一秒钟内,相机的曝光会自动调整,直到曝光达到最佳状态。当我打开手机上的摄像头应用程序时,也会发生这种行为

问题 一旦曝光正确,我会尽快拍照。最好我可以注册一个回调,以便在曝光良好时调用。我该怎么做

我试过的
  • 将相机的曝光补偿配置为最大值。(没有帮助;预览开始后,相机仍然需要大约一秒钟的时间才能获得正确的曝光。)
  • 自动对焦API,但由于相机不支持自动对焦,因此无法正常工作
  • 硬编码一秒钟的延迟以等待曝光。这是次优的,因为在室外日光下,不需要这么多时间
传统摄像头API 不幸的是,带有传统摄像头驱动程序的设备似乎不支持这一点。因此,最好的选择似乎是开始预览,然后等待大约一秒钟

camera2
API 使用
camera2
API,您可以通过检查
capturesult.CONTROL\u AE\u STATE
的值来检查自动曝光状态

示例代码 首先开始捕获:

// Auto-exposure only seems to start after the first picture has been taken
// And on the Pixel 3 XL, it finishes fastest when you make a lot of captures
captureSession.setRepeatingRequest(request, captureCallback, null);
并使用此样板代码监控自动曝光:

private CaptureResult firstResult;

private final CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {

    @Override
    public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
        super.onCaptureCompleted(session, request, result);

        if (firstResult == null)
            firstResult = result;

        boolean aeAcquired;
        Integer aeState = lastResult.get(CaptureResult.CONTROL_AE_STATE);
        if (aeState == null) {
            // This camera doesn't support monitoring of auto-exposure, so we'll just have to wait a bit and then assume it's adjusted.
            long nanosSinceFirstResult = result.get(CaptureResult.SENSOR_TIMESTAMP) - firstResult.get(CaptureResult.SENSOR_TIMESTAMP);
            long millisSinceFirstResult = nanosSinceFirstResult / 1000 / 1000;
            aeAcquired = millisSinceFirstResult >= 750;
        } else {
            aeAcquired = aeState == CameraMetadata.CONTROL_AE_STATE_CONVERGED || aeState == CameraMetadata.CONTROL_AE_STATE_FLASH_REQUIRED;
        }

        if (aeAcquired) {
            // Auto-exposure has finished
        }   
    }

};

我自己没有尝试过,但是从
getExposureCompensation
获取一个值怎么样?如果仍然为0,则可能尚未执行曝光调整。(如果默认情况下不需要调整风险敞口,这也没用,所以你需要再做一次类似的检查。)这只是来自于阅读文档,而不是实际经验,所以我只是把它扔出去。@JASONGPETERSON,是的;我不久前试过了,不管相机使用的是什么曝光(或曝光补偿),getExposure*方法都会返回
0