Android CameraX 似乎会针对特定的 PreviewView 尺寸略微裁剪分析图像

Android CameraX seems to crop analysis images slightly for specific PreviewView sizes

使用的依赖项:

implementation 'androidx.camera:camera-camera2:1.1.0-alpha04'
implementation 'androidx.camera:camera-lifecycle:1.1.0-alpha04'
implementation 'androidx.camera:camera-view:1.0.0-alpha24'

为简单起见,假设您使用的设备具有:

PreviewView 的布局尺寸接近 1080x1920 和 FILL_CENTER 作为比例类型, 我们得到的分析框架与我们在 PreviewView 中看到的内容相同 - 没关系。 当我们的 PreviewView 变得更窄一点时, 例如 700x1920 - 它得到分析帧的裁剪部分: 左右画面的某些部分现在看起来被裁剪了 - 也没关系。

但是当我们改变 PreviewView 的尺寸使其看起来像横向时, 例如 - 到 1080x500 时出现问题。 我们的 PreviewView 使相机的帧看起来被裁剪了 从顶部和底部 - 没关系。 但不正常的是 - 我们的分析框架变得 实际上 被裁剪 略微 在左边和右边。 这意味着我希望在 PreviewView 和帧中看到相同的水平捕获边界 (因为由于缩放只裁剪了垂直部分), 但 PreviewView 实际上在其宽度上显示了更多一点 而不是相应的框架,所以看起来框架在水平方向上松动了大约 20px, 什么不应该发生,因为由于帧 (1080x1920) 和 PreviewView (1080x500) 大小, 只应剪掉垂直部分。

附上插图:

有人在 CameraX 中遇到过相同的行为吗?

UPD:我是怎么发现这个的? - 通过将帧(图像)保存到文件。 帧缓冲区转换为 cv::Mats:

void nv21_buffer_to_bgr_mat(JNIEnv* env,
                            jbyteArray nv21_buffer,
                            jint width,
                            jint height,
                            cv::Mat& mat)
{

    // To YUV.
    jbyte* nv21_buffer_bytes = env->GetByteArrayElements(nv21_buffer, nullptr);
    cv::Mat yuv(height + height / 2, width, CV_8UC1, nv21_buffer_bytes);

    // To BGR.
    cvtColor(yuv, mat, cv::COLOR_YUV2BGR_NV21, 3);
    env->ReleaseByteArrayElements(nv21_buffer, nv21_buffer_bytes, 0);

}

UPD2:也许上述案例的布局检查器图像会有所帮助:

底层 camera2 API 在裁剪方面有一套相当严格的规则,关于如何使用多个输出分辨率。 SCALER_CROP_REGION(数字缩放)控件的文档对此有 useful diagrams;对于您的情况,假设 CROP_REGION 覆盖了整个活动数组。

最重要的是,CameraX PreviewView 对其输入应用了进一步的裁剪,因为相机设备本身只支持几种尺寸。因此 PreviewView 会选择一个具有合理纵横比的受支持分辨率,然后在显示时根据需要裁剪它以填充您的视图布局区域。

因此,ImageAnalysis 和 Preview 用例及其视野之间的关系取决于 CameraX 在底层为用例选择的分辨率,以及 PreviewView 的额外裁剪。

这里可能发生的情况是,您的横向 PreviewView 正在选择比 ImageAnalysis 正在选择的基础分辨率更宽。如果您拥有设备的开发人员访问权限,而您的应用是 运行,则您可以通过 adb shell dumpsys media.camera 检查实际选择的内容。该命令转储了很多信息,包括 CameraX 为相机设备配置的确切内容。

您可以尝试在 Preview.Builder 上使用 setTargetAspectRatio or the setTargetResolution 方法来匹配 ImageAnalysis 的纵横比;这应该确保 PreviewView 只是 ImageAnalysis 接收到的内容的一部分。