[英]Touch based focus with Camera API2 on android
I am trying to implement touch based focus on Android using cameraApi2. 我正在尝试使用cameraApi2在Android上实现基于触摸的焦点。 It work sort of but it doesn't seem to work always for me.
它有点工作,但它似乎并不总是适合我。 My implementation is as follows:
我的实现如下:
First I create Camera PreviewSession with the following steps: 首先,我使用以下步骤创建Camera PreviewSession:
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO);
Then I call createCaptureSession and in that I call 然后我调用createCaptureSession并在其中调用
mCaptureSession.setRepeatingRequest( mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);
I have implement OnTouch Listener to capture the touched area of the screen and generate AF Region 我已经实现了OnTouch Listener来捕获屏幕的触摸区域并生成AF区域
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, meteringRectangleArr);
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);
In the captureCallback, I do following steps in onCaptureCompleted 在captureCallback中,我在onCaptureCompleted中执行以下步骤
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
mCaptureSession.capture(mPreviewRequestBuilder.build(), null, mBackgroundHandler);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_IDLE);
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null, mBackgroundHandler);
Now upon touch the Camera focus works sometimes and sometimes the preview is completely blur. 现在触摸相机焦点时有效,有时预览完全模糊。
Here is an implementation of a handler class (based on this ) which implements OnTouchListener
. 这是一个实现
OnTouchListener
的处理程序类(基于此 )的实现。 You can set it to the TextureView
to detect the touched point and make the desired focus. 您可以将其设置为
TextureView
以检测触摸点并进行所需的焦点。
CameraFocusOnTouchHandler.java CameraFocusOnTouchHandler.java
import android.annotation.SuppressLint;
import android.graphics.Rect;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.MeteringRectangle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class CameraFocusOnTouchHandler implements View.OnTouchListener {
private static final String TAG = "FocusOnTouchHandler";
private CameraCharacteristics mCameraCharacteristics;
private CaptureRequest.Builder mPreviewRequestBuilder;
private CameraCaptureSession mCaptureSession;
private Handler mBackgroundHandler;
private boolean mManualFocusEngaged = false;
public CameraFocusOnTouchHandler(
CameraCharacteristics cameraCharacteristics,
CaptureRequest.Builder previewRequestBuilder,
CameraCaptureSession captureSession,
Handler backgroundHandler
) {
mCameraCharacteristics = cameraCharacteristics;
mPreviewRequestBuilder = previewRequestBuilder;
mCaptureSession = captureSession;
mBackgroundHandler = backgroundHandler;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
//Override in your touch-enabled view (this can be different than the view you use for displaying the cam preview)
final int actionMasked = motionEvent.getActionMasked();
if (actionMasked != MotionEvent.ACTION_DOWN) {
return false;
}
if (mManualFocusEngaged) {
Log.d(TAG, "Manual focus already engaged");
return true;
}
final Rect sensorArraySize = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
//TODO: here I just flip x,y, but this needs to correspond with the sensor orientation (via SENSOR_ORIENTATION)
final int y = (int) ((motionEvent.getX() / (float) view.getWidth()) * (float) sensorArraySize.height());
final int x = (int) ((motionEvent.getY() / (float) view.getHeight()) * (float) sensorArraySize.width());
final int halfTouchWidth = 50; //(int)motionEvent.getTouchMajor(); //TODO: this doesn't represent actual touch size in pixel. Values range in [3, 10]...
final int halfTouchHeight = 50; //(int)motionEvent.getTouchMinor();
MeteringRectangle focusAreaTouch = new MeteringRectangle(Math.max(x - halfTouchWidth, 0),
Math.max(y - halfTouchHeight, 0),
halfTouchWidth * 2,
halfTouchHeight * 2,
MeteringRectangle.METERING_WEIGHT_MAX - 1);
CameraCaptureSession.CaptureCallback captureCallbackHandler = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
mManualFocusEngaged = false;
if (request.getTag() == "FOCUS_TAG") {
//the focus trigger is complete - resume repeating (preview surface will get frames), clear AF trigger
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, null);
try {
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
@Override
public void onCaptureFailed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureFailure failure) {
super.onCaptureFailed(session, request, failure);
Log.e(TAG, "Manual AF failure: " + failure);
mManualFocusEngaged = false;
}
};
//first stop the existing repeating request
try {
mCaptureSession.stopRepeating();
} catch (CameraAccessException e) {
e.printStackTrace();
}
//cancel any existing AF trigger (repeated touches, etc.)
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
try {
mCaptureSession.capture(mPreviewRequestBuilder.build(), captureCallbackHandler, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
//Now add a new AF trigger with focus region
if (isMeteringAreaAFSupported()) {
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, new MeteringRectangle[]{focusAreaTouch});
}
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
mPreviewRequestBuilder.setTag("FOCUS_TAG"); //we'll capture this later for resuming the preview
//then we ask for a single request (not repeating!)
try {
mCaptureSession.capture(mPreviewRequestBuilder.build(), captureCallbackHandler, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
mManualFocusEngaged = true;
return true;
}
private boolean isMeteringAreaAFSupported() {
Integer value = mCameraCharacteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF);
if (value != null) {
return value >= 1;
} else {
return false;
}
}
}
When you sure that the camera is opened and mCaptureSession
is successfully careated, you can set the touch handler to the TextureView
as following: 当你确定相机是否打开,
mCaptureSession
成功careated,您可以设置触摸处理器的TextureView
如下:
mTextureView.setOnTouchListener(new CameraFocusOnTouchHandler(mCameraCharacteristics, mPreviewRequestBuilder, mCaptureSession, mBackgroundHandler));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.