gpt4 book ai didi

java - 在 Android 上使用 Camera API2 进行基于触摸的对焦

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:39:06 32 4
gpt4 key购买 nike

我正在尝试使用 cameraApi2 在 Android 上实现基于触摸的焦点。它有点工作,但它似乎并不总是适合我。我的实现如下:

首先,我通过以下步骤创建 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);

然后我调用 createCaptureSession 并在其中调用

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

我已经实现了 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);

在 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);

现在,在触摸时,相机焦点有时会起作用,有时预览会完全模糊。

最佳答案

这是实现 OnTouchListener 的处理程序类(基于 this)的实现。您可以将其设置为 TextureView 以检测触摸点并获得所需的焦点。

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

}

当您确定相机已打开并且 mCaptureSession 已成功处理后,您可以将触摸处理程序设置为 TextureView,如下所示:

mTextureView.setOnTouchListener(new CameraFocusOnTouchHandler(mCameraCharacteristics, mPreviewRequestBuilder, mCaptureSession, mBackgroundHandler));

关于java - 在 Android 上使用 Camera API2 进行基于触摸的对焦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53324821/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com