目标检测入门:3.目标检测损失函数(IOU、GIOU、GIOU)

目录

一、IOU

二、GIOU

三、DIOU

四、DIOU_Loss实战


在前面两章里面训练模型时,损失函数都是选择L1Loss(平均绝对值误差(MAE))损失函数,L1Loss损失函数公式如下:

{Loss}_{\text {MAE }}=\frac{1}{N} \sum_{n=1}^{N}|y(n)-\hat{y}(n)|

由公式可知,L1Loss损失函数是线性函数,其梯度是恒定的,即无论预测值与真实值之间的误差大小,其梯度都是常数(+1或-1)。虽然避免了梯度爆炸的问题,但在误差很小时,梯度仍然较大,不利于梯度在接近最优解时的精细调整。同时L1Loss并不直接优化我们最关心的目标——即预测框和真实框的之间的重叠程度。L1Loss通常是分别计算预测框和真实框各个坐标点之间的L1距离,这种方法假设了坐标点之间是相互独立的,没有考虑它们之间的相关性。

预测框与真实框损失

上图中的绿框代表真实框,黑框为模型的预测框,两个预测框的大小不一,与真实框之间的重叠面积也不一致,但得到的L1Loss损失值却是一样的。说明L1Loss损失不能准确反应两个目标边界框重合的程度,因此诞生了IOU损失函数。

一、IOU

论文原文:《UnitBox: An Advanced Object Detection Network》icon-default.png?t=N7T8http://arxiv.org/pdf/1608.01471

IOU(Intersection over Union)损失函数是目标检测中常用的一种损失韩式,主要用于评估预测边界框(Bounding Box)与真实框(Ground Truth Box)之间的重叠程度,并作为优化目标来指导模型训练。

IOU即交并比,适用于衡量两个边界框的之间的重叠程度的度量指标。其计算公式为:

IoU=\frac{|A\cap B|}{|A\cup B|}

即两个框的相交的面积除以两个框相并的面积。

L1Loss与IOU

如上图所示,第一个预测框与真实框的相交的面积为(25-5)*(15-5)=200,相并的面积为15*(25-5)+(35-5)*50-200=1600,最终IOU=200/1600=0.125。而第二个预测框的IOU则为0.319。相对于两个预测框计算L1损失的结果相同,可以看出IOU能直接反映出预测框与真实框之间的重叠程度。

IOU损失计算方式如下:

Iou Loss

简单代码实现如下:
 

import cv2
import numpy as npdef IOU(RecA, RecB):x1 = max(RecA[0], RecB[0])y1 = max(RecA[1], RecB[1])x2 = min(RecA[2], RecB[2])y2 = min(RecA[3], RecB[3])# 计算交集部分面积interArea = max(0, x2 - x1 + 1) * max(0, y2 - y1 + 1)# 计算预测值和真实值的面积RecA_Area = (RecA[2] - RecA[0] + 1) * (RecA[3] - RecA[1] + 1)RecB_Area = (RecB[2] - RecB[0] + 1) * (RecB[3] - RecB[1] + 1)#计算并集部分面积UnionArea=float(RecA_Area + RecB_Area - interArea)# 计算IOUiou = interArea / UnionAreareturn iouimg = np.zeros((512, 512, 3), np.uint8)
img.fill(255)RecA = [50, 50, 300, 300] #方框的左上角坐标和右上角坐标
RecB = [60, 60, 320, 320]cv2.rectangle(img, (RecA[0], RecA[1]), (RecA[2], RecA[3]), (0, 255, 0), 5)
cv2.rectangle(img, (RecB[0], RecB[1]), (RecB[2], RecB[3]), (255, 0, 0), 5)iou =IOU(RecA, RecB)
font = cv2.FONT_ITALIC#展示IOU结果
cv2.putText(img, "IOU = %.2f" % iou, (130, 190), font, 0.6, (0, 0, 0), 2)
cv2.putText(img, "IOU_Loss = %.2f" % (1-iou), (80, 350), font, 0.6, (0, 0, 0), 2)cv2.imshow("IOU",img )
cv2.waitKey()
cv2.destroyAllWindows()

IOU

最终结果如上图所示,IOU_Loss相对与L1Loss更能反映预测框与真实框之间的重叠程度。

如上图所示,IOU最大的缺点是当预测框与真实框不相交的时候,其IOU都为0,此时模型的梯度消失,导致无法进一步优化,各位可以试一下将IOU_Loss替换前两章小黄人目标检测任务中的L1_Loss,会发现模型无法收敛。

二、GIOU

原文论文:《Generalized Intersection over Union: A Metric and A Loss for Bounding Box Regression》icon-default.png?t=N7T8http://arxiv.org/pdf/1902.09630GIOU(Generalized Intersection over Union),即广义交并比,这是一种在目标检测领域中用来评估预测框与真实框之间重叠度的指标,传统IOU在两个框无重叠时无法反映他们之间的远近关系,在模型训练时会出现梯度消失的情况。为了解决这个问题,GIOU被提出。公式如下:

GIOU=IoU-\frac{|C-(A\cup B)|}{|C|}

GIOU引入了一个最小闭包区域(即能同事包含预测框与真实框的最小矩形框),如上图中的红框C,并引入了一个额外的惩罚项来反映两个框的远近程度。

代码实现如下:

import cv2
import numpy as npdef GIOU(RecA, RecB):x1 = max(RecA[0], RecB[0])y1 = max(RecA[1], RecB[1])x2 = min(RecA[2], RecB[2])y2 = min(RecA[3], RecB[3])# 计算交集部分面积interArea = max(0, x2 - x1 + 1) * max(0, y2 - y1 + 1)# 计算预测值和真实值的面积RecA_Area = (RecA[2] - RecA[0] + 1) * (RecA[3] - RecA[1] + 1)RecB_Area = (RecB[2] - RecB[0] + 1) * (RecB[3] - RecB[1] + 1)#计算并集部分面积UnionArea=float(RecA_Area + RecB_Area - interArea)# 计算IOUiou = interArea / UnionAreaC_x1 = min(RecA[0], RecB[0])C_y1 = min(RecA[1], RecB[1])C_x2 = max(RecA[2], RecB[2])C_y2 = max(RecA[3], RecB[3])#计算最小闭包矩形面积C_area = (C_x2 - C_x1) * (C_y2 - C_y1)IOU = interArea / UnionAreaGIOU = IOU - abs((C_area - UnionArea) / C_area)return GIOUimg = np.zeros((512, 512, 3), np.uint8)
img.fill(255)RecA = [50, 50, 80,80] #方框的左上角坐标和右上角坐标
RecB = [100, 160, 320, 320]cv2.rectangle(img, (RecA[0], RecA[1]), (RecA[2], RecA[3]), (0, 255, 0), 5)
cv2.rectangle(img, (RecB[0], RecB[1]), (RecB[2], RecB[3]), (255, 0, 0), 5)iou =GIOU(RecA, RecB)
font = cv2.FONT_ITALIC#展示IOU结果
cv2.putText(img, "GIOU = %.2f" % iou, (200, 450), font, 0.6, (0, 0, 0), 2)cv2.imshow("IOU",img)
cv2.waitKey()
cv2.destroyAllWindows()

GIOU在计算预测框与真实框之间的重叠程度时,即使两框之间无重叠区域,其结果也不会为0,有效的解决了模型在预测框也真实框之间无交集时出现的梯度消失问题。

GIOU缺点

当真实框内含预测框时,如上图所示,IOU和GIOU的值相同,无法反映出哪个预测框更好。

三、DIOU

论文原文:《Distance-IoU Loss: Faster and Better Learning for Bounding Box Regression》icon-default.png?t=N7T8http://arxiv.org/pdf/1911.08287

DIOU(Distance Intersection over Union)是一种改进的交并比,DIOU既考虑到了IOU的缺点,又考虑到了GIOU的缺点。DIOU也是增加了最小闭包区域(即能同事包含预测框与真实框的最小矩形框),但不再计算闭包区域与预测框真实框之间的交并比,而是计算它们之间的欧氏距离。公式如下:

IoU-\mathrm{DIoU}=\frac{\rho^2(\mathrm{A},\mathrm{B})}{\mathrm{c}^2}

其中c代表最小闭包区域矩形的对角线距离,d代表预测框中心点和真实框中心点距离。DIOU等于d的平方除以c的平方。

代码实现如下

import cv2
import numpy as npdef DIOU(RecA, RecB):x1 = max(RecA[0], RecB[0])y1 = max(RecA[1], RecB[1])x2 = min(RecA[2], RecB[2])y2 = min(RecA[3], RecB[3])# 计算交集部分面积interArea = max(0, x2 - x1 + 1) * max(0, y2 - y1 + 1)# 计算预测值和真实值的面积RecA_Area = (RecA[2] - RecA[0] + 1) * (RecA[3] - RecA[1] + 1)RecB_Area = (RecB[2] - RecB[0] + 1) * (RecB[3] - RecB[1] + 1)#计算并集部分面积UnionArea=float(RecA_Area + RecB_Area - interArea)# 计算IOUiou = interArea / UnionArea# DISTANCEC_x1 = min(RecA[0], RecB[0])C_y1 = min(RecA[1], RecB[1])C_x2 = max(RecA[2], RecB[2])C_y2 = max(RecA[3], RecB[3])center_x1 = (RecA[0]+RecA[2]) / 2center_y1 = (RecA[1]+RecA[3]) / 2center_x2 = (RecB[0] + RecB[2]) / 2center_y2 = (RecB[1] + RecB[3]) / 2center_distance = (center_x2 - center_x1) ** 2 + (center_y2 - center_y1) ** 2c_distance = (C_x2 - C_x1) ** 2 + (C_y2 - C_y1) ** 2DIOU = iou - center_distance / c_distancereturn DIOUimg = np.zeros((512, 512, 3), np.uint8)
img.fill(255)RecA = [0, 0, 30,50] #方框的左上角坐标和右上角坐标
RecB = [5, 5, 25, 45]cv2.rectangle(img, (RecA[0], RecA[1]), (RecA[2], RecA[3]), (0, 255, 0), 5)
cv2.rectangle(img, (RecB[0], RecB[1]), (RecB[2], RecB[3]), (255, 0, 0), 5)iou =DIOU(RecA, RecB)
font = cv2.FONT_ITALIC#展示IOU结果
cv2.putText(img, "DIOU = %.2f" % iou, (200, 450), font, 0.6, (0, 0, 0), 2)cv2.imshow("IOU",img)
cv2.waitKey()
cv2.destroyAllWindows()

当真实框内含预测框时,DIOU也能反映出不同的预测框之间的差距,有效的解决了GIOU的缺点。

现在还有各种改进的交并比,如CIOU、EIOU、Focal-EIOU、SIOU、WIOU等,如果大家有兴趣可以去学习一下这些改进的IOU。

四、DIOU_Loss实战

在这一节我们用学习到的DIOU替换前两章中的小黄人目标检测的L1Loss损失函数。

DIOU_Loss代码如下

class DIou_Loss(nn.Module):def __init__(self):super(DIou_Loss, self).__init__()def box_iou(self, b1, b2):"""输入为:----------b1: tensor, shape=(batch,[x1,y1,x2,y2]) x1,y1 左上角坐标,x2,y2右下角坐标b2: tensor, shape=(batch, [x1,y1,x2,y2])返回为:-------iou: tensor, shape=(batch, 1)"""b1_wh = b1[:, 2:4] - b1[:, :2]b2_wh = b2[:, 2:4] - b2[:, :2]inter_x1 = torch.max(b1[:, 0], b2[:, 0])inter_y1 = torch.max(b1[:, 1], b2[:, 1])inter_x2 = torch.min(b1[:, 2], b2[:, 2])inter_y2 = torch.min(b1[:, 3], b2[:, 3])# ----------------------------------------------------##   求真实框和预测框所有的iou# ----------------------------------------------------#intersect_area =  (torch.clamp(inter_x2 - inter_x1, min=0)+1) * (torch.clamp(inter_y2 - inter_y1, min=0)+1)b1_area = (b1_wh[:, 0]+1) * (b1_wh[:, 1]+1)b2_area = (b2_wh[:, 0]+1) * (b2_wh[:, 1]+1)union_area = b1_area + b2_area - intersect_areaiou = intersect_area / union_area# DISTANCEC_x1 = torch.min(b1[...,0], b2[...,0])C_y1 = torch.min(b1[...,1], b2[...,1])C_x2 = torch.max(b1[...,2], b2[...,2])C_y2 = torch.max(b1[...,3], b2[...,3])center_x1 = (b1[...,0] + b1[...,2]) / 2center_y1 = (b1[...,1] + b1[...,3]) / 2center_x2 = (b2[...,0] + b2[...,2]) / 2center_y2 = (b2[...,1] + b2[...,3]) / 2center_distance = (center_x2 - center_x1) ** 2 + (center_y2 - center_y1) ** 2c_distance = (C_x2 - C_x1) ** 2 + (C_y2 - C_y1) ** 2DIOU = iou - center_distance / c_distancereturn DIOUdef forward(self, input, targets=None):iou = self.box_iou(input, targets)  # 计算交互比loss = torch.mean((1 - iou))return loss

其余代码可以去github下载

GitHub - 1578630119/Single_Object_Detection

再将损失函数换成DIOU_Loss,同时我们还可以利用IOU计算模型的准确率,设置一个阈值,即交并比值,当大于这个值,则这个预测框是正确的,小于则是错误的,最终可以得到模型准确率。代码如下

def iou(b1, b2):b1_wh = b1[:, 2:4] - b1[:, :2]b2_wh = b2[:, 2:4] - b2[:, :2]inter_x1 = torch.max(b1[:, 0], b2[:, 0])inter_y1 = torch.max(b1[:, 1], b2[:, 1])inter_x2 = torch.min(b1[:, 2], b2[:, 2])inter_y2 = torch.min(b1[:, 3], b2[:, 3])# ----------------------------------------------------##   求真实框和预测框所有的iou# ----------------------------------------------------#intersect_area = (torch.clamp(inter_x2 - inter_x1, min=0) + 1) * (torch.clamp(inter_y2 - inter_y1, min=0) + 1)b1_area = (b1_wh[:, 0] + 1) * (b1_wh[:, 1] + 1)b2_area = (b2_wh[:, 0] + 1) * (b2_wh[:, 1] + 1)union_area = b1_area + b2_area - intersect_areaiou = intersect_area / union_areareturn ioudef test():#如果已经训练好了权重,模型直接加载权重文件进行测试#model_test=Net_res()model_test.load_state_dict(torch.load('model.pth',map_location=device))model_test.eval()model_test=model_test.to(device)test_loss = 0correct=0with torch.no_grad():  # 仅测试模型,禁用梯度计算for batch_idx, (data, target) in enumerate(eval_loader):data = data.to(device)target = target.to(device)output = model_test(data)test_loss += criterion(output, target).item()result = iou(output, target)result = torch.where(result > 0.3, 1, 0)correct = correct + result.sum()print('Accuracy:{:.2f}%'.format((correct / ((batch_idx+1)*test_batch_size)).to('cpu').detach().numpy()*100))print('Test Loss:',test_loss/(batch_idx+1))
测试结果

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

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

相关文章

视频监控平台web客户端的免密查看视频页:在PC浏览器上如何调试手机上的前端网页(PC上的手机浏览器的开发者工具)

目录 一、手机上做前端页面开发调试 1、背景 2、视频监控平台AS-V1000的视频分享页 3、调试手机前端页面代码的条件 二、手机端的准备工作 1、手机准备 2、手机的开发者模式 3、PC和手机的连接 (1)进入调试模式 (2)选择…

Android Compose 十二:常用组件列表 上拉加载

列表 上拉加载 当前思路 判断 列表最后一个显示的条目 为 数据集合的长度-1 用来记录刷新状态 var refreshing by remember {mutableStateOf(false)}数据集合 val list remember{List(10){"条目》》${it}"}.toMutableStateList()}用来记录列表当前状态及状态变化…

Redis分布式集群部署

目录 一. 原理简述 二. 集群配置​​​​​​​ 2.1 环境准备 2.2 编译安装一个redis 2.3 创建集群 2.4 写入数据测试 实验一: 实验二: 实验三: 实验四: 添加节点 自动分配槽位 提升节点为master: 实验…

不知几DAY的Symfony---RCE复现

感谢红队大佬老流氓的供稿,此篇文章是针对Symfony框架的一个RCE漏洞复现 ​框架简介 Symfony是一个开源的PHP Web框架,它现在是许多知名 CMS 的核心组件,例如Drupal、Joomla!、eZPlatform(以前称为 eZPublish)或Bolt。…

vue模板语法v-html

模板语法v-html vue使用一种基于HTML的模板语法,使我们能够声明式的将其组件实例的数据绑定到呈现的DOM上,所有的vue模板都是语法层面的HTML,可以被符合规范的浏览器和HTML解释器解析。 一.文本插值 最基本的数据绑定形式是文本插值&#…

Python学习篇:Python基础知识(三)

目录 1 Python保留字 2 注释 3 行与缩进 ​编辑4 多行语句 5 输入和输出 6 变量 7 数据类型 8 类型转换 9 表达式 10 运算符 1 Python保留字 Python保留字(也称为关键字)是Python编程语言中预定义的、具有特殊含义的标识符。这些保留字不能用作…

航空数据管控系统-①项目准备阶段:任务1:项目需求描述

任务描述 从用户的角度阐述项目的开发背景、使用范围及功能需求,从而指导学生独立完成项目的设计与开发。 任务指导 目录 标题 内容 备注 1. 项目概述 1.1 项目背景介绍 (1)说明产品是什么,什么用途 (2&#xff…

【FFmpeg】avcodec_send_frame函数

目录 1.avcodec_send_frame1.1 将输入的frame存入内部buffer(encode_send_frame_internal)1.1.1 frame的引用函数(av_frame_ref )1.1.1.1 帧属性的拷贝(frame_copy_props)1.1.1.2 buffer的引用函数&#xf…

Linux和mysql中的基础知识

cpu读取的指令大部分在内存中(不考虑缓存) 任何程序在运行之前都的加入到内存。 eip->pc指针,指明当前指令在什么位置。 代码大概率是从上往下执行的,基于这样的基本理论。既可以将一部分指令加载到CPU对应的缓存中&#xf…

git 还原被删除的分支

在多人项目开发中,有一次碰到忘记合并到master分支了,直接就把开发分支给删除了,现在记录下怎么还原被删除的分支 必须保证删除的分支之前已经被推送到了远程仓库 # 找出被删除分支的最后一个提交的哈希值 git reflog show# 找到提交哈希值…

【SSL 1823】消灭怪物(非传统BFS)

题目大意 小b现在玩一个极其无聊的游戏,它控制角色从基地出发,一路狂奔夺走了对方的水晶,可是正准备回城时,发现地图上已经生成了 n n n 个怪。 现在假设地图是二维平面,所有的怪和角色都认为是在这个二维平面的点上…

微信小程序的开发

前端:微信小程序开发的技术 后端:springboot的框架 一:微信小程序环境的搭建 1. 访问微信开发者官⽅⽹站的⼩程序开发⼯具下载⻚⾯。 2. 根据你的操作系统(Windows、macOS或Linux)选择合适的版本进⾏下载。 3. 下…

前端三件套开发模版——产品介绍页面

今天有空,使用前端三件套html、css、js制作了一个非常简单的产品制作页面,与大家分享,希望可以满足大家应急的需求。本页面可以对产品进行“抢购”、对产品进行介绍,同时可以安排一张产品的高清大图,我也加入了页面的背…

电气-伺服(4)CANopen

一、CAN Controller Area Network ,控制器局域网,80年的德国Bosch的一家公司研发可以测量仪器直接的实时数据交换而开发的一款串行通信协议。 CAN发展历史 二、CAN 的osi 模型 CAN特性: CAN 的数据帧 三、CANopen 什么是CANopen CANopen 的网络模型 …

力扣1685.有序数组中差绝对值之和

力扣1685.有序数组中差绝对值之和 记录左边之和 和 右边之和从左到右遍历每个元素 求res class Solution {public:vector<int> getSumAbsoluteDifferences(vector<int>& nums) {int n nums.size(),lsum 0,rsum accumulate(nums.begin(),nums.end(),0);ve…

MySQL8 快速导入数据指令load Data 最全详解

MySQL8 快速导入数据指令load Data 最全详解 修改mysql配置文件修改my.ini文件进入mysql,进入库"ceshi"查询你导入的数据表导入数据查询导入的数据 项目基础windows版本MySQL8 修改mysql配置文件 找到mysql的安装目录下的my.ini文件 C:\ProgramData\MySQL\MySQL Serv…

openEuler AArch64 架构 vCPU 热插拔技术内幕

OpenAtom openEuler&#xff08;简称"openEuler"&#xff09;社区引领技术浪潮&#xff0c;早在openEuler 20.09 创新版本就率先使能并对外开放了 AArch64 架构 vCPU 热插特性。时隔四年&#xff0c;openEuler 24.03 LTS 版本补充了 vCPU 热拔能力&#xff0c;vCPU 热…

2.5 C#视觉程序开发实例1----设计一个IO_Manager

2.5 C#视觉程序开发实例1----设计一个IO_Manager 第一步目标&#xff1a; 1 实现获取IO触发信号Trig0 2 能够实现程序切换 3 图像处理后能够输出一个脉冲 1 IO 引脚定义 1.1 输入信号定义 1.2 输出信号定义 2 IO时序图 2.1 触发时序 2.2 切换程序时序图 3 IO_Manager.cs …

【运维】如何在Ubuntu中设置一个内存守护进程来确保内存不会溢出

文章目录 前言增加守护进程1. 编写监控脚本2. 创建 systemd 服务文件3. 启动并启用服务4. 验证服务是否运行注意事项 如何修改守护进程1. 修改监控脚本2. 重新加载并重启服务3. 验证服务是否运行总结 如何设置一个日志文件来查看信息1. 修改监控脚本以记录日志方法一&#xff1…

2024 年 亚太赛 APMCM (C题)中文赛道国际大学生数学建模挑战赛 | 量子计算的物流配送 | 数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题&#xff01; 完整内容可以在文章末尾领取&#xff01; 该段文字…