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

Node.js调用Python YOLO进程未执行相机移动及休眠问题排查

Node.js调用YOLO控制相机异常问题排查与解决

问题描述

我想用Node.js调用Python的YOLO完成人体检测,拿到人体坐标后控制相机移动。已经写了用spawn启动Python进程的代码,也实现了监听stderr处理坐标、控制相机的逻辑,但目前进程持续接收数据,相机移动和休眠功能均未执行,无法定位问题。

相关代码

Node.js进程启动代码

const yoloProcess = spawn(
  "C:\\Users\\LAB908\\anaconda3\\envs\\yolov5\\python",
  [
    "C:\\Users\\LAB908\\Downloads\\yolov5-deepsparse-blogpost-main\\yolov5-train\\detect.py",
    "--class",
    "0",
    "--weights",
    "yolov5s.pt",
    "--source",
    "rtsp://admin:123456@169.254.10.100/stream0",
  ],
  {
    encoding: "utf8",
  }
);

Node.js坐标处理与相机控制逻辑

var i = 1;
yoloProcess.stderr.on("data", async (data) => {
  left = data.toString().split(",")[0].replace("(", "");
  right = data.toString().replace(")", "").replace("\n", "").split(",")[1];
  //console.log(data.toString());

  console.log("left:" + String(left));
  console.log("right:" + String(right));

  await sleep(3000);
  pos.push((parseFloat(right) + parseFloat(left)) / 2);

  console.log(pos);

  if (pos[i] - pos[i - 1] > 0) {
    await move_right();
    console.log("move right");
  } else if (pos[i] - pos[i - 1] < 0) {
    await move_left();
    console.log("move left");
  } else {
    await move_stop();
    console.log("do not move");
  }
});

问题根源分析

  • 异步回调并发冲突:stderr.on("data")会被YOLO的高频帧输出持续触发,每个回调都是异步执行。await sleep(3000)仅阻塞当前回调,但新的data事件会立刻启动新的回调,导致多个控制逻辑同时运行,相机指令被打乱,休眠效果也被并发回调抵消。
  • 数据解析不可靠:直接按逗号分割data的方式未做过滤,YOLO的stderr会输出初始化日志、帧率信息等非坐标内容,分割后得到的left/right可能是无效字符串,后续数值计算出错,相机控制逻辑无法进入正确分支。
  • 索引逻辑错误:初始i=1,但pos数组为空,第一次push后数组长度为1,pos[i]即pos[1]为undefined,差值计算结果为NaN,所有条件判断都不成立,相机控制代码完全未执行。

修复方案

1. 限制回调并发,实现帧过滤

通过标记位控制同一时间仅处理一组坐标,避免回调堆积,同时只处理有效坐标:

let isProcessing = false;
let latestCoords = null;
const pos = []; // 确保pos已初始化

yoloProcess.stderr.on("data", (data) => {
  const rawStr = data.toString().trim();
  // 仅处理符合"(x,y)"格式的行
  if (rawStr.startsWith("(") && rawStr.endsWith(")")) {
    const [leftStr, rightStr] = rawStr.replace(/[()]/g, "").split(",");
    const left = parseFloat(leftStr);
    const right = parseFloat(rightStr);
    if (!isNaN(left) && !isNaN(right)) {
      latestCoords = { left, right };
    }
  }

  // 当前无处理任务时,启动坐标处理流程
  if (!isProcessing && latestCoords) {
    isProcessing = true;
    processCoords(latestCoords).finally(() => {
      isProcessing = false;
      latestCoords = null;
    });
  }
});

async function processCoords(coords) {
  const { left, right } = coords;
  console.log(`left: ${left}, right: ${right}`);

  await sleep(3000);
  const center = (left + right) / 2;
  pos.push(center);

  console.log(pos);

  // 数组至少有2个元素再做移动判断
  if (pos.length >= 2) {
    const diff = pos[pos.length - 1] - pos[pos.length - 2];
    if (diff > 0) {
      await move_right();
      console.log("move right");
    } else if (diff < 0) {
      await move_left();
      console.log("move left");
    } else {
      await move_stop();
      console.log("do not move");
    }
  } else {
    await move_stop();
    console.log("initial position, stop moving");
  }
}

2. 优化YOLO输出格式(更可靠)

修改YOLO的detect.py,让它仅将有效人体坐标以JSON格式输出到stdout,避免和日志混在一起:

# 在detect.py的检测循环中添加以下代码(找到处理检测结果的位置)
import json
for *xyxy, conf, cls in reversed(det):
    if int(cls) == 0:  # 仅处理人体类(class 0)
        x1, x2 = xyxy[0], xyxy[2]  # 取bbox的左右x坐标
        # 打印JSON并强制刷新缓冲区,确保Node.js能实时接收
        print(json.dumps({"left": float(x1), "right": float(x2)}), flush=True)

然后Node.js改为监听stdout:

yoloProcess.stdout.on("data", (data) => {
  const lines = data.toString().split("\n").filter(line => line.trim());
  for (const line of lines) {
    try {
      const coords = JSON.parse(line);
      latestCoords = coords;
    } catch (e) {
      // 跳过无效JSON行
      continue;
    }
  }
  // 后续处理逻辑同方案1
});

3. 修复坐标比较逻辑

移除固定索引i,直接通过数组长度获取最后两个元素的差值,彻底避免索引越界问题:

// 替换原有的差值判断逻辑
if (pos.length >= 2) {
  const diff = pos[pos.length - 1] - pos[pos.length - 2];
  // 后续移动判断逻辑不变
}

内容的提问来源于stack exchange,提问作者chi peitzu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 23:06:21