将InputImage转换为Bitmap的有效方法

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

我必须使用 Java 将 com.google.mlkit.vision.common.InputImage 转换为 Android 中的等效位图图像。现在我正在使用以下代码。

// iImage is an object of InputImage
Bitmap bmap = Bitmap.createBitmap(iImage.getWidth(), iImage.getHeight(), Bitmap.Config.RGB_565);
bmap.copyPixelsFromBuffer(iImage.getByteBuffer());

上面的代码没有将InputImage转换为Bitmap。谁能建议我将 InputImage 转换为 Bitmap 的有效方法。

android bitmap
2个回答
0
投票

您可以从 byteBuffer 创建位图,可以通过调用 getByteBuffer() 方法接收位图。在 ML Kit Vision 的官方快速入门示例中,您可以找到如何实现这一点的方法。下面是一段可以解决您的问题的代码: getBitmap() 方法将 NV21 格式字节缓冲区转换为位图:

@Nullable
  public static Bitmap getBitmap(ByteBuffer data, FrameMetadata metadata) {
    data.rewind();
    byte[] imageInBuffer = new byte[data.limit()];
    data.get(imageInBuffer, 0, imageInBuffer.length);
    try {
      YuvImage image =
          new YuvImage(
              imageInBuffer, ImageFormat.NV21, metadata.getWidth(), metadata.getHeight(), null);
      ByteArrayOutputStream stream = new ByteArrayOutputStream();
      image.compressToJpeg(new Rect(0, 0, metadata.getWidth(), metadata.getHeight()), 80, stream);

      Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());

      stream.close();
      return rotateBitmap(bmp, metadata.getRotation(), false, false);
    } catch (Exception e) {
      Log.e("VisionProcessorBase", "Error: " + e.getMessage());
    }
    return null;
  }

rotateBitmap()方法:

private static Bitmap rotateBitmap(
      Bitmap bitmap, int rotationDegrees, boolean flipX, boolean flipY) {
    Matrix matrix = new Matrix();

    // Rotate the image back to straight.
    matrix.postRotate(rotationDegrees);

    // Mirror the image along the X or Y axis.
    matrix.postScale(flipX ? -1.0f : 1.0f, flipY ? -1.0f : 1.0f);
    Bitmap rotatedBitmap =
        Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);

    // Recycle the old bitmap if it has changed.
    if (rotatedBitmap != bitmap) {
      bitmap.recycle();
    }
    return rotatedBitmap;
  }

点击链接即可查看完整代码:https://github.com/googlesamples/mlkit/blob/master/android/vision-quickstart/app/src/main/java/com/google/mlkit/视觉/演示/BitmapUtils.java


0
投票

在 ML Kit 版本 16.0.0-beta1 中,

InputImage
具有三种可能的支持数据结构:

使用的支持数据结构由构造函数确定:

  • Bitmap

    • InputImage.fromFilePath()
    • InputImage.fromBitmap()
    • 有时
      InputImage.fromMediaImage()
  • ByteBuffer

    • InputImage.fromByteArray()
    • InputImage.fromByteBuffer()
  • Image

    • 有时
      InputImage.fromMediaImage()

每个

InputImage
对象仅使用一个后备数据结构,这意味着其他后备数据获取器将返回 null。

如果支持位图可用,这个问题就已经有了答案。但是,如果找不到怎么办?

有一个方法

InputImage.getFormat()
可以返回代表不同图像格式的4个不同的常量整数值。
IMAGE_FORMAT_NV21
IMAGE_FORMAT_YV12
IMAGE_FORMAT_BITMAP
IMAGE_FORMAT_YUV_420_888

仅当支持数据是

IMAGE_FORMAT_BITMAP

 时才使用 
Bitmap
。所以剩下的是三种 YUV 图像格式和两种可能的支持数据结构。

ByteBuffer
将使用
IMAGE_FORMAT_NV21
IMAGE_FORMAT_YV12

Image
总是使用
IMAGE_FORMAT_YUV_420_888

这三种YUV格式直接对应于

android.graphics.ImageFormat
,可以在这里阅读:
https://developer.android.com/reference/android/graphics/ImageFormat

我会简单地请求每个支持数据元素,直到获得非空值。从那时起,如果它是位图,那么您的工作就完成了。对于其他人...

我在 Stack Overflow 上发现的一个不太理想的解决方案是转换为

android.graphics.YuvImage
,使用它的
compressToJPEG()
方法获取 JPEG 压缩字节的输出并将这些字节通过管道传输到
BitmapFactory.decodeByteArray() 
创建一个
Bitmap
,如此处所示。

虽然这样效率很低,但直接转换无疑是可能的。

使用上述信息进行研究应该足以帮助您实现目标。但为了帮助您顺利完成旅程,这里还有一些资源。

  • Jim Bar 的“关于 YUV 格式”,用于学习 YUV 格式的一般概念以及各种 YUV 格式之间的差异

  • Christopher Wright的“YUV Colorspace”,用于了解从 YUV 到 RGB 转换的实际算法,其中最重要的公式如下所示:

    R = Y + 1.4075 * (V - 128)  
    G = Y - 0.3455 * (U - 128) - (0.7169 * (V - 128))  
    B = Y + 1.7790 * (U - 128)  
    

我可能会在将来编辑完整的实现,因为我自己将来可能会担心这个问题。但是,我很可能会使用上面提供的信息。

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