Camera2了解传感器和设备方向

时间:2018-01-23 16:25:54

标签: android rotation android-camera2

在尝试使用Android Camera2实现触控聚焦功能时,我遇到了一个问题。

理论很简单:

  • 获取预览图面中的拍子位置
  • 将其映射到传感器或传感器裁剪区域的尺寸(如果是缩放),请确保在需要时反转尺寸
  • 应用基础更改以与传感器相同的基础结束
  • 从结果中生成MeteringRectangle并在新的CaptureRequest
  • 中使用它

有很多例子展示了如何处理第一点和最后一点,但没有多少以可理解的方式处理第二点和第三点。文档和示例并不是很清楚,可能会让人感到困惑。

我们走了......

CameraCharacteristics.SENSOR_ORIENTATION被描述为

  

顺时针角度,输出图像需要通过该角度以原始方向旋转到设备屏幕上。

知道传感器坐标系定义为(0,0)是有源像素阵列中的左上角像素,我将其视为旋转传感器坐标系中捕获的图像所需的角度 到使图像在原始方向看起来直立的位置。因此,如果传感器的顶部朝向具有纵向原始方向的手机的右侧,则SENSOR_ORIENTATION将为90°。 Sensor Orientation

通过mActivity.getWindowManager().getDefaultDisplay().getRotation();获取的

显示方向记录为:

  

从“自然”方向返回屏幕的旋转。返回的值可能是Surface.ROTATION_0(无旋转),Surface.ROTATION_90,Surface.ROTATION_180或Surface.ROTATION_270。例如,如果设备具有自然高的屏幕,并且用户将其侧面转向横向,则此处返回的值可以是Surface.ROTATION_90或Surface.ROTATION_270,具体取决于它的转向。角度是屏幕上绘制图形的旋转,这是设备物理旋转的相反方向。例如,如果设备逆时针旋转90度,则补偿渲染将顺时针旋转90度,因此此处返回的值将为Surface.ROTATION_90。

我发现这个定义比传感器定位更清晰,没有解释的地方。

现在事情开始变得难看......

我决定使用Camera2Raw示例中提供的方法来获取从传感器方向到设备方向的旋转。

/**
 * Rotation need to transform from the camera sensor orientation to the device's current
 * orientation.
 *
 * @param c                 the {@link CameraCharacteristics} to query for the camera sensor
 *                          orientation.
 * @param deviceOrientation the current device orientation relative to the native device
 *                          orientation.
 * @return the total rotation from the sensor orientation to the current device orientation.
 */
private static int sensorToDeviceRotation(CameraCharacteristics c, int deviceOrientation) {
    int sensorOrientation = c.get(CameraCharacteristics.SENSOR_ORIENTATION);

    // Get device orientation in degrees
    deviceOrientation = ORIENTATIONS.get(deviceOrientation);

    // Reverse device orientation for front-facing cameras
    if (c.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
        deviceOrientation = -deviceOrientation;
    }

    // Calculate desired JPEG orientation relative to camera orientation to make
    // the image upright relative to the device orientation
    return (sensorOrientation + deviceOrientation + 360) % 360;
}

以下是手机背面和前置摄像头的不同输出表,其中包含纵向原生方向。 enter image description here

我注意到的第一件事是,如果我按照描述考虑输出(从相机传感器方向旋转到设备的当前方向), 为了使它有意义,我必须考虑输出旋转为逆时针(与传感器方向和设备方向不同)!! 例如,如果我们采用典型的90°传感器和0°设备方向,则重新设置为90°,如果我在分析中没有弄错,则只能逆时针方向。

假设我对传感器和设备方向的理解是正确的(不确定),那么上表的结果必定是错误的,因为如果你看90°传感器和90°器件定位情况下,它不能是180°应该是0°。 下一张图片直观地展示了我对90°传感器方向电话的所有理解。 enter image description here

我继续在R 2 中实现我的基础更改,以从屏幕基础到传感器基础获得我的分接点并添加预期的偏移。

我观察到,如果我切换180°和0°计算,那么我的触摸对焦可以完美地工作。从传感器到当前设备方向的旋转的正确观察值实际上对应于前置摄像头的表格。

所以我的直觉是sensorToDeviceRotation有缺陷,返回值应为:

// Calculate desired JPEG orientation relative to camera orientation to make
// the image upright relative to the device orientation
return (sensorOrientation - deviceOrientation + 360) % 360;

就计算的内容而言,它实际上更合乎逻辑......

有人可以证实吗?或者我在某处误解了什么?

干杯

1 个答案:

答案 0 :(得分:4)

是的,这是Camera2Raw中的一个错误;谢谢你抓住它。

如果您比较Camera#setDisplayOrientation参考文档中的示例代码,您会看到您期望的数学:

...
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
     result = (info.orientation + degrees) % 360;
     result = (360 - result) % 360;  // compensate the mirror
} else {  // back-facing
     result = (info.orientation - degrees + 360) % 360;
}