点击以调整相机X中的对焦/曝光



我想实现在预览上点击一个点的标准用户体验,以将自动对焦和自动曝光点调整到他们点击的位置。我找到了 Preview.focus() 函数,但它说它需要"传感器坐标框架"中的尺寸,我假设这与 TextureView 的 TouchEvent 像素坐标不同。

如何从 TextureView 预览的触摸坐标转换为 Preview.focus() 预期的"传感器坐标框"?

如果此示例是示例代码的一部分,那就太好了,因为它似乎是一个非常常见的用例,几乎每个人都会期望。

这篇由 Google 工程师撰写的博客文章确切地解释了如何做到这一点(在 Kotlin 中)。

这是在Java中实现相同目标的方法:

private void setUpTapToFocus() {
textureView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_UP) {
/* Original post returns false here, but in my experience this makes
onTouch not being triggered for ACTION_UP event */
return true;
}
TextureViewMeteringPointFactory factory = new TextureViewMeteringPointFactory(textureView);
MeteringPoint point = factory.createPoint(event.getX(), event.getY());
FocusMeteringAction action = FocusMeteringAction.Builder.from(point).build();    
cameraControl.startFocusAndMetering(action);
return true;
}
});
}

cameraControl对象可以像这样实例化:

CameraControl cameraControl = CameraX.getCameraControl(CameraX.LensFacing.BACK);

但请确保您有

implementation "androidx.camera:camera-view:1.0.0-alpha03"

build.gradle依赖项中。


作为参考,以下是来自 Husayn Hakeem 博客文章的原始 Kotlin 代码:

private fun setUpTapToFocus() {
textureView.setOnTouchListener { _, event ->
if (event.action != MotionEvent.ACTION_UP) {
return@setOnTouchListener false
}
val factory = TextureViewMeteringPointFactory(textureView)
val point = factory.createPoint(event.x, event.y)
val action = FocusMeteringAction.Builder.from(point).build()
cameraControl.startFocusAndMetering(action)
return@setOnTouchListener true
}
}

TextureView 的坐标与传感器坐标不同。请参考此处的示例代码(请注意,"CameraView"尚未在 maven 存储库中公开。所以我们不鼓励你现在使用它)。 我们知道这些需要做很多工作,因此CameraX团队也在开发一个对开发人员更友好的对焦/测光API版本。

基本流程如下: (1) 从视图触摸事件中获取 X、Y。 (2) 使用设备方向和相机2 CameraCharacteristics.SENSOR_ORIENTATION计算相对相机方向。该值表示传感器图像需要旋转以在当前设备方向上直立的顺时针角度。
(3)将x,y交换为90/270度,并按方向正确反转x,y。 反转 x 进行镜像(前置摄像头) (4) 使用CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE)变换到传感器坐标,视图宽度/高度。

注意:对于相机ID,现在您可以在mCameraManager.getCameraIdList()中找到具有正确镜头朝向的第一个camera_id。 但是算法可以更改。

如今,这可以使用LifecycleCameraController.setController(cameraController)非常容易地实现。

从文档中:

设置后,控制器将使用预览视图显示相机预览源。它还使用预览视图的布局维度为所有用例设置裁剪矩形,以便其他用例的输出与最终用户在预览视图中看到的内容相匹配。它还支持点击对焦和捏缩放等功能。

这里有一个关于如何使用它的简短示例(我正在使用 Kotlin,但在 Java 中是一样的)。

fun startCamera(
context: Context,
lifecycleOwner: LifecycleOwner,
previewView: PreviewView
): LifecycleCameraController {
//create camera instance
val cameraController = LifecycleCameraController(context)
//start camera
cameraController.bindToLifecycle(lifecycleOwner)
//enable camera preview feed and features like tap-to-focus and pinch-to-zoom
previewView.controller = cameraController
return cameraController
//...
//cameraController.takePicture(OutputFileOptions, Executor, OnImageSavedCallback) //take picture
//cameraController.unbind() //close camera
}

最新更新