我想实现标准的UX:在预览上点击一个点,以将自动聚焦和自动曝光点调整到它们所点击的位置。我找到了Preview.focus()函数,但是它说它需要“传感器坐标系”中的尺寸,我认为这与TextureView的TouchEvent像素坐标不同。
如何将TextureView预览的触摸坐标转换为Preview.focus()所需的“传感器坐标框架”?
如果此示例是示例代码的一部分,那就太好了,因为这似乎是几乎每个人都会期望的非常常见的用例。
答案 0 :(得分:0)
TextureView的坐标与传感器坐标不同。请参考示例代码https://vaex.readthedocs.io/en/latest/(请注意,“ CameraView”尚未在maven存储库中公开。因此,我们不建议您现在使用它)。我们知道这些工作量很大,因此CameraX团队还在开发对开发人员更友好的焦点/测光API版本。
基本流程如下:
(1)从视图触摸事件获取x,y。
(2)使用设备方向和camera2 CameraCharacteristics.SENSOR_ORIENTATION计算相对摄像机方向。该值表示顺时针旋转的角度,传感器图像需要旋转该角度才能在当前设备方向上直立。
(3)将x,y换成90/270度,并按方向正确反转x,y。反转x进行镜像(前置摄像头)
(4)使用CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE)转换为传感器坐标,查看宽度/高度。
注意:对于相机ID,现在您可以在mCameraManager.getCameraIdList()中找到第一个带有正确镜头朝向的camera_id。但是可以更改算法。
答案 1 :(得分:0)
This blog post(在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 blog post的原始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
}
}