【问题标题】:Android Camera 2 API 1fps using setRepeatingRequestAndroid Camera 2 API 1fps 使用 setRepeatingRequest
【发布时间】:2017-10-14 19:36:17
【问题描述】:

我想使用 Camera 2 API 的 setRepeatingRequest() 模式拍摄 1fps 的静止图像。

我将CONTROL_AE_MODE 设置为CONTROL_AE_MODE_OFF,将SENSOR_FRAME_DURATION 设置为1。但是,使用下面的代码,我仍然会收到非常高的 20fps 帧速率。

我尝试将捕获请求模板从 TEMPLATE_PREVIEW 更改为 TEMPLATE_STILL_CAPTURE 没有任何运气。如何使用 setRepeatingRequest() 实现 1fps?

CaptureRequest.Builder requestBuilder
            = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
    requestBuilder.addTarget(imageReader.getSurface());
        cameraDevice.createCaptureSession(Collections.singletonList(imageReader.getSurface()),
            new CameraCaptureSession.StateCallback() {

                @Override
                public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                    // The camera is already closed
                    if (cameraDevice == null) {
                        return;
                    }

                    captureSession = cameraCaptureSession;
                    try {
                        requestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                                CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                        requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
                        requestBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, 1L);

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

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

                        captureSession.setRepeatingRequest(
                                requestBuilder.build(), captureCallback, callbackHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(
                        @NonNull CameraCaptureSession cameraCaptureSession) {
                }
            }, null);
} catch (CameraAccessException e) {
    e.printStackTrace();
}

【问题讨论】:

    标签: android camera android-camera android-camera2


    【解决方案1】:

    首先,SENSOR_FRAME_DURATION中的单位是纳秒,根据the docs

    所以试试requestBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, 1000000L);

    此外,您还可以使用CountDownTimer 并每隔 1 秒拍一张照片,这样可以不那么优雅。我知道这很糟糕,因为您每秒钟都在初始化所有相机的东西,但这是一个可行的解决方案。一个例子是:

    new CountDownTimer(5000,1000){
        @Override
        public void onFinish() { (...) }
    
        @Override
        public void onTick(long millisUntilFinished) {
            // TODO take picture
        }
    }.start();
    

    另一种解决方案是使用 Camera.Parameters [setPreviewFpsRange](https://developer.android.com/reference/android/hardware/Camera.Parameters.html#setPreviewFpsRange(int, int)),但它需要 Camera API 而不是 Camera2。但这只是另一种可能

    【讨论】:

    • 不幸的是,setPreviewFpsRange() 不会让它变得更容易,因为您只能选择一个受支持的范围。大多数设备没有将 1 fps 列为支持的帧速率。
    • @AlexCohn 你是完全正确的。但是正确使用 SENSOR_FRAME_DURATION 的简单方法必须成功
    • 不一定。我不确定SENSOR_INFO_MAX_FRAME_DURATION 会说什么。 FULL能力的设备保证至少100ms,但其他设备不保证,甚至可能null
    • SENSOR_FRAME_DURATION 不起作用。我想没有简单的方法可以使用 setRepeatingRequest() 来做到这一点。我可能只是重复 capture() 调用
    • 请注意,对于 1fps = 1000000000L。
    【解决方案2】:

    您对调用 onCaptureCompleted() 的频率的控制是有限的。但是您可以完全控制您在该回调中所做的事情。

    如果您的相机产生 20 fps,您可以跳过 19 个回调并捕获第 20 个。如果您不确定帧率是否足够稳定,您可以保留您使用的最后一张图片的时间戳(使用SystemClock.elapsedRealtime()),然后忽略所有回调直到一秒后。如果您真的需要,您甚至可以使用sleep() 来提高精度。

    【讨论】:

    • 您能否详细说明如何使用时间戳。我们可以将 onCaptureCompleted 中的时间戳与我们在 onImageAvailable 侦听器中获取的图像时间戳进行比较吗?
    • 那么有没有什么方法可以给我们捕获的图像加上一些特定的 CaptureRequest 参数来区分它们,同时捕获大量具有不同参数的图像?
    • 这是一个棘手的问题。我相信你可以在 onImageAvailable() 到达时参考最新可用的 CaptureRequest 参数,但可能无法保证。一些棘手的 HAL 可能会比您预期的稍晚交付 onCaptureCompleted()。我的意思是,如果您有 5 FPS,甚至 10 FPS,那么您很可能安全地认为在合理的时间内到达的 onCaptureCompleted() 和 onImageAvailable() 彼此对应。但是如果你有,比如说,60 FPS 序列,你就不应该再相信这种对应关系了。
    • 是的,我也有同样的经历。我不完全记得我使用的 FPS,但是 onCaptureCompleted 和 onImageAvailable 没有同步。我尝试使用时间戳来识别图像,但它们不正确匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-23
    • 2019-10-23
    • 2017-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多