Android Camera2采坑记录

问题1 相机预览画面变形

造成原因:

画面显示空间的长宽比例与相机预览的分辨率比例不一致

解决方案:

根据SurfaceView的长宽比例选择合适的相机分辨率,并调整SurfaceView的显示比例(因为相机预览的分辨率是固定的那几组,而你无法百分百确定选择相机的分辨率会和你SurfaceView的比例一致,所以,选择完相机预览分辨率后,你还得调整显示画面的比例)

/**
     * 选择合适的预览尺寸
     *
     * @param choices
     * @param textureViewWidth
     * @param textureViewHeight
     * @return
     */
    private Size chooseOptimalSize(Size[] choices, int textureViewWidth, int textureViewHeight) {
        //先查找preview中是否存在与surfaceview相同宽高的尺寸
        for (Size option : choices) {
            if ((option.getWidth() == textureViewWidth) && (option.getHeight() == textureViewHeight)) {
                return option;
            }
        }
        // 得到与传入的宽高比最接近的size
        float reqRatio = ((float) textureViewWidth) / textureViewHeight;
        float curRatio, deltaRatio;
        float deltaRatioMin = Float.MAX_VALUE;
        Size retSize = null;
        for (Size size : choices) {
            curRatio = ((float) size.getWidth()) / size.getHeight();
            deltaRatio = Math.abs(reqRatio - curRatio);
            if (deltaRatio < deltaRatioMin) {
                deltaRatioMin = deltaRatio;
                retSize = size;
            }
        }
        return retSize;
    }

问题2 Camera2手动点击聚焦失效

问题详情:参考Camera2-master项目手动点击聚焦,设置完CaptureRequest.Builde所需要手动聚焦的参数后,使用CameraCaptureSession.setRepeatingRequest()请求相机聚焦于某一区域,小米手机上面测试失效。然后并不是所有的设备都会失效,我所使用的另一台华为mate9设备能够正常聚焦。
代码如下:

        //List of metering areas to use for auto-exposure adjustment. 自动曝光
        mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, mAERegions);
        //传感器所需要捕获的区域
        mCaptureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, mCropRegion);
//        float minimumLens = mCameraCharacteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
//        float num = (((float) 1) * minimumLens / 100);
//        mCaptureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0.0f);
        mCaptureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
        mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
        mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
        mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);
        updatePreview(mCameraCaptureSession);
/**
     * 更新相机预览
     *
     * @param session
     */
    private void updatePreview(CameraCaptureSession session) {
        try {
            session.setRepeatingRequest(mCaptureRequestBuilder.build(), null, mChildHander);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            //CameraDevice was already closed
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

造成原因

具体的原因还没有找到,查看谷歌官方文档,比较了一下setRepeatingRequest 和capture方法的区别,一个是他们的优先级不一样,后者要高于前者,后来再仔细想想,请求聚焦应该只是某一刻的时候发生的事情,也不应该是连续的事情,所以使用capture还是挺合理的。

解决方案:

在谷歌上找到关于AF的一些问题的方法,尝试使用CameraCaptureSession.capture()方法去请求需要手动聚焦的区域,在小米手机上面测试,效果显著,问题解决。

//List of metering areas to use for auto-focus  用来自动对焦的测量面积列表
        mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, mAFRegions);
        //List of metering areas to use for auto-exposure adjustment. 自动曝光
        mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, mAERegions);
        //传感器所需要捕获的区域
        mCaptureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, mCropRegion);
//        float minimumLens = mCameraCharacteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
//        float num = (((float) 1) * minimumLens / 100);
//        mCaptureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0.0f);
        mCaptureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
        mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
        mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
        mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);

        try {
            mCameraCaptureSession.capture(mCaptureRequestBuilder.build(),null,mChildHander);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }

你可能感兴趣的:(Android Camera2采坑记录)