在Camera2 API中实现“点击对焦”功能

13

我想在我的自定义相机中实现点按对焦功能。 这是由Google提供的基本代码 https://github.com/googlesamples/android-Camera2Basic

以下是我认为应该添加特性的代码片段 如果有人已经实现了Camera2 API,请帮忙!

  private void lockFocus() {
    try {
        // This is how to tell the camera to lock focus.
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
                CameraMetadata.CONTROL_AF_TRIGGER_START);
        // Tell #mCaptureCallback to wait for the lock.
        mState = STATE_WAITING_LOCK;
        mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
                mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}
3个回答

15

您需要将自动对焦和自动曝光区域设置为用户触碰的区域。

关键在于CONTROL_AF_REGIONSCONTROL_AE_REGIONS

它们的单位是传感器活动阵列坐标系,因此您需要将UI触摸坐标转换为与预览视图相关的坐标,然后再转换为活动阵列坐标。

如果预览的宽高比与传感器相同,则很简单;否则,您需要调整裁剪以创建预览输出。目前最好的有关裁剪工作原理的图表在此处。请注意,如果您还应用了缩放,您需要在计算中包括缩放因子。

一旦您计算出区域,您可能需要将AF模式设置为AUTO(而不是通常用于正常预览的CONTINUOUS_PICTURE),然后触发AF。 一旦您聚焦AF(查看捕获结果中的AF状态,等待AF_STATE_FOCUSED_LOCKED),您就可以拍摄对焦的图片了。如果您想在一段时间后或用户取消触摸以聚焦后返回正常操作,则将AF模式切换回CONTINUOUS_PICTURE。


4
  1. 使用onTouch监听器获取用户触摸屏幕的位置。
  2. 基于该位置计算一个/一些MeteringRectangle(s)
  3. 使用这些MeteringRectangle设置CaptureRequest.CONTROL_AF_REGIONCaptureRequest.CONTROL_AE_REGION

  4. CaptureRequest.CONTROL_AF_MODE设置为CaptureRequest.CONTROL_AF_MODE_AUTO

  5. CaptureRequest.CONTROL_AF_TRIGGER设置为CameraMetadata.CONTROL_AF_TRIGGER_START
  6. CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER设置为CameraMetadata.CONTROL_AE_TRIGGER_START

  7. 然后构建捕获请求


这里可以找到完整的示例。



0
 public void handleFocus(MotionEvent event) {
    int pointerId = event.getPointerId(0);
    int pointerIndex = event.findPointerIndex(pointerId);
    // Get the pointer's current position
    float x = event.getX(pointerIndex);
    float y = event.getY(pointerIndex);

    Rect touchRect = new Rect(
            (int) (x - 100),
            (int) (y - 100),
            (int) (x + 100),
            (int) (y + 100) );


    if (mCameraId == null) return;
    CameraManager cm = (CameraManager)this.getSystemService(Context.CAMERA_SERVICE);
    CameraCharacteristics cc = null;
    try {
        cc = cm.getCameraCharacteristics(mCameraId);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }


    MeteringRectangle focusArea = new MeteringRectangle(touchRect,MeteringRectangle.METERING_WEIGHT_DONT_CARE);
    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
    try {
        mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
                mBackgroundHandler);
        // After this, the camera will go back to the normal state of preview.
        mState = STATE_PREVIEW;
    } catch (CameraAccessException e){
        // log
    }

    /* if (isMeteringAreaAESupported(cc)) {
     *//*mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS,
                new MeteringRectangle[]{focusArea});*//*
    }
    if (isMeteringAreaAFSupported(cc)) {
        *//*mPreviewRequestBuilder
                .set(CaptureRequest.CONTROL_AF_REGIONS, new MeteringRectangle[]{focusArea});
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                CaptureRequest.CONTROL_AF_MODE_AUTO);*//*
    }*/
    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS,
            new MeteringRectangle[]{focusArea});
    mPreviewRequestBuilder
            .set(CaptureRequest.CONTROL_AF_REGIONS, new MeteringRectangle[]{focusArea});
    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
            CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
            CameraMetadata.CONTROL_AF_TRIGGER_START);
    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
            CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);
    try {
        mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback,
                mBackgroundHandler);
        /* mManualFocusEngaged = true;*/
    } catch (CameraAccessException e) {
        // error handling
    }
}

在averide on touch中调用touch event方法


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接