camera 自动对焦&手动对焦

基础内容可参考

自动对焦系统概述|Camera

https://jingyan.baidu.com/article/22a299b5c882a29e19376aad.html

对焦框坐标基本概念:

Android Camera2之 手动点击区域对焦 - 简书

Camera2点击对焦实现 - mydddfly - 博客园

本文主要总结自己开发过程中遇到的各个知识点

需求: Camera2  App开发:取消自动对焦,设置为触摸手动对焦,对焦完成后依然不允许自动对焦

思路:

触摸屏幕OnTouchListener监听--》根据坐标转换,计算对焦区域--》进行对焦--》显示对焦框

1、触摸屏幕,

private View.OnTouchListener mOntouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent event) {
            try {
                switch(event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        int[] location = new int[2];
                        mTextureView[0].getLocationOnScreen(location);

                        int tmpx = mTextureView[0].getWidth();
                        int tmpy = mTextureView[0].getHeight();
                        Log.d(TAG, "onTouch,TextureView.getWidth:" + tmpx +
                                ",TextureView.getHeight:" + tmpy + ",location[0]:" + location[0] +
                                ",location[1]" + location[1] + ",TextureView.getLeft:" + mTextureView[0].getLeft()
                                + ",TextureView.getTop:" + mTextureView[0].getTop()+", mTextureView[0].getRight():"+ mTextureView[0].getRight()+", mTextureView[0].getBottom():"+ mTextureView[0].getBottom());

                        int focusWidth = mAutoFoucView.getLayoutParams().width;
                        int focusHeight = mAutoFoucView.getLayoutParams().height;

                        float x_raw = event.getRawX();//between screen
                        float y_raw = event.getRawY();//between screen

                        mAutoFoucView.setVisibility(View.VISIBLE);
                        ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) mAutoFoucView.getLayoutParams();
//                        int left = (int) (event.getX() - focusWidth / 2 + location[0]);
//                        int top = (int) (event.getY() - focusHeight / 2 + location[1]);
                        int left = (int) (event.getX() - focusWidth / 2);
                        int top = (int) (event.getY() - focusHeight / 2);


                        Log.d(TAG, "onTouch,focusWidth:" + focusWidth +
                                ",focusHeight:" + focusHeight + ",event.getX():" + event.getX() +
                                ",event.getY():" + event.getY() + ",event.getRawX():" + event.getRawX()
                                + ",event.getRawY():" + event.getRawY());

                        layoutParams.leftMargin = left;
                        layoutParams.topMargin = top;
                        mAutoFoucView.setLayoutParams(layoutParams);
                        mAutoFoucView.prepareFocus();

                        int width = mTextureView[0].getWidth();
                        int height = mTextureView[0].getHeight();

                        meteringRectangle = getMeteringRectangles(event.getX(), event.getY(), width, height);

                        Message msg = Message.obtain();
                        msg.what = CameraOpt.MSG_SET_TOUCH_POINT_VALUE;
                        msg.obj= meteringRectangle;
                        msg.arg1 = mAutoFoucView.isFocusing()? 1 : 0;
                        mCameraOpt[0].getHandler().sendMessage(msg);
                        break;
                }
                return true;
            } catch (Exception e) {
                Log.v("onTouch", e.toString());
                return false;
            }

        }


    };
                case MSG_SET_TOUCH_POINT_VALUE:
                    meteringRectangle =(MeteringRectangle[]) msg.obj;
                    isFocusing = msg.arg1 != 0;
                    //Log.i(TAG,"isFocusing="+isFocusing);
                    onTouchFoucs(meteringRectangle);

                    break;
    private void onTouchFoucs(MeteringRectangle[] meteringRectangle) {
        if(isFocusing)
        {
//设置AF/AE对焦区域,开始对焦
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, meteringRectangle);
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, meteringRectangle);
            //        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);

            mPreviewRequest = mPreviewRequestBuilder.build();
            try {
                mCaptureSession.setRepeatingRequest(mPreviewRequest, mPreviewListener, mHandler);
            } catch (CameraAccessException e) {
                Log.e(TAG, "setRepeatingRequest failed, " + e.getMessage());
            }

        }
    }
private final CameraCaptureSession.CaptureCallback mPreviewListener = new CameraCaptureSession.CaptureCallback() {
        @Override
        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
            Log.d(TAG, "onCaptureCompleted begin isFocusing="+isFocusing);
            if (mPreviewRequestBuilder == null) {
                return;
            }
            if(isFocusing){
                Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);//
                Log.d(TAG, "onCaptureCompleted begin afState="+afState);
                if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState
                        || CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {

                    isFocusSucess = true;
                    mCamLister.onFocusState(isFocusSucess);

                    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
                    //如果对焦完成后不允许自动对焦,注释掉如下几行。
//                    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE);
//                    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
//                    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);


                    mPreviewRequest = mPreviewRequestBuilder.build();
                    try {
                        mCaptureSession.setRepeatingRequest(mPreviewRequest, null, mHandler);//
                    } catch (CameraAccessException e) {
                        Log.e(TAG, "setRepeatingRequest failed, errMsg: " + e.getMessage());
                    }

                }
                else {
                    isFocusSucess = false;
                    mCamLister.onFocusState(isFocusSucess);
                }
            }

            isFocusing = false;
    super.onCaptureCompleted(session, request, result);
//            Log.d(TAG, mCameraId + " onCaptureCompleted end");
        }
        @Override
        public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
            super.onCaptureStarted(session, request, timestamp, frameNumber);
        }

        @Override
        public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, CaptureFailure failure) {
            super.onCaptureFailed(session, request, failure);
        }
    };

mPreviewListener是监听预览界面;

getMeteringRectangles函数后面补充

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Camera2 API中实现手动对焦需要以下步骤: 1. 获取CameraManager实例,使用该实例获取可用的相机设备列表。 2. 获取要使用的相机设备的CameraDevice实例。 3. 创建一个CaptureRequest.Builder对象,并将其与相机设备关联。 4. 设置手动对焦模式和对焦区域。 5. 构建CaptureRequest对象。 6. 启动相机预览。 7. 实现一个触摸事件监听器,在用户触摸屏幕时获取焦点坐标,并设置对焦区域。 8. 在触摸事件监听器中调用CaptureRequest.Builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START)触发对焦操作。 9. 实现一个CameraCaptureSession.CaptureCallback回调函数,在对焦完成后更新预览界面。 下面是一个简单的实现示例: ```java private void setupCamera() { // 获取相机管理器实例 CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { // 获取可用的相机设备列表 String[] cameraIds = cameraManager.getCameraIdList(); for (String cameraId : cameraIds) { // 获取相机设备实例 CameraDevice cameraDevice = cameraManager.openCamera(cameraId, mStateCallback, mBackgroundHandler); // 创建一个CaptureRequest.Builder对象,并将其与相机设备关联 mPreviewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); // 设置手动对焦模式和对焦区域 mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO); mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, new MeteringRectangle[]{new MeteringRectangle(focusRect, 1000)}); // 构建CaptureRequest对象 mPreviewRequest = mPreviewRequestBuilder.build(); // 启动相机预览 cameraDevice.createCaptureSession(Arrays.asList(mSurface), mSessionCallback, mBackgroundHandler); } } catch (CameraAccessException e) { e.printStackTrace(); } } private void startPreview() { try { // 设置自动对焦模式 mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO); // 启动预览 mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } private void setFocusArea(float x, float y) { // 计算对焦区域 Rect focusRect = calculateFocusRect(x, y); // 设置对焦区域 mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, new MeteringRectangle[]{new MeteringRectangle(focusRect, 1000)}); // 触发对焦操作 mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START); try { // 更新预览界面 mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) { super.onCaptureCompleted(session, request, result); // 对焦完成后更新预览界面 if (request.get(CaptureRequest.CONTROL_AF_TRIGGER) != null && request.get(CaptureRequest.CONTROL_AF_TRIGGER) == CameraMetadata.CONTROL_AF_TRIGGER_START) { mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, null); mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); try { mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null, mBackgroundHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } } }; private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { mCameraDevice = camera; startPreview(); } @Override public void onDisconnected(@NonNull CameraDevice camera) { mCameraDevice.close(); mCameraDevice = null; } @Override public void onError(@NonNull CameraDevice camera, int error) { mCameraDevice.close(); mCameraDevice = null; } }; private CameraCaptureSession.StateCallback mSessionCallback = new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { mCaptureSession = session; try { mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mBackgroundHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { session.close(); mCaptureSession = null; } }; ``` 在以上代码中,calculateFocusRect()方法用于计算对焦区域,可以根据需要自行实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值