如何将nv21 CameraImage转换为Flutter图像

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

我正在使用 google_mlkit_face_detection 来检测人脸,但我找不到将 nv21 帧转换为 flutter 图像格式的好方法(package:image/src/image.dart )

问题仅在Android上,因为人脸检测包要求在Android上的CameraController中使用nv21格式,并且我需要返回用人脸检测包检测到的人脸的帧(CameraImage对象),但我找不到任意位置从 nv21 到 Flutter 格式的转换函数。

我找到了YUV420的:

import 'package:google_mlkit_face_detection/google_mlkit_face_detection.dart';
import 'package:image/image.dart' as img;


static img.Image _convertYUV420(CameraImage input) {

   var imge = img.Image(input.width, input.height); // Create Image buffer

   Plane plane = input.planes[0];
   const int shift = (0xFF << 24);

   // Fill image buffer with plane[0] from YUV420_888
   for (int x = 0; x < input.width; x++) {
     for (int planeOffset = 0;
         planeOffset < input.height * input.width;
         planeOffset += input.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;

       imge.data[planeOffset + x] = newVal;
     }
   }

   return imge;
 }

和bgra8888:

  import 'package:google_mlkit_face_detection/google_mlkit_face_detection.dart';
  import 'package:image/image.dart' as img;


  static img.Image _convertBGRA8888(CameraImage image) {
     return img.Image.fromBytes(
       (image.planes[0].bytesPerRow / 4).round(),
       image.height,
       image.planes[0].bytes,
       format: img.Format.argb,
     );
  }

但不适用于 nv21,

最后我找到了执行转换的代码,但是照片顺时针旋转了90度(或逆时针旋转270度),但我不知道如何纠正它

  static img.Image _convertNV21(CameraImage image) {

final width = image.width.toInt();
final height = image.height.toInt();

Uint8List yuv420sp = image.planes[0].bytes;

final outImg = img.Image(height, width); 
final int frameSize = width * height;

for (int j = 0, yp = 0; j < height; j++) {
  int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
  for (int i = 0; i < width; i++, yp++) {
    int y = (0xff & yuv420sp[yp]) - 16;
    if (y < 0) y = 0;
    if ((i & 1) == 0) {
      v = (0xff & yuv420sp[uvp++]) - 128;
      u = (0xff & yuv420sp[uvp++]) - 128;
    }
    int y1192 = 1192 * y;
    int r = (y1192 + 1634 * v);
    int g = (y1192 - 833 * v - 400 * u);
    int b = (y1192 + 2066 * u);

    if (r < 0)
      r = 0;
    else if (r > 262143) r = 262143;
    if (g < 0)
      g = 0;
    else if (g > 262143) g = 262143;
    if (b < 0)
      b = 0;
    else if (b > 262143) b = 262143;

    // I don't know how these r, g, b values are defined, I'm just copying what you had bellow and
    // getting their 8-bit values.
    outImg.setPixelRgba(i, j, ((r << 6) & 0xff0000) >> 16,
        ((g >> 2) & 0xff00) >> 8, (b >> 10) & 0xff);
  }
}
return outImg;
}

有人有什么建议吗?

flutter face-detection
1个回答
0
投票

按照代码片段将 nv21 转换为图像

imglib.Image _convertNV21(CameraImage image) {
  final width = image.width.toInt();
  final height = image.height.toInt();
  Uint8List yuv420sp = image.planes[0].bytes;

  // Initial conversion from NV21 to RGB
  final outImg = imglib.Image(height, width); // Note the swapped dimensions
  final int frameSize = width * height;

  for (int j = 0, yp = 0; j < height; j++) {
    int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
    for (int i = 0; i < width; i++, yp++) {
      int y = (0xff & yuv420sp[yp]) - 16;
      if (y < 0) y = 0;
      if ((i & 1) == 0) {
        v = (0xff & yuv420sp[uvp++]) - 128;
        u = (0xff & yuv420sp[uvp++]) - 128;
      }
      int y1192 = 1192 * y;
      int r = (y1192 + 1634 * v);
      int g = (y1192 - 833 * v - 400 * u);
      int b = (y1192 + 2066 * u);

      if (r < 0) {
        r = 0;
      } else if (r > 262143) r = 262143;
      if (g < 0) {
        g = 0;
      } else if (g > 262143) g = 262143;
      if (b < 0) {
        b = 0;
      } else if (b > 262143) b = 262143;

      outImg.setPixelRgba(j, width - i - 1, ((r << 6) & 0xff0000) >> 16,
          ((g >> 2) & 0xff00) >> 8, (b >> 10) & 0xff);
    }
  }
  return outImg;
  // Rotate the image by 90 degrees (or 270 degrees if needed)
  // return imglib.copyRotate(outImg, -90); // Use -90 for a 270 degrees rotation
}

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