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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 05:33:13