You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 10:27:04