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

如何将YOLOv4特征向量转换为边界框?TensorRT C++实现疑问

从TensorRT输出解析YOLOv4边界框的步骤

先明确你的输出结构:18个通道对应3个锚框,每个锚框包含[tx, ty, tw, th, conf, class_prob](4个坐标偏移值+1个置信度+1个类别概率,因为你做的是人像检测,类别数为1)。

1. 遍历三个尺度的输出

三个尺度(52×52、26×26、13×13)分别对应小、中、大目标的检测,需要逐个处理:

  • 对每个尺度的网格点(i,j)(i为行索引,j为列索引),遍历3组通道(0-5、6-11、12-17,每组对应一个锚框)
  • 取出每组通道的6个值:tx, ty, tw, th, conf, cls_prob

2. 计算图像绝对坐标

YOLO的输出是基于网格的偏移量,需要转换为图像的真实坐标:

  • 先匹配对应尺度的预定义锚框(YOLOv4针对这三个尺度的标准锚框为:10,13 16,30 33,23;30,61 62,45 59,119;116,90 156,198 373,326,必须和训练模型时用的锚框完全一致)
  • 计算网格内的相对中心坐标:cx = j + sigmoid(tx),cy = i + sigmoid(ty)(sigmoid将偏移量映射到0-1范围,对应网格内的相对位置)
  • 计算框的真实宽高:bw = anchor_w * exp(tw),bh = anchor_h * exp(th)(exp还原宽高的缩放比例)
  • 转换为图像绝对坐标(以YOLOv4常用的416×416输入尺寸为例):
    • x1 = (cx - bw/2) * 416
    • y1 = (cy - bh/2) * 416
    • x2 = (cx + bw/2) * 416
    • y2 = (cy + bh/2) * 416
      若预处理时缩放的图像尺寸不是416×416,替换对应数值即可;最后需将坐标映射回原始图像尺寸。

3. 过滤低置信度框

  • 计算框的综合得分:score = sigmoid(conf) * sigmoid(cls_prob)(原始输出为logit值,需用sigmoid转换为0-1的概率)
  • 设置置信度阈值(比如0.5),过滤掉得分低于阈值的框

4. 非极大值抑制(NMS)

同一个目标会被多个框重复检测,用NMS去重:

  • 将所有保留的框按得分降序排序
  • 遍历每个框,移除与它交并比(IOU)大于阈值(比如0.5)的其他框

C++代码示例片段

// 假设已获取三个尺度的输出数据,存放在float* out1, out2, out3中
// 定义对应三个尺度的锚框
float anchors[3][6] = {
    {10.0f,13.0f, 16.0f,30.0f, 33.0f,23.0f},   // 52x52尺度
    {30.0f,61.0f, 62.0f,45.0f, 59.0f,119.0f},  // 26x26尺度
    {116.0f,90.0f, 156.0f,198.0f, 373.0f,326.0f} // 13x13尺度
};

// 处理52x52尺度输出
int grid_size = 52;
float* output = out1;
for(int i = 0; i < grid_size; i++){
    for(int j = 0; j < grid_size; j++){
        for(int anchor_idx = 0; anchor_idx < 3; anchor_idx++){
            int channel_base = anchor_idx * 6;
            float tx = output[(i*grid_size + j)*18 + channel_base + 0];
            float ty = output[(i*grid_size + j)*18 + channel_base + 1];
            float tw = output[(i*grid_size + j)*18 + channel_base + 2];
            float th = output[(i*grid_size + j)*18 + channel_base + 3];
            float conf = output[(i*grid_size + j)*18 + channel_base + 4];
            float cls_prob = output[(i*grid_size + j)*18 + channel_base + 5];

            // 实现sigmoid函数
            auto sigmoid = [](float x){ return 1.0f / (1.0f + exp(-x)); };
            float cx = j + sigmoid(tx);
            float cy = i + sigmoid(ty);
            float bw = anchors[0][anchor_idx*2] * exp(tw);
            float bh = anchors[0][anchor_idx*2+1] * exp(th);

            // 转换为416x416图像的绝对坐标
            float x1 = (cx - bw/2.0f) * 416.0f;
            float y1 = (cy - bh/2.0f) * 416.0f;
            float x2 = (cx + bw/2.0f) * 416.0f;
            float y2 = (cy + bh/2.0f) * 416.0f;

            // 计算得分并过滤
            float score = sigmoid(conf) * sigmoid(cls_prob);
            if(score > 0.5){
                // 保存框信息:x1, y1, x2, y2, score
                // ...
            }
        }
    }
}

// 同理处理26x26和13x13尺度的输出,注意对应anchors的索引(anchors[1]和anchors[2])
// 最后对所有保存的框执行NMS

注意事项

  • 锚框必须和训练YOLOv4模型时使用的完全一致,否则坐标计算会出现偏差
  • 若输入图像尺寸不是416×416,需调整坐标缩放的系数
  • 可自行实现更高效的sigmoid和exp函数,替代标准库函数提升性能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 17:37:32