如果应用程序的默认方向设置为纵向模式,我们如何检测使用 CameraX 捕获的图像的方向

How do we detect the Orientation of Image captured using CameraX if Application's default orientation is set to Portrait Mode

基本上,我的相机应用设置为人像模式。但是,用户可以通过相应地旋转 phone 来拍摄肖像或风景照片(应用程序不旋转)。

所以我的问题是,我们如何找到捕获的图像方向?

我尝试使用 DisplayManager.DisplayListener,但是,它仅在发生应用程序方向时才有效。由于我已经将应用程序的方向设置为竖屏模式,所以这里没有任何回调。

我什至尝试使用 ExifInterface,但是,它总是给出 6 作为旋转。

我正在寻找使用 CameraX api 的解决方案。

请关注camerax的Official documentation

By default, the camera rotation is set to match the default display's rotation during the creation of the use case. In this default case, CameraX produces outputs to allow the app to easily match what you would expect to see in the preview. You can change the rotation to a custom value to support multi-display devices by passing in the current display orientation when configuring use case objects or dynamically after they have been created.

您可以使用默认显示旋转 and/or 来自 Preview.PreviewOutput() 的 camerax 元数据输出组合来为 GLSurfaceView 显示创建变换。

val previewConfig = PreviewConfig.Builder()
        .setTargetRotation(windowManager.defaultDisplay.rotation)
        .build()

基于设置的旋转,每个用例将直接旋转图像数据或向非旋转图像数据的消费者提供旋转元数据。

  • 预览: 提供元数据输出以创建正确的转换 对于 GLSurfaceView 显示使用 Preview.PreviewOutput.getRotationDegrees().

  • ImageAnalysis: 提供元数据输出以便图像缓冲区 坐标是相对于显示坐标已知的。分析() 方法提供一个代表旋转度的 rotationDegrees 参数 需要应用于图像分析数据以匹配 取景器.

  • ImageCapture: 图像 Exif 元数据将被更改以记录 旋转设置。

在我们的案例中尝试同样的方法 ExifInterface 不起作用。

private int getImgimageOrientation(){
final String[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.ImageColumns.ORIENTATION };
final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
        imageColumns, null, null, imageOrderBy);

if(cursor.moveToFirst()){
    int orientation = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION));
    cursor.close();
    return orientation;
} else {
    return 0;
}
}

我也有这个问题。解决它的方法是使用设备传感器数据获得正确的方向,然后将其设置在我的 imageCapture 对象中。请参阅下面的代码段。

        orientationEventListener = object : OrientationEventListener(context) {
            override fun onOrientationChanged(orientation: Int) {
                // Monitors orientation values to determine the target rotation value
                val rotation = if (orientation >= 45 && orientation < 135) {
                    Surface.ROTATION_270
                } else if (orientation >= 135 && orientation < 225) {
                    Surface.ROTATION_180
                } else if (orientation >= 225 && orientation < 315) {
                    Surface.ROTATION_90
                } else {
                    Surface.ROTATION_0
                }

                imageCapture?.setTargetRotation(rotation)
            }
        }

这也是 Google 问题跟踪器中类似问题的推荐方法:https://issuetracker.google.com/issues/144944155