功能性模块:(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

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include<stdio.h>#include<string.h>#include<stdlib.h>#include<malloc.h>#include<iostream>#include<stack>#include<queue>using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签