23

我正在从我的图像检测器算法中收集结果。所以基本上我所做的是,从一组图像(大小为 320 x 480)中,我将通过它运行一个 64x128 的滑动窗口,并且在一些预定义的比例下。

我明白那个:

  • 真阳性 = 当我检测到的窗口与地面实况(带注释的边界框)重叠(在定义的交叉点大小/质心内)
  • 误报 = 当算法给我正窗口时,这些窗口超出了事实。
  • False Negatives = 当我没有给出正面窗口时,而基本事实注释表明有一个对象。

但是真阴性呢?这些真正的否定是我的分类器给我否定结果的所有窗口吗?这听起来很奇怪,因为我一次将一个小窗口 (64x128) 滑动 4 个像素,并且我在检测中使用了大约 8 种不同的比例。如果我这样做,那么每张图像都会有很多真正的底片。

或者我是否准备了一组纯负图像(根本没有物体/人),我只是滑过,如果每个图像中都有一个或多个正检测,我会将其视为假负,反之亦然反之?

这是一个示例图像(绿色矩形作为基本事实)

示例图像,不是真实结果

4

6 回答 6

8

我一直看到以下四个术语:

  • 假阴性;结果应该是积极的,但却是消极的。
  • 假阳性; 结果应该是负面的,但是是正面的。
  • 真阳性;结果应该是积极的并且是积极的。
  • 真阴性;结果应该是负面的并且是负面的。

就您而言,如果我理解正确,您正在尝试检测图像中是否有物体。因此,假阴性意味着有一个对象(结果应该是肯定的)但算法没有检测到它(因此返回否定)。真正的否定只是算法正确地说明它检查的区域包含对象。

您可以选择忽略负值,但这些可用于进一步训练您的算法(例如;使用查找两者的算法,而不是将所有无法识别的内容设置为 false)。

于 2013-04-29T07:56:43.710 回答
2

不是 fn、fp 或 tp 的所有可能的矩形都是 tn。

因此,真阴性 (tn) 的数量是巨大的,但也是详尽无遗的。

背景:通常,在对象检测中,所有包含 tn 的度量都会被忽略,因为会有很多 tn,这使得度量很难使用。

于 2020-02-01T15:27:01.197 回答
0

True Negatives :这是一种背景预测,ground truth 没有这些位置的框,也不存在于预测中。

假阴性:地面实况有框,但预测在该位置不包含任何框。

于 2020-02-04T17:39:06.990 回答
0

通常,在对象检测任务中,我们不寻找真阴性 (TN) 情况,因为算法告诉我们,我们喜欢检测对象(不是非对象候选者);相反,在分类任务中,我们的目标是决定将每个实例视为负面还是正面。因此,我们自然会在分类任务中出现真阴性 (TN) 案例。此外,对于目标检测任务,还有更好、更兼容的措施。您可以参考平均平均精度(mAP)来评估您的对象检测算法。请注意,mAP 与简单的精度平均不同。您可以在以下网址找到有关此主题的更多信息: https ://medium.com/@jonathan_hui/map-mean-average-precision-for-object-detection-45c121a31173

于 2020-03-30T06:40:34.580 回答
-1

AFAIK,真正的否定将是一个对象存在于图像中但没有在地面实况注释或模型预测中被标记的场景。

通常二维对象检测系统仅使用两个数据,即地面实况注释和模型预测。然而,为了找到真正的否定案例,我们需要寻找一个包含关于图像中存在的所有类实例的信息(不仅仅是那些特定于我们的模型)的基本事实注释的超集。

例如拍摄给定的图像;如果我们有兴趣为自动驾驶目的进行对象检测,我们可以考虑以下两个基本事实注释:

超级集 GT 注释

  • 汽车(车辆)
  • 动物
  • 房子窗口
  • 汉堡(可能扔在路上)

自动驾驶 GT 注释

  • 汽车(车辆)
  • 动物

使用上述两个基本事实注释,可以计算汉堡和窗口的真负值。但是,我怀疑是否可以在没有超集注释的情况下计算 True Negatives。

于 2019-04-05T06:11:51.903 回答
-1

这里有一个很好的解释。F1 分数在 wiki 中进行了解释,有助于衡量成功。

在此处输入图像描述

我试图编写一个计算 F1 分数的函数:

    /// <param name="realClasses">Class names that exists on the image. A class name may exists more than once.</param>
    /// <param name="foundClasses">Predicted class names. A class name may exists more than once.</param>
    private static void findPosNeg(List<string> realClasses, List<string> foundClasses, out int truePositive, out int falsePositive, out int falseNegative)
    {            
        Dictionary<string, int> dicReal = new Dictionary<string, int>(StringComparer.InvariantCultureIgnoreCase);
        Dictionary<string, int> dicFound = new Dictionary<string, int>(StringComparer.InvariantCultureIgnoreCase);
        #region fill dictionaries
        foreach (string className in realClasses)
        {
            if (!dicReal.ContainsKey(className))
                dicReal[className] = 1;
            else
                dicReal[className]++;
        }
        foreach (string className in foundClasses)
        {
            if (!dicFound.ContainsKey(className))
                dicFound[className] = 1;
            else
                dicFound[className]++;
        }
        #endregion

        truePositive = 0;
        falsePositive = 0;
        falseNegative = 0;
        foreach (string className in dicFound.Keys)
        {
            if (!dicReal.ContainsKey(className))
                falsePositive += dicFound[className];
            else
            {
                int found = dicFound[className];
                int real = dicReal[className];
                truePositive += Math.Min(found, real);
                if (real > found)
                    falseNegative += real - found;
                else if (found > real)
                    falsePositive += found - real;
            }
        }
        foreach (string className in dicReal.Keys)
            if (!dicFound.ContainsKey(className))
                falseNegative += dicReal[className];

    }
    /// <summary>
    /// Calculates F1Score ref:https://en.wikipedia.org/wiki/Precision_and_recall
    /// </summary>
    private static double calc_F1Score(int truePositive, int falsePositive, int falseNegative, out double precision, out double recall)
    {
        precision = (double)truePositive / ((double)truePositive + (double)falsePositive);
        recall = (double)truePositive / ((double)truePositive + (double)falseNegative);
        double div = (precision + recall);
        return (div != 0d) ? 2d * precision * recall / div : 0d;
    }
于 2017-02-16T07:02:34.380 回答