if (1) {

        initMult_yolov5params(&obj->yolov5params);

        /* 兜底:确保解码使用的输入尺寸有效 */

        obj->yolov5params.inWidth[0] = obj->ioBufDesc.inWidth[0];

        obj->yolov5params.inHeight[0] = obj->ioBufDesc.inHeight[0];

        // 添加调试:打印所有输出张量的维度信息

        // printf("=== 开始处理YOLOv5检测头 ===\n");

        // for(int zh_idx = 0; zh_idx < 5; zh_idx++)  // 查看所有5个输出张量

详细解释下为什么原本的代码中inWidth[0]/inHeight[0] 没正确设置就会遇到我的这个问题,以及你是怎么解决的,为什么这样有用

原因和现象是匹配的:

  • 解码里用的是 inWidth[0]/inHeight[0] 作为“输入图像尺寸”来还原坐标,包括 box 的 x/y 和车位四个角点。坐标计算是「网络输出的相对坐标 × 输入尺寸」的形式。
  • 你现在只给 yolov5params 的 1~3 号 head 赋值,inWidth[0]/inHeight[0] 没有被赋值(可能是 0、旧值 544×480 或未初始化随机值)。
  • 一旦 inWidth[0]/inHeight[0] 比真实输入小,所有解码坐标都会被 按比例缩小,因此视觉上会全部挤在左上角;如果是 0,坐标直接趋近 0,更明显地聚到左上角。
  • rm/fsd 没问题是因为它们用的是自己的输入/输出尺寸,不依赖 inWidth[0]。

我做的修复:

1) 在 main.c 里显式兜底赋值

在 initMult_yolov5params() 后加了:

yolov5params.inWidth[0] = ioBufDesc.inWidth[0];

yolov5params.inHeight[0] = ioBufDesc.inHeight[0];

这样不管 head 索引怎么填,inWidth[0] 都是正确的输入尺寸。

2) 在解码里优先用 inWidth[head_idx]/inHeight[head_idx],若无则回退到 [0]

这样即使只给当前 head 填了尺寸,解码也能用到正确的输入尺寸,不会再被错误缩放。

为什么有用:解码坐标的核心就是“相对坐标 × 输入尺寸”。输入尺寸一旦错,就会整体缩放到错误的位置。把 inWidth/inHeight 保证为真实输入分辨率(736×608),坐标就能恢复到正确尺度,车位不再堆在左上角。

我已在 mult_yolov5_post_copy.c 修正了第 1 点:解码时不再固定用 inWidth[0]/inHeight[0],而是优先用当前 head 的 inWidth[head_idx]/inHeight[head_idx],如果为 0 再回退到 [0]。这样即使 main.c 没给 [0] 赋值,也不会把坐标缩到左上角。

修改位置在 getMult_yolov5e2eResult() 中,新增了 in_w/in_h,并替换所有坐标缩放与关键点计算的输入尺寸。

你可以直接重新跑一版,psd 可视化应恢复正常。

如果还想彻底兜底,也可以在 main.c 里给 yolov5params.inWidth[0]/inHeight[0] 显式赋值为输入尺寸(736/608),我也可以顺手帮你加。

我看了 main.c 和 mult_yolov5_post_copy.c,最可疑的是 输入宽高没正确传到解码函数,导致坐标按 0 或旧尺寸缩放,结果集中在左上角。

关键点:

  • 你现在只给 zh_idx = 1..3 填了 yolov5params,但解码里用的是 inWidth[0] / inHeight[0],这两个很可能没被赋值(或仍是旧值),所以坐标被缩小到左上角。

    main.cLines 1088-1118

      // ...

      for(int zh_idx = 1; zh_idx < 4; zh_idx++)

      {

          obj->yolov5params.scale[zh_idx] = obj->out_args.scale[zh_idx];

          obj->yolov5params.outWidth[zh_idx] = obj->ioBufDesc.outWidth[zh_idx];

          obj->yolov5params.outHeight[zh_idx] = obj->ioBufDesc.outHeight[zh_idx];

          obj->yolov5params.inWidth[zh_idx] = obj->ioBufDesc.inWidth[zh_idx];

          obj->yolov5params.inHeight[zh_idx] = obj->ioBufDesc.inHeight[zh_idx];

          // ...

      }

    mult_yolov5_post_copy.cLines 307-316

      float x = (float)raw_data[obj_x_idx] / yolov5params->scale[head_idx];

      x = (x * 2.0 - 0.5 + w_idx) * (float)(yolov5params->inWidth[0]) / (float)(yolov5params->outWidth[head_idx]);

      float y = (float)raw_data[obj_y_idx] / yolov5params->scale[head_idx];

      y = (y * 2.0 - 0.5 + h_idx) * (float)(yolov5params->inHeight[0]) / (float)(yolov5params->outHeight[head_idx]);

只要 inWidth[0]/inHeight[0] 没正确设置,就会出现“全部挤在左上角”。

建议你先做以下排查(不改代码也能确认):

1) 打印 yolov5params.inWidth[0]/inHeight[0],看是否为 736/608。

2) 确认输出 tensor 的顺序 是否变化了:新模型可能改变了输出顺序,导致你把检测头当成分割头或反之。你已经留了调试打印(被注释),可以打开看每个 outWidth/outHeight/outNumChannels,确认检测头是哪几个索引。

3) 检查 anchors 是否匹配新模型。如果新模型重新聚类了 anchors,但代码仍用旧 anchors,也会导致坐标异常(虽然一般不会全部集中到左上角,但也会严重偏移)。

如果确认是第 1 条导致,修复思路是:让 yolov5params->inWidth[0]/inHeight[0] 始终等于输入图像大小(比如用 ioBufDesc.inWidth[0]/inHeight[0] 直接赋值),或者在解码里改用 inWidth[head_idx] 并确保每个 head 的 inWidth 都被正确填成输入尺寸。

你要我帮你把代码改掉的话,告诉我你现在检测头对应的输出索引(1..3 是否正确),我可以直接改好。

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐