Flutter中如何将MLKit的InputImage转换为Image组件?
InputImage转Flutter Image组件的解码异常解决方法
问题描述
google_mlkit_commons定义了InputImage,我用camerawesome获取相机图像并通过MLKit文本识别器分析,文本识别功能正常,但尝试用InputImage.bytes创建Image组件时抛出异常:
Failed to decode image. E/FlutterJNI(31225): android.graphics.ImageDecoder$DecodeException: Failed to create image decoder with message 'unimplemented'Input contained an error.
问题原因
InputImage的字节数据是YUV格式(如NV21),而Flutter的Image.memory仅支持解码PNG、JPEG、RGBA等常见图像格式,无法直接解析YUV格式的原始字节流,因此导致解码失败。
解决方案
方案一:通过image库转换YUV格式为RGBA
- 在
pubspec.yaml中添加依赖:
dependencies: image: ^4.0.17 # 版本可根据最新情况调整
- 修改
_processImage方法,将NV21格式字节转换为RGBA格式后生成Image组件:
import 'package:image/image.dart' as img; Future<void> _processImage(AnalysisImage image) async { final InputImage inputImage = image.toInputImage(); if (_isBusy) return; _isBusy = true; final RecognizedText recognizedText = await _textRecognizer.processImage(inputImage); final String text = recognizedText.text.toLowerCase(); if ((text.isNotEmpty) && (text.contains('hoje'))) { img.Image? convertedImage; if (inputImage.format == InputImageFormat.nv21) { final size = inputImage.size; // 解码NV21格式为Image对象 convertedImage = img.decodeNv21( inputImage.bytes!, size.width.toInt(), size.height.toInt(), ); // 根据相机旋转角度调整图像方向 convertedImage = img.copyRotate(convertedImage, inputImage.rotation.rawValue * 90); // 编码为PNG字节流 final pngBytes = img.encodePng(convertedImage); setState(() { _image = Image.memory(pngBytes); }); } } _isBusy = false; }
方案二:直接从camerawesome获取JPEG格式图像
如果不需要用YUV格式进行ML分析,可调整camerawesome配置,直接获取JPEG格式图像数据,无需额外转换即可用Image.memory显示:
// 修改CameraAwesomeBuilder的图像分析配置 CameraAwesomeBuilder.previewOnly( imageAnalysisConfig: AnalysisConfig( androidOptions: const AndroidAnalysisOptions.jpeg( // 切换为JPEG格式 width: 1024, ), maxFramesPerSecond: 5, autoStart: true, ), onImageForAnalysis: _processImage, builder: (CameraState cameraModeState, previewSize, previewRect) { return AwesomeCameraLayout(state: cameraModeState); }, )
对应修改_processImage方法:
Future<void> _processImage(AnalysisImage image) async { final InputImage inputImage = image.toInputImage(); if (_isBusy) return; _isBusy = true; final RecognizedText recognizedText = await _textRecognizer.processImage(inputImage); final String text = recognizedText.text.toLowerCase(); if ((text.isNotEmpty) && (text.contains('hoje'))) { setState(() { // 直接使用JPEG字节创建Image组件 _image = Image.memory(image.when( jpeg: (img) => img.bytes, nv21: (img) => img.bytes, bgra8888: (img) => img.bytes, )!); }); } _isBusy = false; }
注意事项
- 方案一中要注意匹配相机的旋转角度,避免图像显示方向错误;
- 方案二中MLKit文本识别器同样支持JPEG格式的
InputImage,不会影响原有识别功能。
内容的提问来源于stack exchange,提问作者mabg
相关产品推荐
相关产品推荐

