如何使用Android Camera2 API捕获单个图像?

如何使用Android Camera2 API捕获单个图像?,android,Android,我正在使用Android Camera2 API来捕获和处理图像。图像处理是对成功捕获的响应。我遇到的问题是相机捕获了2幅图像,我无法更改Camera2基本示例中的代码,以确保只捕获一幅图像。可以通过将日志代码添加到Camera2BasicFragment.java public void run() { Log.d("Camera2", "Saving image"); ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();

我正在使用Android Camera2 API来捕获和处理图像。图像处理是对成功捕获的响应。我遇到的问题是相机捕获了2幅图像,我无法更改Camera2基本示例中的代码,以确保只捕获一幅图像。可以通过将日志代码添加到
Camera2BasicFragment.java

public void run() {
    Log.d("Camera2", "Saving image");
    ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
    ...
}
编辑-进一步调查后,问题似乎出现在示例的实现中,而不是API的任何基本问题。在示例中,以下代码跟踪摄影机的状态更改

 private void process(CaptureResult result) {
        switch (mState) {
            case STATE_PREVIEW: {
                // We have nothing to do when the camera preview is working normally.
                break;
            }
            case STATE_WAITING_LOCK: {
                int afState = result.get(CaptureResult.CONTROL_AF_STATE);
                if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
                        CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
                    // CONTROL_AE_STATE can be null on some devices
                    Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                    if (aeState == null ||
                            aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                        mState = STATE_WAITING_NON_PRECAPTURE;
                        /** CAPTURE 1 */
                        captureStillPicture();
                    } else {
                        runPrecaptureSequence();
                    }
                }
                break;
            }
            case STATE_WAITING_PRECAPTURE: {
                ...
                break;
            }
            case STATE_WAITING_NON_PRECAPTURE: {
                // CONTROL_AE_STATE can be null on some devices
                Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
                    mState = STATE_PICTURE_TAKEN;
                    /** CAPTURE 2 **/
                    captureStillPicture();
                }
                break;
            }
        }
    }
我已经验证了
captureStillPicture
的两个调用都会生成图像,并因此进行处理。我不完全确定正确的状态转换应该是什么


自从我开始阅读并深入研究你的问题以来,我一直在使用摩托罗拉Nexus 6,我相信这就是它的工作方式。根据文件()所述:

每个请求将生成一个CaptureResult并为其生成新帧 一个或多个目标曲面

请注意,它表示“frames”。复数形式


说,我相信你应该只考虑内部的最后一个帧<代码> OnCopultEngult回调。

示例代码中确实存在冗余/错误。简单的解决方案是在将

/**CAPTURE 1*/
写入之前更改行

mState = STATE_PICTURE_TAKEN;

只有当所有设置都已正确/聚合时,才进入这种情况,因此最好启动静止捕获,就像它那样。它这么做只是没有录音而已

这是因为示例的实现。要解决此问题,只需在captureStillPicture()方法末尾调用unlock()方法-

为了以防万一,这里是解锁方法

private void unlockFocus() {
        try {
            // Reset the autofucos trigger
            mPreviewBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
            mPreviewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

            // After this, the camera will go back to the normal state of preview.
            mState = STATE_PREVIEW;
            mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), mCaptureCallback, backgroundHandler);

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

您为我指出了正确的方向,但它似乎出现在示例的实现中,而不是API固有的任何内容。我已经对我的问题进行了相应的编辑。看起来,当设备只支持camera2时,这种情况也会发生,而不是有限或完全支持。导致控件状态为空。
private void unlockFocus() {
        try {
            // Reset the autofucos trigger
            mPreviewBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
            mPreviewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

            // After this, the camera will go back to the normal state of preview.
            mState = STATE_PREVIEW;
            mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), mCaptureCallback, backgroundHandler);

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }