功能性模块:(7)检测性能评估模块(precision,recall等)_功能模块 评价量-程序员宅基地

技术标签: 算法  python  深度学习  pytorch  神经网络  功能性模块  

功能性模块:(7)检测性能评估模块

一、模块介绍

其实每个算法的好坏都是有对应的评估标准的,如果你和老板说检测算法好或者不好,哈哈哈,那必然就是悲剧了。好或者不好是一个定性的说法,对于实际算法来说,到底怎么样算法算好?怎么样算法算不好?这些应该是有个定量的标准。对于检测来说,可能最常用的几个评价指标就是precision(查准率,就是你检测出来的目标有多少是真的目标),recall(查全率,就是实际的目标你的算法能检测出来多少),还有ap,map等。本篇博客其实就是让小伙伴们对自己的检测模型心里有一个底,换句话说这个模型你训练出来到底咋样?

二、代码实现

import numpy as np
import os

def voc_ap(rec, prec, use_07_metric=False):
    """Compute VOC AP given precision and recall. If use_07_metric is true, uses
    the VOC 07 11-point method (default:False).
    """
    if use_07_metric:
        # 11 point metric
        ap = 0.
        for t in np.arange(0., 1.1, 0.1):
            if np.sum(rec >= t) == 0:
                p = 0
            else:
                p = np.max(prec[rec >= t])
            ap = ap + p / 11.
    else:
        # correct AP calculation
        # first append sentinel values at the end
        mrec = np.concatenate(([0.], rec, [1.]))
        mpre = np.concatenate(([0.], prec, [0.]))
        # compute the precision envelope
        for i in range(mpre.size - 1, 0, -1):
            mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])
        # to calculate area under PR curve, look for points
        # where X axis (recall) changes value
        i = np.where(mrec[1:] != mrec[:-1])[0]
        # and sum (\Delta recall) * prec
        ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
    return ap


def ComputeMAP(gt_root, predict_root, OVTHRESH=0.5):
    """

    :param gt_root: 生成gt文件的根目录
    :param predict_root: 算法跑出的根目录
    :param overthresh: 设置的阈值
    :return:
    """
    # 获取所有的文件
    files_gt = os.listdir(gt_root)
    files_pred = os.listdir(predict_root)
    files_gt.sort()
    # 这个变量的目的是什么?保存gt中真正的框的数量
    npos = 0
    class_recs = {
    }
    # 遍历所有gt文件
    for file_gt in files_gt:
        img_name = os.path.splitext(os.path.basename(file_gt))[0]
        file_gt = os.path.join(gt_root, os.path.basename(file_gt))
        print("*" * 80)
        print("img name is: ", img_name)
        print("gt file is: ", file_gt)
        # 处理gt文件
        with open(file_gt, 'r') as f:
            lines = f.readlines()
        splitlines = [x.strip().split(' ') for x in lines]
        bbox = np.array([[float(z) for z in x[:]] for x in splitlines])
        print("bbox is: \n", bbox)
        det = [False] * len(bbox)
        npos = npos + len(bbox)
        class_recs[img_name] = {
    'bbox': bbox, 'det': det}
    print("*" * 80)
    print("Total npos is: ", npos)

    # 遍历所有的检测结果
    img_ids = []
    confidence = []
    BB = []
    for file_pred in files_pred:
        img_name = os.path.splitext(os.path.basename(file_pred))[0]
        file_pred = os.path.join(pred_root, os.path.basename(file_pred))
        print("*" * 80)
        print("img_name is: ", img_name)
        print("pred file is: ", file_pred)
        with open(file_pred, 'r') as f:
            lines = f.readlines()
        splitlines = [x.strip().split(" ") for x in lines]
        confidence_p = [float(x[0]) for x in splitlines]
        bbox_p = [[float(z) for z in x[1:]] for x in splitlines]
        # 根据confidence_p的长度,复制对应的img_name的str,生成对应长度的list
        # ['20160220082030T28_H', '20160220082030T28_H', '20160220082030T28_H', '20160220082030T28_H']
        img_ids.extend([img_name] * len(confidence_p))
        confidence.extend(confidence_p)
        BB.extend(bbox_p)
        print(img_ids)
        print(confidence)
        print(BB)

    confidence = np.array(confidence)
    BB = np.array(BB)
    print("*" * 80)
    print("All files loaded!")

    # 按照confidence的降序进行排列
    sorted_idx = np.argsort(-confidence)
    print("sorted idx is: ", sorted_idx)
    BB = BB[sorted_idx, :]
    img_ids = [img_ids[x] for x in sorted_idx]

    # 计算对应的TPs 和 FPs
    nd = len(img_ids)
    tp = np.zeros(nd)
    fp = np.zeros(nd)
    wrong_count = 0
    for d in range(nd):
        print("We are now test: ", img_ids[d])
        # 取出对应图像的gt
        R = class_recs[img_ids[d]]
        # 检测的结果
        bb = BB[d, :].astype(float)
        # 假设重叠面积初始为-inf
        ovmax = -np.inf
        BBGT = R['bbox'].astype(float)
        print("bb: \n ", bb)
        print("BBGT: \n", BBGT)
        print("BBGT size is: ", BBGT.size)

        if BBGT.size > 0:
            # 计算覆盖的部分
            ixmin = np.maximum(BBGT[:, 0], bb[0])
            iymin = np.maximum(BBGT[:, 1], bb[1])
            ixmax = np.minimum(BBGT[:, 2], bb[2])
            iymax = np.minimum(BBGT[:, 3], bb[3])

            iw = np.maximum(ixmax - ixmin + 1., 0.)
            ih = np.maximum(iymax - iymin + 1., 0.)
            # 计算交叉的面积
            inters = iw * ih

            # 计算iou吧
            uni = ((bb[2] - bb[0] + 1.) * (bb[3] - bb[1] + 1.)
                   + (BBGT[:, 2] - BBGT[:, 0] + 1.0) * (BBGT[:, 3] - BBGT[:, 1] + 1.0)
                   - inters)

            overlaps = inters / uni
            ovmax = np.max(overlaps)
            jmax = np.argmax(overlaps)
            print("overlaps is: ", overlaps)
            print("ovmax is: ", ovmax)
            print("jmax is: ", jmax)

        if ovmax > OVTHRESH:
            # 如果检测的这个标记还没有激活,默认是False
            if not R['det'][jmax]:
                tp[d] = 1.
                R['det'][jmax] = 1
            else:
                fp[d] = 1.
                wrong_count += 1
        else:
            fp[d] = 1.
            wrong_count += 1
    np.set_printoptions(threshold=np.inf)
    # 计算 precision 和 recall
    fp = np.cumsum(fp)
    tp = np.cumsum(tp)
    print("fp is: ", fp)
    print("tp is: ", tp)
    # 召回率(查全率)
    rec = tp / float(npos)
    # 精确率(查准率)
    prec = tp / np.maximum(tp + fp, np.finfo(np.float).eps)

    ap = voc_ap(rec, prec, False)
    print("ap is: ", ap)
    print("*" * 80)
    print("RESULTS: \n")
    print("Total %d images, %d objects" % (len(files_gt), npos))
    print("Detected Correct: %d, Wrong: %d, Miss: %d under IOU: %f"
          % (nd - wrong_count, wrong_count, npos - (nd - wrong_count), OVTHRESH))
    print("Accuracy %f, Recall %f, Average Precision %f"
          % (float(nd - wrong_count) / (nd), float(nd - wrong_count) / (npos), ap))

    # 记录漏检的文件
    f = open('./lost.txt', 'w')
    for k, v in class_recs.items():
        if False in v['det']:
            f.write(str(k) + '.jpg' + '\n')
    f.close()


if __name__ == "__main__":
    gt_root = './mini_test/gt/'
    pred_root = './mini_test/res/'
    ComputeMAP(gt_root, pred_root)

LZ就不详细讲代码了,注释已经很详细了,主要是你的gt应该是什么样子的呢?

  • 命名标准:img_name.txt
  • gt格式:
# x1 y1 x2 y2
965 209 1040 329 
  • res格式:
# score x1 y1 x2 y2
0.9999481 962 222 1043 331
0.9999091 635 251 747 412
0.9783503 1795 340 1836 402
0.57386667 1730 305 1748 337

这个是结果展示,代码中LZ为了清晰加了非常多的打印,谁让云存储不稳定呢,动不动图片就被损坏了,哭唧唧。。。

在这里插入图片描述
ps:最近疫情反弹的厉害,谁能想到新冠肺炎居然坚持了一年,国外疫情也是指数性增长,这算是人类的灾难,也许多年后在看现在,又会有不一样的体会。珍惜当下,爱惜生命!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Felaim/article/details/112347579

智能推荐

分布式光纤传感器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告_预计2026年中国分布式传感器市场规模有多大-程序员宅基地

文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大

07_08 常用组合逻辑电路结构——为IC设计的延时估计铺垫_基4布斯算法代码-程序员宅基地

文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码

OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版

关于美国计算机奥赛USACO,你想知道的都在这_usaco可以多次提交吗-程序员宅基地

文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗

MySQL存储过程和自定义函数_mysql自定义函数和存储过程-程序员宅基地

文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程

半导体基础知识与PN结_本征半导体电流为0-程序员宅基地

文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0

随便推点

【Unity3d Shader】水面和岩浆效果_unity 岩浆shader-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader

广义线性模型——Logistic回归模型(1)_广义线性回归模型-程序员宅基地

文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型

HTML+CSS大作业 环境网页设计与实现(垃圾分类) web前端开发技术 web课程设计 网页规划与设计_垃圾分类网页设计目标怎么写-程序员宅基地

文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁_.net dll 全局目录-程序员宅基地

文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录

BRIEF特征点描述算法_breif description calculation 特征点-程序员宅基地

文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点

房屋租赁管理系统的设计和实现,SpringBoot计算机毕业设计论文_基于spring boot的房屋租赁系统论文-程序员宅基地

文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文