Flutter中如何将CameraImage流转换为Bytes/File供Google ML Kit使用
实现方案
推荐优先使用InputImage.fromBytes构造方法,不需要额外写文件到磁盘,实时处理性能最优,也可以根据需求选择转文件的方案。
方案1:直接从Camera图像流提取Bytes构造InputImage(推荐)
CameraController返回的image是CameraImage类型,你需要先拼接图像平面的字节数据,同时构造对应的InputImageData传入即可,代码示例如下:
_cameraService.cameraController.startImageStream((image) async { // 1. 拼接所有图像平面的字节 final allBytes = <int>[]; for (var plane in image.planes) { allBytes.addAll(plane.bytes); } final bytes = Uint8List.fromList(allBytes); // 2. 构造InputImageData final inputImageData = InputImageData( size: Size(image.width.toDouble(), image.height.toDouble()), imageRotation: _cameraService.cameraController.description.sensorOrientation, inputImageFormat: InputImageFormatValue.fromRawValue(image.format.raw) ?? InputImageFormat.nv21, planeData: image.planes.map( (Plane plane) { return InputImagePlaneMetadata( bytesPerRow: plane.bytesPerRow, height: plane.height, width: plane.width, ); }, ).toList(), ); // 3. 构造InputImage直接传给ML Kit final inputImage = InputImage.fromBytes(bytes: bytes, inputImageData: inputImageData); // 后续调用ML Kit面部检测接口即可 });
注意:如果是iOS平台,图像格式默认是bgra8888,上面的inputImageFormat自动识别逻辑可以适配,无需额外调整
方案2:转临时File使用
如果需要持久化存储图像或者更适配你的业务逻辑,可以将图像编码为图片文件存到临时目录,再用fromFile或者fromFilePath构造:
import 'dart:io'; import 'package:image/image.dart' as img; import 'package:path_provider/path_provider.dart'; _cameraService.cameraController.startImageStream((image) async { // 1. 将CameraImage转换为可编码的图片格式 img.Image convertedImage; if (Platform.isAndroid) { // Android默认是YUV420格式,转RGB convertedImage = img.Image.fromBytes( image.width, image.height, image.planes[0].bytes, format: img.Format.yuv420, ); } else if (Platform.isIOS) { // iOS默认是BGRA8888格式,转RGB convertedImage = img.Image.fromBytes( image.width, image.height, image.planes[0].bytes, format: img.Format.bgra, ); } // 2. 编码为png写入临时目录 final tempDir = await getTemporaryDirectory(); final file = File('${tempDir.path}/temp_frame.png'); await file.writeAsBytes(img.encodePng(convertedImage)); // 3. 构造InputImage final inputImage = InputImage.fromFile(file); // 或者 final inputImage = InputImage.fromFilePath(file.path); });
注意:该方案因为涉及磁盘IO和图片编码,性能比方案1低,不适合高帧率实时处理场景
内容的提问来源于stack exchange,提问作者user16788731
相关产品推荐
相关产品推荐

