Android Camera2 实现点击对焦

698 阅读1分钟

1 坐标映射

蓝框:手机预览界面

紫色坐标系:Android View坐标系

绿色坐标系:Camera2坐标系(根据SENSOR_INFO_ACTIVE_ARRAY_SIZE确定,即底层Camera坐标点的范围)


使用Matrix进行坐标映射

直接求Preview到Camera Driver的坐标转换:

private Matrix previewToCameraTransform(boolean mirrorX, int sensorOrientation,RectF previewRect) {

    Matrix transform = new Matrix();

    // 1 判断是否前摄,是否需要镜像翻转

    transform.setScale(mirrorX ? -1 : 1, 1);

    // 2 将预览坐标旋转对应角度, 使之和Camera Driver坐标长宽对应

    transform.postRotate(-sensorOrientation);

    // 3 将当前的Matrix操作作用于预览对应的矩阵上, 此时得到的 previewRect逻辑上

    //   和 mDriverRectF已经对应了

    transform.mapRect(previewRect);

    // Map  preview coordinates to driver coordinates

    Matrix fill = new Matrix();

    fill.setRectToRect(previewRect, mDriverRectF, Matrix.ScaleToFit.FILL);

    // Concat the previous transform on top of the fill behavior.

    transform.setConcat(fill, transform);

    // finally get transform matrix

    return transform;

}

得到想要的Matrix,点击屏幕后, 根据屏幕坐标构建一个Rect, 通过调用 RectF toCameraSpace(RectF source);, 就得到了我们可以直接构造MeteringRectangle(Rect rect, int meteringWeight)Rect

注意: 构造函数 public CoordinateTransformer(CameraCharacteristics chr, RectF previewRect)中的 CameraCharacteristics chr, 要区分不同Camera ID。

2 触发对焦

startControlAFRequest(MeteringRectangle focusRect, MeteringRectangle meterRect)

其中,对焦模式设为AUTO

//对焦模式必须设置为AUTO

int afMode = CaptureRequest.CONTROL_AF_MODE_AUTO;

builder.set(CaptureRequest.CONTROL_AF_MODE, afMode);

builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);

通过 mSession.capture() 触发一次对焦操作的, 但在下次进行 mSession.setRepeatingRequest() 之前, 需要将之前的触发对焦的Request给清除掉, 即设置:

mPreviewBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,CaptureRequest.CONTROL_AF_TRIGGER_IDLE); //触发对焦

builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE);

try {

    mCaptureSession.setRepeatingRequest(builder.build(),mCaptureCallback,mBackgroundHandler);

    //触发对焦

    builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);

    //触发对焦通过capture发送请求,因为用户点击屏幕后只需要触发一次对焦

    mCaptureSession.capture(builder.build(), mCaptureCallback, mBackgroundHandler);

}

如果不设置的话, 会造成连续不断的对焦。


小结:

  1. CONTROL_AF_MODE_AUTO 对焦模式AUTO
  2. 触发一次对焦 CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE
  3. setRepeatingRequest
  4. CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START
  5. mCaptureSession.capture