TensorFlow二头肌弯举计数异常:计数器持续递增问题求助
二头肌弯举计数重复递增问题修复方案
问题根源
计数器持续递增的核心原因是React useState的更新是异步的:
- 当检测到
angle < 40且stage === 'down'时,你调用setStage('up')和setCanCount(false),但这两个状态的更新不会立刻生效 - 由于pose检测按帧持续执行(每一帧都会调用
countReps),接下来的几帧里stage依然是down、canCount依然是true,导致重复触发计数器递增
修复方案
方案1:使用Ref跟踪实时状态(推荐)
Ref的更新是同步的,能立刻反映当前状态,避免异步更新带来的延迟问题:
const webcamRef = useRef(null); const canvasRef = useRef(null); const [pose, setPose] = useState(null); const [counter, setCounter] = useState(0); const [stage, setStage] = useState('down'); // 仅用于UI展示 const [angle, setAngle] = useState(0); // 用Ref跟踪实时状态 const stageRef = useRef('down'); const canCountRef = useRef(true); const countReps = (pose) => { const confidenceThreshold = 0.35; const leftShoulder = pose.keypoints.find(point => point.part === 'leftShoulder' && point.score > confidenceThreshold); const leftElbow = pose.keypoints.find(point => point.part === 'leftElbow' && point.score > confidenceThreshold); const leftWrist = pose.keypoints.find(point => point.part === 'leftWrist' && point.score > confidenceThreshold); if (leftShoulder && leftElbow && leftWrist) { const angle = calculateAngle(leftShoulder.position, leftElbow.position, leftWrist.position); setAngle(angle); if (angle > 140) { // 同步更新Ref状态 stageRef.current = 'down'; canCountRef.current = true; // 同步更新UI状态 setStage('down'); console.log('Stage changed to down'); } else if (angle < 40 && stageRef.current === 'down' && canCountRef.current) { setCounter(prevCounter => prevCounter + 1); // 同步更新Ref状态,立刻阻止重复计数 canCountRef.current = false; stageRef.current = 'up'; // 同步更新UI状态 setStage('up'); console.log('Stage changed to up'); } } else { console.log("Key points not detected or not confident enough"); } };
方案2:优化状态判断逻辑
如果不想用Ref,可以在计数条件中加入canCount的检查,确保只有允许计数时才触发递增:
const countReps = (pose) => { const confidenceThreshold = 0.35; const leftShoulder = pose.keypoints.find(point => point.part === 'leftShoulder' && point.score > confidenceThreshold); const leftElbow = pose.keypoints.find(point => point.part === 'leftElbow' && point.score > confidenceThreshold); const leftWrist = pose.keypoints.find(point => point.part === 'leftWrist' && point.score > confidenceThreshold); if (leftShoulder && leftElbow && leftWrist) { const angle = calculateAngle(leftShoulder.position, leftElbow.position, leftWrist.position); setAngle(angle); if (angle > 140) { setStage('down'); setCanCount(true); console.log('Stage changed to down'); } else if (angle < 40 && stage === 'down' && canCount) { setCounter(prevCounter => prevCounter + 1); setCanCount(false); setStage('up'); console.log('Stage changed to up'); } } else { console.log("Key points not detected or not confident enough"); } };
说明
- 方案1的Ref方式更可靠,因为它能实时同步状态,不会受React状态更新异步性的影响
- 两种方案的核心逻辑都是:确保一次完整的弯举动作(从down到up再回到down)只会触发一次计数
内容的提问来源于stack exchange,提问作者Laura Nguyen
相关产品推荐
相关产品推荐

