如果应用程序默认方向为纵向模式,我们如何检测使用 CameraX 拍摄的图像的方向?

6

基本上,我的相机应用程序被设置为纵向模式。然而,用户可以通过相应旋转手机来以纵向或横向拍照(应用程序不会旋转)。

所以我的问题是,如何找到拍摄的图像方向?

我尝试使用DisplayManager.DisplayListener,但它只在应用程序方向发生改变时起作用。由于我已经将应用程序方向锁定为纵向模式,在这里它不会得到任何回调。

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

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


您可以使用 ImageAnalysis.setTargetRotation()Preview.PreviewOutput() 来决定使用 CameraX API 拍摄的照片的旋转。 - Sudheesh R
我该如何了解在ImageAnalysis.setTargetRotation()中设置的旋转角度?正如问题所述,应用程序固定为纵向模式,而显示管理器不提供旋转角度,因为显示屏不会旋转。 - arungiri_10
从文档中得知:"当应用程序被锁定为纵向模式时,您可能会使用此功能——因此在旋转时不会发生重新配置——但照片或分析用例需要了解设备的当前旋转。例如,可能需要了解旋转情况以便于面部检测时面部朝向正确,或者将照片设置为横向或纵向。尽管捕获图像的数据是未经旋转的,但Exif数据包含旋转信息,以便图库应用程序可以在保存后以正确的方向显示图像。" - Sudheesh R
是的,你说得对。但是照片或分析用例需要知道设备当前的旋转方向。那么我该如何获取当前的旋转方向呢? - arungiri_10
我理解了你的问题,你可以看看这个答案,我认为它可能会对你有所帮助。如果你担心电池优化问题,也可以尝试一下这个 - Sudheesh R
3个回答

7

我也曾遇到这个问题。解决方法是使用设备传感器数据获取正确的方向,然后将其设置在我的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


但是在创建imageCapture用例时,默认的目标旋转怎么办? - Mohanakrrishna

0

在我们的情况下,尝试使用这个替代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;
}
}

-1
请按照 camerax 的官方文档进行操作:

默认情况下,在创建用例时,摄像机的旋转会与默认显示屏的旋转相匹配。在这种默认情况下,CameraX 会生成输出,以使应用程序能够轻松地匹配预览中所期望看到的内容。您可以通过在配置用例对象时传入当前显示方向或在创建后动态更改来将旋转更改为自定义值,以支持多显示设备。

您可以使用默认的显示旋转和/或从Preview.PreviewOutput()获取的 camerax 元数据组合来为 GLSurfaceView 显示创建变换。

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

根据设置的旋转,每个用例要么直接旋转图像数据,要么向非旋转图像数据的使用者提供旋转元数据。

  • 预览(Preview):提供元数据输出以创建适合 GLSurfaceView 显示的正确转换,使用 Preview.PreviewOutput.getRotationDegrees() 方法。

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接