Implement Tap to Focus in Camera2 API

2020-02-23 08:14发布

i want to implement tap to focus feature in my custom camera. This is the basic code provided by Google https://github.com/googlesamples/android-Camera2Basic

Here's the code snippet where i think i should add my feature If anyone has implemented the Camera2 API please help!

  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();
    }
}

标签: android
3条回答
叼着烟拽天下
2楼-- · 2020-02-23 08:38

You'll need to set the autofocus and auto-exposure region to the area tapped by the user.

The keys are CONTROL_AF_REGIONS and CONTROL_AE_REGIONS.

The units for them are in the sensor active array coordinate system, so you'll have to translate from your UI touch coordinates to coordinates relative to your preview view, and from there, to the active array coordinates.

If the aspect ratio of your preview matches that of the sensor, then that's straightforward; if not, you'll have to adjust for the crop that is done to create the preview output. The best diagram for how the cropping works is currently here. Note that if you're also applying zoom, you'll want to include the zoom factor as well in your calculations.

Once you've calculated the region, you'll probably want to set the AF mode to AUTO (instead of CONTINUOUS_PICTURE which is usually used for normal preview), and then trigger AF. Once you converge AF (look at the AF state in the capture results, wait for AF_STATE_FOCUSED_LOCKED), you're good to take a picture that's in focus. If you want to return to normal operation after some time or the user cancels the touch to focus, switch AF mode back to CONTINUOUS_PICTURE.

查看更多
放荡不羁爱自由
3楼-- · 2020-02-23 08:40
  1. Use the onTouch listener to get the point where the user touch the screen.
  2. Calculate a/some MeteringRectangle(s) based on that position.
  3. Use this metering rectangles to set the CaptureRequest.CONTROL_AF_REGION & CaptureRequest.CONTROL_AE_REGION

  4. set the CaptureRequest.CONTROL_AF_MODE to CaptureRequest.CONTROL_AF_MODE_AUTO

  5. CaptureRequest.CONTROL_AF_TRIGGER to CameraMetadata.CONTROL_AF_TRIGGER_START
  6. CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER to CameraMetadata.CONTROL_AE_TRIGGER_START

  7. Then build capture request


Here you can find a full example.


查看更多
该账号已被封号
4楼-- · 2020-02-23 09:02
 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
    }
}

call on touch event method in averide on touch

查看更多
登录 后发表回答