我编写了一个 flutter 函数,用于将手机相机预览图像处理为 RGB。它适用于迄今为止我测试过的大多数设备。但对于一台设备(诺基亚 X10),生成的图像看起来很奇怪,我不知道我做错了什么。这就是处理后的相机图像的样子。看起来正确的一个来自我的三星手机,而看起来错误的一个是在诺基亚手机上运行代码获得的。
我验证了两部手机返回的相机图像均使用 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是一个固定的定义。
我发现了问题。 罪魁祸首是这一行
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;
问题解决了!