Flutter ML Kit姿势检测坐标与屏幕位置不匹配,如何正确放置自定义Widget
Flutter ML Kit 姿势关键点坐标匹配解决方案
问题核心
ML Kit 返回来的人体关键点坐标是相对于输入推理的原始图像帧的尺寸,并非你页面中实际渲染的相机预览Widget的尺寸,再加上相机预览的宽高比适配、横竖屏旋转、前后摄像头镜像三个变量的影响,直接使用原始坐标必然会出现位置错位、偏移的问题。
修复步骤
1. 采集基础参数
你需要提前拿到3组核心参数:
- 原始输入帧的尺寸:即传入ML Kit做推理的
InputImage对应的宽高 - 实际渲染的相机预览尺寸:通过绑定
GlobalKey到相机预览组件的父容器获取:
final GlobalKey previewKey = GlobalKey(); // 绑定到你包裹CameraPreview的Container上 // 组件渲染完成后获取实际尺寸 Size previewSize = previewKey.currentContext!.size!;
- 设备当前方向、相机朝向(前置/后置)
2. 计算缩放与偏移参数
相机预览一般默认按BoxFit.cover适配屏幕,需要先计算缩放比和适配偏移:
// 适配横竖屏,调整原始输入帧的宽高 bool isLandscape = MediaQuery.of(context).orientation == Orientation.landscape; double adjustedInputWidth = isLandscape ? inputImageSize.width : inputImageSize.height; double adjustedInputHeight = isLandscape ? inputImageSize.height : inputImageSize.width; // 计算缩放比,cover模式取宽高缩放的最大值 double scaleX = previewSize.width / adjustedInputWidth; double scaleY = previewSize.height / adjustedInputHeight; double finalScale = max(scaleX, scaleY); // 计算宽高比不一致产生的留白偏移 double offsetX = (previewSize.width - adjustedInputWidth * finalScale) / 2; double offsetY = (previewSize.height - adjustedInputHeight * finalScale) / 2;
3. 转换原始关键点坐标到屏幕坐标
// 取原始关键点坐标 double rawX = pose.landmarks[PoseLandmarkType.rightShoulder]!.x; double rawY = pose.landmarks[PoseLandmarkType.rightShoulder]!.y; // 适配横竖屏转换坐标 double adjustedX, adjustedY; if (isLandscape) { adjustedX = rawX; adjustedY = rawY; } else { adjustedX = rawY; adjustedY = inputImageSize.width - rawX; } // 应用缩放和偏移得到屏幕坐标 double screenX = adjustedX * finalScale + offsetX; double screenY = adjustedY * finalScale + offsetY; // 前置摄像头需要做x轴镜像翻转 bool isFrontCamera = /*你的相机朝向判断逻辑*/; if (isFrontCamera) { screenX = previewSize.width - screenX; } // 最终更新坐标 setState(() { x = screenX; y = screenY; });
4. 自定义Widget位置微调
如果你希望自定义Widget的中心点对准关键点,需要在Positioned参数里减去Widget自身宽高的一半:
Positioned( // 假设你的自定义Widget宽高都是20 left: x - 10, top: y - 10, child: YourCustomMarker(), )
内容的提问来源于stack exchange,提问作者Débora
相关产品推荐
相关产品推荐

