flutter中的YUV420图像转换

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

我编写了一个 flutter 函数,用于将手机相机预览图像处理为 RGB。它适用于迄今为止我测试过的大多数设备。但对于一台设备(诺基亚 X10),生成的图像看起来很奇怪,我不知道我做错了什么。这就是处理后的相机图像的样子。看起来正确的一个来自我的三星手机,而看起来错误的一个是在诺基亚手机上运行代码获得的。

Samsung after yuv420 processing

我验证了两部手机返回的相机图像均使用 YUV420_888

这是我的 yuv 转换代码:

  static img.Image convertYUV420toImageColor(CameraImage image) {
    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;
      myLogger.d(image.planes[0].bytesPerRow); // nokia: 512, samsung: 320
      myLogger.d(image.planes[0].bytesPerPixel); // 1 for both phones
      myLogger.d(image.planes[1].bytesPerRow); // nokia: 512, samsung: 320
      myLogger.d(image.planes[1].bytesPerPixel); // 2 for both phones
      myLogger.d(image.planes[2].bytesPerRow); // nokia: 512, samsung: 320
      myLogger.d(image.planes[2].bytesPerPixel); // 2 for both phones

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

      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);
          img2.setPixelRgba(x, y, r, g, b, 255);
        }
      }

      return img.copyRotate(img2, angle: 90); //Image.memory(png);
    } catch (e) {
      Log.logger.d("ERROR: " + e.toString());
    }
    throw Exception("error during YUV420 conversion");
  }

我的印象是任何 YUV420_888 转换都适用于我的代码,但我的测试表明情况并非如此。我无法找到两个设备之间指定的图像格式的差异。

我在这里做错了什么?我什至不确定什么参数可能是错误转换的原因。我以为YUV420_888是一个固定的定义。

android flutter image image-processing
1个回答
0
投票

我发现了问题。 罪魁祸首是这一行

final int index = y * width + x;

我错误地认为

width
始终等于
image.planes[0].bytesPerRow
但我的问题中显示的值已经指出它们可能不同(512 与 320)。

附加长度是转换图像时需要正确调整的填充。如果不这样做,就会出现条纹,因为处理使用了错误的 y 值。

只需将计算更正为

final int bytesPerRowY = image.planes[0].bytesPerRow;
final int index = y * bytesPerRowY + x;

问题解决了!

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