使用图像分析在纵向模式下图像无法正确旋转

问题描述 投票:0回答:1

在使用 CameraX 库中的 ImageAnalysis 类时,我在 Android 应用程序中遇到图像旋转问题。在特定设备(华为 Nova 12 SE)上,纵向模式拍摄的图像无法正确旋转。在我测试的其他设备(Pixel 7、三星 Galaxy A55)上运行良好。

相关代码如下:

fun <T, R> analyzeImageAsync(
        imageProxy: ImageProxy,
        onProcess: (input: InputImage) -> Task<T>,
        transform: (result: T) -> R?
    ): Deferred<R?> = scope.async {
        val image = InputImage.fromMediaImage(
             imageProxy.image ?: return@async null,
            imageProxy.imageInfo.rotationDegrees
        )

        suspendCoroutine { continuation ->
            onProcess(image)
                .addOnSuccessListener { result ->
                    continuation.resume(transform(result))
                }.addOnFailureListener { exception ->
                    continuation.resumeWithException(exception)
                }
        }
    }

当我查看捕获的图像时,我看到图像旋转了 90 度,将旋转度更改为 0 不会改变图像的结果。

我也尝试将图像更改为Bitmap,希望能解决问题,但结果是一样的:

fun <T, R> analyzeImageAsync(
    imageProxy: ImageProxy,
    onProcess: (input: InputImage) -> Task<T>,
    transform: (result: T) -> R?
): Deferred<R?> = scope.async {
    val bitmap = imageProxy.toBitmap() 
    val inputImage = InputImage.fromBitmap(bitmap, imageProxy.imageInfo.rotationDegrees) 
    // Further processing...
}

有什么帮助吗?

编辑:

第一个图像是我期望的图像,第二个是我得到的图像,它是旋转的。

enter image description here

enter image description here

android android-camerax
1个回答
0
投票

将 ImageProxy 转换为 Bitmap 并应用手动旋转:将 ImageProxy 转换为 Bitmap 后需要手动应用旋转。这允许您通过旋转度数来解释任何特定于设备的怪癖。

这是代码的固定版本:

 fun ImageProxy.toBitmap(): Bitmap {
    val yBuffer = planes[0].buffer
    val uBuffer = planes[1].buffer
    val vBuffer = planes[2].buffer

    val ySize = yBuffer.remaining()
    val uSize = uBuffer.remaining()
    val vSize = vBuffer.remaining()

    val nv21 = ByteArray(ySize + uSize + vSize)

    yBuffer.get(nv21, 0, ySize)
    vBuffer.get(nv21, ySize, vSize)
    uBuffer.get(nv21, ySize + vSize, uSize)

    val yuvImage = YuvImage(nv21, ImageFormat.NV21, width, height, null)
    val out = ByteArrayOutputStream()
    yuvImage.compressToJpeg(Rect(0, 0, width, height), 100, out)
    val imageBytes = out.toByteArray()

    return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
}

fun rotateBitmap(bitmap: Bitmap, rotationDegrees: Int): Bitmap {
    val matrix = Matrix().apply {
        postRotate(rotationDegrees.toFloat())
    }
    return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
}

fun <T, R> analyzeImageAsync(
    imageProxy: ImageProxy,
    onProcess: (input: InputImage) -> Task<T>,
    transform: (result: T) -> R?
): Deferred<R?> = scope.async {
    val bitmap = imageProxy.toBitmap()
    val rotationDegrees = imageProxy.imageInfo.rotationDegrees
    val rotatedBitmap = rotateBitmap(bitmap, rotationDegrees)

    val inputImage = InputImage.fromBitmap(rotatedBitmap, 0) // Pass 0 since we manually rotate
    suspendCoroutine { continuation ->
        onProcess(inputImage)
            .addOnSuccessListener { result ->
                continuation.resume(transform(result))
            }
            .addOnFailureListener { exception ->
                continuation.resumeWithException(exception)
            }
    }
}

toBitmap() 转换:使用 YuvImage 将 ImageProxy 从 YUV 格式转换为位图,以确保正确处理图像缓冲区。 使用矩阵手动旋转:rotateBitmap() 方法根据 imageProxy.imageInfo.rotationDegrees 旋转位图。这可以处理不同设备上的旋转不一致问题。 InputImage 中的零旋转:由于位图已经旋转,因此将 0 作为旋转参数传递给 InputImage.fromBitmap()。

© www.soinside.com 2019 - 2024. All rights reserved.