【yolov5小技巧(1)】---可视化并统计目标检测中的TP、FP、FN

在这里插入图片描述


文章目录

  • 🚀🚀🚀前言
  • 一、1️⃣相关名词解释
  • 二、2️⃣论文中案例
  • 三、3️⃣新建相关文件夹
  • 四、4️⃣detect.py推理
  • 五、5️⃣开始可视化
  • 六、6️⃣可视化结果分析


在这里插入图片描述

👀🎉📜系列文章目录

嘻嘻 暂时还没有~~~~

🚀🚀🚀前言

在目标检测过程中,看F1置信度分数,依旧map@0.5或者AP、recall这些评估指标虽然可以很简单粗暴的看出模型训练的一个性能,但是缺无法直观的看出究竟哪一点提升了,然而这些品估指标都是通过TP、FP、FN进行计算的,如果能够直观的看见哪些目标是TP、FP、FN,那么在实验过程中就能知道自己改进的网络对哪些目标是有提升效果的。

🚀所以这个文章将手把手带你如何可视化自己数据集中的TP、FP、FN,帮助你更直观的感受自己网络究竟在哪些方面有提升 ,所使用的数据集图片是钢轨表面疵点。


一、1️⃣相关名词解释

在目标检测中,TP(真正例)、FP(假正例)和FN(假负例) 的定义稍微复杂一些,因为目标检测不仅要考虑分类是否正确,还要考虑定位是否准确。以下是这些概念的解释和示例:

1.真正例(True Positives,TP):指检测到的目标与实际目标之间的匹配。这意味着检测到的目标在位置和类别上都与实际目标匹配
2.假正例(False Positives,FP):指模型错误地将负例(非目标)样本预测为正例(目标)。在目标检测中,FP 是指检测到的目标与实际无目标区域之间的匹配。
3.假负例(False Negatives,FN):指模型未能检测到实际存在的目标。在目标检测中,FN 是指未检测到的实际目标。

举个例子:
假设我们有一张图像,其中包含一只猫和一只狗。我们的目标检测模型会尝试检测图像中的动物,并且根据预测结果计算 TP、FP 和 FN。

  • TP(真正例):如果模型正确地检测到了图像中的猫和狗,并且对它们进行了正确的分类和定位,那么这就是一个 TP。
  • FP(假正例):如果模型在图像中的某些区域错误地检测到了动物(例如,将一只猫误认为狗),或者在图像中检测到了不存在的动物,那么这就是一个 FP。
  • FN(假负例):如果模型未能检测到图像中的某些动物(例如,漏掉了图像中的狗),那么这就是一个 FN。

例如,如果我们的模型在一张图像中正确检测到了一只猫和一只狗,并且没有检测到不存在的动物,那么:
TP = 2(图像中的猫狗都被检测出来,并且类别位置正确
FP = 0(模型未将不存在的动物检测为目标)
FN = 0(模型未漏掉任何实际存在的目标)

二、2️⃣论文中案例

🔥🔥🔥下面这幅图是出之NWD这篇论文,基于 IoU 的检测器(第一行)和基于 NWD 的检测器(第二行)的一些可视化结果,使用NWD替换IOU之后对于小目标的检测精度提升了很多。(感兴趣的可以去我的目标检测论文专栏阅读)。其中绿色、蓝色和红色框分别表示真阳性(TP)假阳性(FP)假阴性(FN)预测。其中TP表示正确预测的结果,FP是错检的结果,FN是漏检的结果;下面的实验可视化颜色也是遵循这种颜色分配!!!
在这里插入图片描述

三、3️⃣新建相关文件夹

这里需要建立三个文件,可以选择在你的yolov5项目文件中新建如下文件夹(千万不要把文件夹命名错了)。文件夹目录结构如下:
在这里插入图片描述

  • image文件:存储的是等下我们需要推理的照片
  • label文件夹:存储的是image文件夹里面所有图片的标注类别
  • predict文件夹:等下存储我们推理detect.py推理image图片后的标准信息。
  • tricks_1.py文件:我们的TP、FP、FN可视化代码,代码如下
import os, cv2, tqdm, shutil
import numpy as npdef xywh2xyxy(box):box[:, 0] = box[:, 0] - box[:, 2] / 2box[:, 1] = box[:, 1] - box[:, 3] / 2box[:, 2] = box[:, 0] + box[:, 2]box[:, 3] = box[:, 1] + box[:, 3]return boxdef iou(box1, box2):x11, y11, x12, y12 = np.split(box1, 4, axis=1)x21, y21, x22, y22 = np.split(box2, 4, axis=1)xa = np.maximum(x11, np.transpose(x21))xb = np.minimum(x12, np.transpose(x22))ya = np.maximum(y11, np.transpose(y21))yb = np.minimum(y12, np.transpose(y22))area_inter = np.maximum(0, (xb - xa + 1)) * np.maximum(0, (yb - ya + 1))area_1 = (x12 - x11 + 1) * (y12 - y11 + 1)area_2 = (x22 - x21 + 1) * (y22 - y21 + 1)area_union = area_1 + np.transpose(area_2) - area_interiou = area_inter / area_unionreturn ioudef draw_box(img, box, color):cv2.rectangle(img, (int(box[0]), int(box[1])), (int(box[2]), int(box[3])), color, thickness=2)return imgif __name__ == '__main__':postfix = 'jpg'img_path = 'image'label_path = 'label'predict_path = 'predict'save_path = 'vis'classes = ['train', 'diningtable', 'person', 'bus', 'pottedplant', 'chair', 'cat', 'tvmonitor', 'motorbike', 'sofa', 'cow', 'bottle', 'aeroplane', 'dog', 'horse', 'car', 'boat', 'sheep', 'bicycle', 'bird']detect_color, missing_color, error_color  = (0, 255, 0), (0, 0, 255), (255, 0, 0)iou_threshold = 0.45if os.path.exists(save_path):shutil.rmtree(save_path)os.makedirs(save_path, exist_ok=True)all_right_num, all_missing_num, all_error_num = 0, 0, 0with open('result.txt', 'w') as f_w:for path in tqdm.tqdm(os.listdir(label_path)):image = cv2.imread(f'{img_path}/{path[:-4]}.{postfix}')if image is None:print(f'image:{img_path}/{path[:-4]}.{postfix} not found.', file=f_w)h, w = image.shape[:2]try:with open(f'{predict_path}/{path}') as f:pred = np.array(list(map(lambda x:np.array(x.strip().split(), dtype=np.float32), f.readlines())))pred[:, 1:5] = xywh2xyxy(pred[:, 1:5])pred[:, [1, 3]] *= wpred[:, [2, 4]] *= hpred = list(pred)except:pred = []try:with open(f'{label_path}/{path}') as f:label = np.array(list(map(lambda x:np.array(x.strip().split(), dtype=np.float32), f.readlines())))label[:, 1:] = xywh2xyxy(label[:, 1:])label[:, [1, 3]] *= wlabel[:, [2, 4]] *= hexcept:print(f'label path:{label_path}/{path} (not found or no target).', file=f_w)right_num, missing_num, error_num = 0, 0, 0label_id, pred_id = list(range(label.shape[0])), [] if len(pred) == 0 else list(range(len(pred)))for i in range(label.shape[0]):if len(pred) == 0: breakious = iou(label[i:i+1, 1:], np.array(pred)[:, 1:5])[0]ious_argsort = ious.argsort()[::-1]missing = Truefor j in ious_argsort:if ious[j] < iou_threshold: breakif label[i, 0] == pred[j][0]:image = draw_box(image, pred[j][1:5], detect_color)pred.pop(j)missing = Falseright_num += 1breakif missing:image = draw_box(image, label[i][1:5], missing_color)missing_num += 1if len(pred):for j in range(len(pred)):image = draw_box(image, pred[j][1:5], error_color)error_num += 1all_right_num, all_missing_num, all_error_num = all_right_num + right_num, all_missing_num + missing_num, all_error_num + error_numcv2.imwrite(f'{save_path}/{path[:-4]}.{postfix}', image)print(f'name:{path[:-4]} right:{right_num} missing:{missing_num} error:{error_num}', file=f_w)print(f'all_result: right:{all_right_num} missing:{all_missing_num} error:{all_error_num}', file=f_w)

📌相关代码讲解:

  • postfix:推理文件夹的图片格式
  • img_path:需要推理图片所保存的文件夹路径
  • label_path:图片标注信息存储的路径
  • predict_path:使用detect.py推理后的txt标签信息存放位置
  • save_path:可视化之后的图片存储位置
  • classes:数据集类别名称
  • detect_color, missing_color, error_color:分别表示正确识别的物体框颜色(绿色)、漏检的物体标注框颜色(红色)、错误识别物体的标注框颜色(蓝色)
  • iou_threshold:预测值和标准信息之间的阈值判断。注意!!!在detect.py中iou-thres', type=float, default=0.45也有个阈值0.45,这个阈值是用来做NMS极大值计算的。
    在这里插入图片描述

四、4️⃣detect.py推理

关于detect.py文件修改如下:
在这里插入图片描述
运行detect.py文件之后会在run文件夹中生成推理出来的的标签文件,其中每个推理文件都标注了预测类别、位置、以及置信度
在这里插入图片描述
在这里插入图片描述

五、5️⃣开始可视化

🔥将推理生成的labels文件夹中的txt文件全部拷贝到我们刚刚自己新建的predict文件夹当中,然后运行tricks_1.py代码,会生成一个vis文件夹,和一个result.txt文件,其中vis就是可视化结果,result.txt保存的就是每个图片物体目标right、missing、error的数量,已经所有TP、FP、FN的总和。运行代码之后的文件夹目录如下:

在这里插入图片描述

六、6️⃣可视化结果分析

🚀其中绿色是预测正确的,蓝色框表示类别预测错误的。红色表示该缺陷存在,但是却没有预测出来。
在这里插入图片描述
在这里插入图片描述


🔥🔥🔥🔥在result.txt中存储的是每张图片TP、FP、FN的数量,这里分析一下rolled-in_scale_5这个缺陷,会发现预测正确的目标是一个、漏检的是一个、错误识别成其它类别的也是一个,
在这里插入图片描述
在这里插入图片描述

我们在label文件中打开rolled-in_scale_5的标签信息,发现只标注了两个疵点,并且其中一个疵点的标注位置确实和预测出的位置不对。
在这里插入图片描述


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/791298.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows上配置Redis主从加哨兵模式实现缓存高可用

一、哨兵模式 哨兵&#xff08;sentinel&#xff09;是Redis的高可用性(High Availability)的解决方案&#xff1a;由一个或多个sentinel实例组成sentinel集群可以监视一个或多个主服务器和多个从服务器。当主服务器进入下线状态时&#xff0c;sentinel可以将该主服务器下的某…

R语言中的常用数据结构

目录 R对象的基本类型 R对象的属性 R的数据结构 向量 矩阵 数组 列表 因子 缺失值NA 数据框 R的数据结构总结 R语言可以进行探索性数据分析&#xff0c;统计推断&#xff0c;回归分析&#xff0c;机器学习&#xff0c;数据产品开发 R对象的基本类型 R语言对象有五…

拯救者Legion R9000X 2021(82HN)原装出厂Win10系统镜像ISO下载

lenovo联想拯救者笔记本R9000X 2021款原厂Windows10系统安装包&#xff0c;恢复出厂开箱状态预装OEM系统 链接&#xff1a;https://pan.baidu.com/s/1tx_ghh6k0Y9vXBz-7FEQng?pwd7mih 提取码&#xff1a;7mih 原装出厂系统自带所有驱动、出厂主题壁纸、系统属性联机支持标…

法律行业案例法模型出现,OPenAI公布与法律AI公司Harvey合作案例

Harvey与OpenAl合作&#xff0c;为法律专业人士构建了一个定制训练的案例法模型。该模型是具有复杂推理广泛领域知识以及超越单一模型调用能力的任务的AI系统&#xff0c;如起草法律文件、回答复杂诉讼场景问题以及识别数百份合同之间的重大差异。 Harvey公司由具有反垄断和证…

Git的简单入门使用

文章目录 拷贝项目的步骤创建项目的步骤提交项目或项目文件的步骤恢复项目文件的步骤 拷贝项目的步骤 找到需要用来存放项目的文件夹&#xff1b;在文件夹页面空白处右键点击&#xff0c;然后再菜单中选择“Open Git Bash here”。在Github上找到需要进行拷贝的项目&#xff0…

CVAE——生成0-9数字图像(Pytorch+mnist)

1、简介 CVAE&#xff08;Conditional Variational Autoencoder&#xff0c;条件变分自编码器&#xff09;是一种变分自编码器&#xff08;VAE&#xff09;的变体&#xff0c;用于生成有条件的数据。在传统的变分自编码器中&#xff0c;生成的数据是完全由潜在变量决定的&…

Rust---复合数据类型之枚举、数组

目录 枚举的使用Option 枚举数组的使用输出结果 枚举&#xff08;Enum&#xff09;&#xff1a;表示一个类型可以有多个不同的取值。枚举类型可以包含不同的变体&#xff08;variants&#xff09;&#xff0c;每个变体可以有不同的数据类型。 枚举的使用 enum Direction {Up,…

波士顿房价预测案例(python scikit-learn)---多元线性回归(多角度实验分析)

波士顿房价预测案例&#xff08;python scikit-learn&#xff09;—多元线性回归(多角度实验分析) 这次实验&#xff0c;我们主要从以下几个方面介绍&#xff1a; 一、相关框架介绍 二、数据集介绍 三、实验结果-优化算法对比实验&#xff0c;数据标准化对比实验&#xff0…

Head First Design Patterns -代理模式

什么是代理模式 代理模式为另一个对象提供替身或者占位符&#xff0c;以便控制客户对对象的访问&#xff0c;管理访问的方式有很多种。例如远程代理、虚拟代理、保护代理等。 远程代理&#xff1a;管理客户和远程对象之间的交互。 虚拟代理&#xff1a;控制访问实例化开销大的对…

算法基础--二分

&#x1f600;前言 二分查找是一种常见的算法技巧&#xff0c;通过不断缩小搜索范围&#xff0c;快速找到目标值的算法。在实际应用中&#xff0c;二分查找可以应用于有序数组中的查找、求上界、求下界等问题&#xff0c;具有较高的效率和广泛的应用价值。 &#x1f3e0;个人主…

动手做一个最小Agent——TinyAgent!

Datawhale干货 作者&#xff1a;宋志学&#xff0c;Datawhale成员 前 言 大家好&#xff0c;我是不要葱姜蒜。在ChatGPT横空出世&#xff0c;夺走Bert的桂冠之后&#xff0c;大模型愈发地火热&#xff0c;国内各种模型层出不穷&#xff0c;史称“百模大战”。大模型的能力是毋…

字符分类函数

字符分类函数 C语言中有⼀系列的函数是专门做字符分类的&#xff0c;也就是⼀个字符是属于什么类型的字符的。这些函数的使用都需要包含⼀个头文件是 ctype.h 这些函数的使用方法非常类似&#xff0c;我们就讲解⼀个函数的事情&#xff0c;其他的非常类似&#xff1a; int i…

图的应用解析

01&#xff0e;任何一个无向连通图的最小生成树(B )。 A.有一棵或多棵 B.只有一棵 C.一定有多棵 D.可能不存在 02.用Prim算法和Kruskal算法构造图的最小生成树&#xff0c…

内存和网卡压力测试

1.内存压力测试 1.1测试目的 内存压力测试的目的是评估开发板中的内存子系统性能和稳定性&#xff0c;以确保它能够满足特定的应用需求。开发板通常用于嵌入式系统、物联网设备、嵌入式智能家居等场景&#xff0c;这些场景对内存的要求通常比较高。 其内存压力测试的主要目的…

【深度学习】sdwebui的token_counter,update_token_counter,如何超出77个token的限制?对提示词加权的底层实现

文章目录 前言关于token_counter关于class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing)如何超出77个token的限制&#xff1f;对提示词加权的底层实现Overcoming the 77 token limit in diffusers方法1 手动拼方法2 compel 问询、帮助请看&#xff1a; 前言 …

动规训练2

一、最小路径和 1、题目解析 就是一个人从左上往做下走&#xff0c;每次只能往右或者往下&#xff0c;求他到终点时&#xff0c;路径上数字和最小&#xff0c;返回最小值 2、算法原理 a状态表示方程 小技巧&#xff1a;经验题目要求 用一个二维数组表示&#xff0c;创建一个…

Flask Python:数据库多条件查询,flask中模型关联

前言 在上一篇Flask Python:模糊查询filter和filter_by&#xff0c;数据库多条件查询中&#xff0c;已经分享了几种常用的数据库操作&#xff0c;这次就来看看模型的关联关系是怎么定义的&#xff0c;先说基础的关联哈。在分享之前&#xff0c;先分享官方文档,点击查看 从文档…

FreeRTOS中断管理以及实验

FreeRTOS中断管理以及实验 继续记录学习FreeRTOS的博客&#xff0c;参照正点原子FreeRTOS的视频。 ARM Cortex-M 使用了 8 位宽的寄存器来配置中断的优先等级&#xff0c;这个寄存器就是中断优先级配置寄存器 &#xff0c; STM32寄存器中并且这个寄存器只使用[7:4]&#xff0c…

RTX RTOS 操作实例分析之---线程(thread)

0 Preface/Foreword 1 线程&#xff08;thread&#xff09; 1.1 线程定义 1.1.1 USE_BASIC_THREADS&#xff08;宏定义&#xff09; 经过以上步骤&#xff08;makefile包含&#xff09;&#xff0c;USE_BASIC_THREADS在编译阶段被定义到相应的模块中。 1.1.2 定义线程ID变量…

安装Pillow库的方法最终解答!_Python第三方库

安装Python第三方库Pillow 我的环境&#xff1a;Window10&#xff0c;Python3.7&#xff0c;Anaconda3&#xff0c;Pycharm2023.1.3 pillow库 Pillow库是一个非常强大的图像处理库。它提供了广泛的图像处理功能&#xff0c;让我们可以轻松地读取和保存图像、创建缩略图和合并到…