目标检测:cocoeval中的evaluateImg,accumulate函数解析

本文深入探讨了COCO数据集的目标检测评估指标计算,包括匹配策略、混淆矩阵的构建和计算过程。作者指出,COCO API的evaluateImg函数在特定限制下对单幅图某一类的检测结果进行评估,通过匹配gt和det框,计算IoU矩阵,考虑面积范围和最大检测框数量等因素。文章还对比了mmdet库的计算方式,指出其可能存在的问题。最后,文章介绍了cocoEval.accumulate()函数如何积累每幅图像的评估结果。

coco数据集的评价指标的计算还是比较复杂的,代码写的也比较凝炼,最近要计算目标检测的混淆矩阵,我看mmdet的计算方式比较奇怪,本着P和R等计算方法要与coco官方对齐的目的,特地写此笔记对coco官方的计算方式进行深入理解。
其他相关优秀笔记:
COCO API-深入解析cocoeval在det中的应用

coco计算不同map有很多变量:iou阈值,目标的面积范围,最大检测框数量等。
coco首先使用cocoEval.evaluate() 函数进行匹配计算,然后使用cocoEval.accumulate()函数进行结果的累加

1. cocoEval.evaluate()

这个函数前面都是一些比较好理解的准备工作,传入参数,计算每张图,每一类中,gt和det两两之间的iou矩阵,存储在self.iou这个字典中,
字典有len(imgId)*len(catId)个key。然后就是调用evaluateImg这个函数了。

        self.evalImgs = [evaluateImg(imgId, catId, areaRng, maxDet)
                 for catId in catIds
                 for areaRng in p.areaRng
                 for imgId in p.imgIds
             ]

根据这个调用方式,以及该函数的return我们可以确定 self.evalImgs是一个长度为len(catId)*len(areaRng)*len(imgId)的列表,其每个元素是一个字典,包含det和gt的匹配信息。
接下来我们再看这个关键的evaluateImg函数

    def evaluateImg(self, imgId, catId, aRng, maxDet):
        '''
        perform evaluation for single category and image
        :return: dict (single image results)
        '''

该函数是为了在特定限制下对单幅图某一类的检测结果进行评估,传入了四个参数:

  • imgId, 表示当前所处理图片的ID
  • catId,表示当前处理的类别ID
  • aRng,表示当前的面积范围,这是为了方便评估s,m,l三种尺度目标的检测效果
  • maxDet,最大检测框数量限制
  1. 函数首先在所有框中挑出imgId, catId的gt框和det框,并根据面积范围的限制设置该gt框是否应该ignore,并把满足面积范围的gt框排在前面,把score更高的det框也排在前面,还设置了该gt框的iscrowd标签,最后从self.ious中挑出imgId, catId的ious矩阵,注意这个最后的ious阵也是根据是否满足面积范围排序了
    self.ious是有n*c个key的字典,n代表图片总数,c代表数据的类别数,每个key所对应value是一个二维矩阵,每一列代表某个gt框与所有det框的交并比。这个字典是之前已经计算好的。该部分代码如下:
        p = self.params
        if p.useCats:
            gt = self._gts[imgId,catId]
            dt = self._dts[imgId,catId]
        else:
            gt = [_ for cId in p.catIds for _ in self._gts[imgId,cId]]
            dt = [_ for cId in p.catIds for _ in self._dts[imgId,cId]]
        if len(gt) == 0 and len(dt) ==0:
            return None

        for g in gt:
            if g['ignore'] or (g['area']<aRng[0] or g['area']>aRng[1]):
                g['_ignore'] = 1
            else:
                g['_ignore'] = 0

        # sort dt highest score first, sort gt ignore last
        gtind = np.<
`std::accumulate` 是 C++ 标准库 `<numeric>` 中的一个函数,用于**对一个范围内的元素进行累加或累积操作**。 --- ### 📌 函数原型(简化版): ```cpp #include <numeric> // 版本1:使用默认的加法操作 template<class InputIt, class T> T accumulate(InputIt first, InputIt last, T init); // 版本2:使用自定义的二元操作函数 template<class InputIt, class T, class BinaryOperation> T accumulate(InputIt first, InputIt last, T init, BinaryOperation op); ``` --- ### 🧠 功能说明: - **作用**:从起始值 `init` 开始,依次对 `[first, last)` 范围内的每个元素进行累积操作。 - **默认操作**:累加(即 `init + *first + *(first+1) + ...`) - **可自定义操作**:比如乘法、逻辑运算、字符串拼接等 --- ### ✅ 示例代码: #### 示例1:基本的累加操作 ```cpp #include <iostream> #include <vector> #include <numeric> int main() { std::vector<int> v = {1, 2, 3, 4, 5}; int sum = std::accumulate(v.begin(), v.end(), 0); std::cout << "Sum: " << sum << std::endl; // 输出 Sum: 15 } ``` #### 示例2:使用乘法代替加法 ```cpp #include <functional> // std::multiplies int product = std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>()); std::cout << "Product: " << product << std::endl; // 输出 1*2*3*4*5 = 120 ``` #### 示例3:字符串拼接 ```cpp #include <string> #include <numeric> #include <vector> std::vector<std::string> words = {"Hello", "world", "C++", "is", "great"}; std::string sentence = std::accumulate(words.begin(), words.end(), std::string(), [](const std::string& a, const std::string& b) { return a.empty() ? b : a + " " + b; }); std::cout << sentence << std::endl; // 输出:Hello world C++ is great ``` --- ### 📝 注意事项: - `std::accumulate` 不会检查溢出。 - 初始值 `init` 的类型必须与操作结果兼容。 - 第二个版本允许传入任意的二元函数函数对象、lambda、函数指针等)。 --- ### 🔁 与 `std::reduce` 的区别(C++17 起): - `std::reduce` 支持并行执行,但要求操作满足结合律和交换律; - `std::accumulate` 顺序执行,适用于所有操作。 --- ### ✅ 总结: > `std::accumulate` 是 C++ 中用于对一个容器范围内的元素进行**累积操作**的通用算法,默认是**求和**,也可以自定义为乘法、拼接等操作。 --- ###
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值