Flutter相机拍摄图片ML模型处理时边界框坐标偏移问题求助
Flutter相机拍摄图片ML识别边界框偏移问题求助
我是Flutter新手,卡在相机拍摄图片的问题上,求各位提供排查方向或建议。
问题详情
用Flutter应用拍摄的图片显示正常、元数据看似无误,但经机器学习模型处理时,物品能识别成功,但边界框坐标严重偏移,位置完全不对。
应用流程:拍摄图片→上传至AWS后端,由Lambda运行训练好的ML模型识别物品,图片存储于S3桶。模型基于冰箱图片训练,正常识别时会生成正确边界框(如图1)。
当前问题:无论iOS还是Android设备,Flutter应用拍摄并上传的图片在S3中显示正常,但ML处理后的边界框偏移严重(如图2、3),已排除分辨率影响。
已做的排查步骤
- 尝试了camera(0.10.5+3)和image_picker(1.0.4)两个库,结果一致;但用image_picker选取其他APP/原生摄像头拍摄的图片时,处理结果正常。
- 使用React应用/原生摄像头拍摄的图片经相同后端处理,边界框正常。
- 直接上传至S3或通过API Gateway上传结果一致;用image_picker上传其他APP拍摄的图片,处理结果正常。
- 尝试不同分辨率图片,排除分辨率导致的问题。
相关代码
使用camera库的拍摄代码
FloatingActionButton( // Provide an onPressed callback. onPressed: () async { // Take the Picture in a try / catch block. If anything goes wrong, // catch the error. try { // Ensure that the camera is initialized. await _initializeControllerFuture; // Attempt to take a picture and get the file `image` // where it was saved. final image = await cameraController.takePicture(); if (!mounted) return; // If the picture was taken, display it on a new screen. await Navigator.of(context).push( MaterialPageRoute( builder: (context) => DisplayPictureScreen( // Pass the automatically generated path to // the DisplayPictureScreen widget. imagePath: image.path, ), ), ); } catch (e) { // If an error occurs, log the error to the console. debugPrint(e.toString()); } }, child: const Icon(Icons.camera_alt), ),
直接上传至S3的DisplayPictureScreen代码
class DisplayPictureScreen extends StatelessWidget { final String imagePath; const DisplayPictureScreen({super.key, required this.imagePath}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Upload and detect for ingredients')), resizeToAvoidBottomInset: false, body: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.file(File(imagePath)), ElevatedButton( child: const Text('Upload'), onPressed: () async { // HTTP POST request to perform file upload File imageFile = File(imagePath); const region = 'us-west-2'; const signer = AWSSigV4Signer(); final scope = AWSCredentialScope( region: region, service: AWSService.s3); const bucketName = 'upload-bucket-name'; const host = '$bucketName.s3.$region.amazonaws.com'; final serviceConfiguration = S3ServiceConfiguration(); // Create a file and write some contents to it. Then, open it // for reading. final Directory directory = await getApplicationDocumentsDirectory(); final filename = File('${directory.path}/testImage.jpg'); print(filename.path); final uint8List = imageFile.readAsBytesSync(); final file = filename..writeAsBytesSync(uint8List); final contents = file.openRead(); const key = '/testImage.jpg'; // Create a PUT request to the path of the file. print('creating upload requests...'); final uploadRequest = AWSStreamedHttpRequest.raw( method: AWSHttpMethod.put, host: host, // uri: Uri.parse('http://$host'), path: key, body: contents, headers: { AWSHeaders.host: host, AWSHeaders.contentType: 'image/jpeg', }, ); // Sign and send the upload request print('signing and sending upload requests...'); final signedUploadRequest = await signer.sign( uploadRequest, credentialScope: scope, serviceConfiguration: serviceConfiguration, ); final uploadResponse = await signedUploadRequest.send(); } ), ], ), ), ); } }
通过API Gateway上传的DisplayPictureScreen代码
class DisplayPictureScreen extends StatelessWidget { final String imagePath; const DisplayPictureScreen({super.key, required this.imagePath}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Upload and detect for ingredients')), // The image is stored as a file on the device. Use the `Image.file` // constructor with the given path to display the image. resizeToAvoidBottomInset: false, body: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.file(File(imagePath)), ElevatedButton( child: const Text('Upload'), onPressed: () async { final user = FirebaseAuth.instance.currentUser; final idToken = await user?.getIdTokenResult(); // HTTP POST request to perform file upload File imageFile = File(imagePath); // http upload - agw final http.Response response; try { response = await http.post( Uri.parse( "https://my-api-gateway-url.amazonaws.com/Prod/"), // Send authorization headers to the backend. headers: { HttpHeaders.authorizationHeader: idToken!.token.toString(), HttpHeaders.contentTypeHeader: 'image/jpeg', }, // body: blob); body: imageFile.readAsBytesSync()); final List result = json.decode(response.body); final int length = result.length; debugPrint(result.toString()); if (length == 0) { Navigator.push( context, MaterialPageRoute( builder: (context) => const NoResultScreen(), ), ); } else { await Navigator.of(context).push( MaterialPageRoute( builder: (context) => ListIngredientsPage( resultData: result, resultLength: length, ), ), ); } } on Exception catch (_) { rethrow; } } ), ], ), ), ); } }
内容的提问来源于stack exchange,提问作者unacorn
相关产品推荐
相关产品推荐

