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

TensorFlow Lite C++中MobileNet-SSD v1模型输出解析问询

解析TensorFlow Lite MobileNet-SSD v1的C++输出

我来帮你梳理下这个问题——关于MobileNet-SSD v1模型的TFLite版本在C++里的输出解析,还有你对expit函数的疑问。

首先得明确这个模型的TFLite输出结构:

  • 第一个输出(对应results[0])是检测框的归一化坐标,格式为[y_min, x_min, y_max, x_max],数值范围在0到1之间
  • 第二个输出(results[1])是每个检测框对应各类别的原始预测值(logits),不是直接能用的置信度分数

关于expit函数的正确性

你用expit转换分数的逻辑其实是对的!因为MobileNet-SSD v1的分类分支输出的是未经过激活的logits,必须通过sigmoid函数(也就是expit,两者完全等价)转换成0-1之间的置信度,公式就是:

score = 1 / (1 + exp(-logit))

你可能觉得不对,大概率是其他细节没处理好,我给你列几个要注意的点:

关键细节要留意

  • 匹配模型的实际维度:MobileNet-SSD v1的TFLite模型,outputClasses的维度通常是[NUM_DETECTIONS, NUM_CLASSES],默认的Pascal VOC版本是20个目标类别+1个背景类,所以NUM_CLASSES应该是21,NUM_RESULTS一般是10或者20,要和你用的模型对应上
  • 跳过背景类:索引0对应的是背景类,你代码里从j=1开始遍历是对的,不用管背景类的分数
  • 过滤无效检测框:不是所有输出的框都是有效的,比如坐标超出0-1范围、宽高为负的框,要提前跳过;有些模型还会有第三个输出(results[2]),是每个框的整体置信度,可以用来快速过滤低质量框

修正后的示例代码

// 先填充好输入数据
interpreter->Invoke();

const std::vector<int>& results = interpreter->outputs();
// 检测框坐标张量:形状为[NUM_RESULTS, 4],每个元素是[y_min, x_min, y_max, x_max]
TfLiteTensor* outputLocations = interpreter->tensor(results[0]);
// 类别logits张量:形状为[NUM_RESULTS, NUM_CLASSES]
TfLiteTensor* outputClasses = interpreter->tensor(results[1]);
// 部分模型会有第三个输出,存储每个框的整体置信度:[NUM_RESULTS]
// TfLiteTensor* outputScores = interpreter->tensor(results[2]);

float* classLogits = tflite::GetTensorData<float>(outputClasses);
float* boxCoords = tflite::GetTensorData<float>(outputLocations);

// 根据你的模型调整这两个值
const int NUM_RESULTS = 10; 
const int NUM_CLASSES = 21;

for (int i = 0; i < NUM_RESULTS; ++i) {
    // 取出当前框的坐标
    float yMin = boxCoords[i * 4 + 0];
    float xMin = boxCoords[i * 4 + 1];
    float yMax = boxCoords[i * 4 + 2];
    float xMax = boxCoords[i * 4 + 3];

    // 跳过无效框
    if (xMin >= xMax || yMin >= yMax || xMin < 0 || yMin < 0 || xMax > 1 || yMax > 1) {
        continue;
    }

    // 遍历所有目标类别(跳过背景类)
    for (int j = 1; j < NUM_CLASSES; ++j) {
        float logit = classLogits[i * NUM_CLASSES + j];
        // 用sigmoid转换为置信度分数
        float score = 1.0f / (1.0f + exp(-logit));
        
        // 只保留分数高于阈值的结果(比如0.5)
        if (score > 0.5f) {
            // 这里可以处理检测结果:比如把坐标转换成图像像素值,记录类别和分数
            // 示例:xMin * imageWidth, yMin * imageHeight
        }
    }
}

额外小技巧

如果你不确定模型的输出维度,可以用这段代码打印出来确认:

// 打印outputClasses的维度信息
for (int d = 0; d < outputClasses->dims->size; ++d) {
    std::cout << "维度 " << d << ": " << outputClasses->dims->data[d] << std::endl;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:22:14