Search code examples
androidandroid-camera2

How to force the focal length to a fixed value with camera2 API?


I have created a computer vision app for Android. I use the front camera to capture images on which I apply my algorithms. On my Samsung Galaxy S8, I observed that when I put objects in front of the camera, the focal length changes with the autofocus (it keeps zooming in and out). This is a problem because it creates unwanted changes in the image which temper with my algorithm. How can I determine a reasonable value for the focal length and then force the sensor to keep it fixed without disabling the auto-focus?

Here is my code for setting up the camera acquisition.

private void createCameraPreviewSession() throws CameraAccessException {
    mCameraDevice.createCaptureSession(Arrays.asList(mImageReader.getSurface()),
            new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(CameraCaptureSession cameraCaptureSession) {
                    if (null == mCameraDevice) {
                        return;
                    }
                    mCaptureSession = cameraCaptureSession;
                    try {
                        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                                CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
                                CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

                        mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null, mBackgroundHandler);
                    } catch (Exception e) {
                        Log.e(Config.tag, "createCaptureSession failed", e);
                    }
                }

                @Override
                public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
                    Log.e(Config.tag, "createCameraPreviewSession failed");
                }
            },
            null
    );
}

private void createImageReader() throws CameraAccessException
{
    mImageReader = ImageReader.newInstance(mFrameSize.getWidth(), mFrameSize.getHeight(),
            mPreviewFormat, 2);
    mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader reader) {
            if (mCaptureSession == null) {
                return;
            }
            Image image = reader.acquireLatestImage();
            if (image == null) {
                return;
            }

            //do something with the image

            image.close();
        }
    }, mBackgroundHandler);
    Surface surface = mImageReader.getSurface();

    mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
    mPreviewRequestBuilder.addTarget(surface);
}

Solution

  • I figured that using CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE is the mode which tries to constantly keep the image in focus. In my case, on some high-end devices with more than one frontal lenses, this could result in switching between lenses. I just changed the auto-focus mode to CaptureRequest.CONTROL_AF_MODE_AUTO and the auto-focus stopped constantly changing the focus. In addition, I used the CaptureRequest.CONTROL_AE_LOCK option to lock and unlock the auto-exposure at critical moments to avoid unwanted exposure changes.