【问题标题】:How to convert Flutter CameraImage to a Base64-encoded binary data object from an Image Stream如何将 Flutter CameraImage 从图像流转换为 Base64 编码的二进制数据对象
【发布时间】:2019-06-11 07:41:32
【问题描述】:

随着颤振相机版本 0.2.8 中图像流的引入,我尝试将其集成到我的项目中以与 AWS 一起使用。

亚马逊要求图片格式为:

  • 最多 5 MB 的图像字节块。
  • 类型:Base64 编码的二进制数据对象
  • 长度约束:最小长度为 1。最大长度为 5242880。

以前我使用 Camera 包来拍照,加载图片,然后将其转换为亚马逊所需的,但使用 ImageStream 更适合我想做的事情。我之前的做法是:

// Take the picutre
await _cameraController.takePicture(path);

// Load it from my filesystem
File imagefile = new File(path); 

// Convert to amazon requirements
List<int> imageBytes = imagefile.readAsBytesSync();
String base64Image = base64Encode(imageBytes);

但是,使用图像流,我找不到任何简单的方法将CameraImage 转换为亚马逊需要的格式。我对图像没有太多经验,所以我很困惑。

我试图操纵firebase ml & camera stream demo中使用的代码

final int numBytes =
    image.planes.fold(0, (count, plane) => count += plane.bytes.length);
final Uint8List allBytes = Uint8List(numBytes);

int nextIndex = 0;
for (int i = 0; i < image.planes.length; i++) {
  allBytes.setRange(nextIndex, nextIndex + image.planes[i].bytes.length,
      image.planes[i].bytes);
  nextIndex += image.planes[i].bytes.length;
}

// Convert as done previously
String base64Image = base64Encode(allBytes);

但是,AWS 回复了 InvalidImageFormatException。如果有人知道如何正确编码图像,那就太棒了!谢谢

【问题讨论】:

  • 您为什么认为CameraImage 更适合您?它可以访问未压缩的像素数据,而 AWS 似乎需要压缩的编码数据,例如 PNG 或 JPG。 (“Amazon Rekognition 支持 PNG 和 JPEG 图像格式。也就是说,您作为各种 API 操作(例如 DetectLabels 和 IndexFaces)的输入提供的图像必须是受支持的格式之一。”)您试图通过以下方式获得什么好处从有效的方式切换到这种新的方式?如果您从原始字节开始,您将需要自己进行压缩/编码 - 这非常慢。
  • @RichardHeap 我想使用CameraImage 的原因是因为我同时使用 AWS 和 firebase ml 进行面部检测然后进行匹配。 Firebase ml 允许我检测是否有在 example I linked in my post 中完成的人脸。从CameraImage 检测到一张脸后,我想使用同一张照片,将其转换为亚马逊对matching a face 的要求。之后拍照可能会导致人移动并超出框架:(
  • 您得到的CameraImage 几乎肯定是YUV 420 格式(检查cameraImage.format.group 以确认)。将其转换为 RGB,然后转换为 PNG 或 JPEG 并非易事,并且可能在本机代码中做得最好。例如,Android 有一个 YUVImage 类,它有一个 compressToJpeg 方法。尝试在纯 Dart 中做到这一点可能会非常s-l-o-w。您最终可能会编写一个插件来调用原生 Android 和 iOS 函数。有一篇有趣的文章here。
  • @RobC 也一样
  • @RobC 还是同样的解决方案?您找到更好的解决方案了吗?

标签: amazon-web-services dart camera flutter


【解决方案1】:

将图片转成png的解决方案:

Future<Image> convertYUV420toImageColor(CameraImage image) async {
  try {
    final int width = image.width;
    final int height = image.height;
    final int uvRowStride = image.planes[1].bytesPerRow;
    final int uvPixelStride = image.planes[1].bytesPerPixel;

    print("uvRowStride: " + uvRowStride.toString());
    print("uvPixelStride: " + uvPixelStride.toString());

    // imgLib -> Image package from https://pub.dartlang.org/packages/image
    var img = imglib.Image(width, height); // Create Image buffer

    // Fill image buffer with plane[0] from YUV420_888
    for(int x=0; x < width; x++) {
      for(int y=0; y < height; y++) {
        final int uvIndex = uvPixelStride * (x/2).floor() + uvRowStride*(y/2).floor();
        final int index = y * width + x;

        final yp = image.planes[0].bytes[index];
        final up = image.planes[1].bytes[uvIndex];
        final vp = image.planes[2].bytes[uvIndex];
        // Calculate pixel color
        int r = (yp + vp * 1436 / 1024 - 179).round().clamp(0, 255);
        int g = (yp - up * 46549 / 131072 + 44 -vp * 93604 / 131072 + 91).round().clamp(0, 255);
        int b = (yp + up * 1814 / 1024 - 227).round().clamp(0, 255);     
        // color: 0x FF  FF  FF  FF 
        //           A   B   G   R
        img.data[index] = (0xFF << 24) | (b << 16) | (g << 8) | r;
      }
    }

    imglib.PngEncoder pngEncoder = new imglib.PngEncoder(level: 0, filter: 0);
    List<int> png = pngEncoder.encodeImage(img);
    muteYUVProcessing = false;
    return Image.memory(png);  
  } catch (e) {
    print(">>>>>>>>>>>> ERROR:" + e.toString());
  }
  return null;
}

来源:https://github.com/flutter/flutter/issues/26348#issuecomment-462321428

【讨论】:

  • 如何将其转换为 RBGA_8888 格式(适用于 iOS)?
【解决方案2】:

您可以使用此直接将图像文件转换为base64。

图像编码:- var imageFilePath = await picker.getImage(source: ImageSource.gallery);

最终字节 = ImageFilePath.readAsBytesSync(); String _img64 = base64Encode(字节);

图像解码:- _img64 = base64Decode(response.bodyBytes); image.memory(_img64);

【讨论】:

    【解决方案3】:

    将图库图片转换为 base 64 Flutter

    Future getImageFromGallery() async {
        var image = await ImagePicker.pickImage(source: ImageSource.gallery);
        final bytes = Io.File(image.path).readAsBytesSync();
        String img64 = base64Encode(bytes);
      }
    

    【讨论】:

      【解决方案4】:

      我正在使用此代码将 YUV_420 888 转换为 PNG

      // CameraImage YUV420_888 -> PNG -> Image (compresion:0, filter: none)
      // Black
      imglib.Image _convertYUV420(CameraImage image) {
        var img = imglib.Image(image.width, image.height); // Create Image buffer
      
        Plane plane = image.planes[0];
        const int shift = (0xFF << 24);
      
        // Fill image buffer with plane[0] from YUV420_888
        for (int x = 0; x < image.width; x++) {
          for (int planeOffset = 0;
          planeOffset < image.height * image.width;
          planeOffset += image.width) {
            final pixelColor = plane.bytes[planeOffset + x];
            // color: 0x FF  FF  FF  FF
            //           A   B   G   R
            // Calculate pixel color
            var newVal = shift | (pixelColor << 16) | (pixelColor << 8) | pixelColor;
      
            img.data[planeOffset + x] = newVal;
          }
        }
      
        return img;
      }
      

      然后创建一个 PNG

          Future<List<int>> convertImagetoPng(CameraImage image) async {
        try {
          imglib.Image img;
          if (image.format.group == ImageFormatGroup.yuv420) {
            img = convertYUV420_ToPNG(image);
          } else if (image.format.group == ImageFormatGroup.bgra8888) {
            img = convertBGRA8888_ToPNG(image);
          }
      
          imglib.PngEncoder pngEncoder = new imglib.PngEncoder();
      
          // Convert to png
          List<int> png = pngEncoder.encodeImage(img);
          return png;
        } catch (e) {
          print(">>>>>>>>>>>> ERROR:" + e.toString());
        }
        return null;
      }
      

      作者 hugand
      您也可以检查性能

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-17
        • 1970-01-01
        • 2012-11-02
        • 2011-04-27
        • 2014-06-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多