YOLOv8改进 | 2023 | MPDIoU、InnerMPDIoU助力细节涨点

论文地址:官方论文地址点击即可跳转

代码地址:官方并没有开源的该损失的函数的代码,我根据文章内容进行了复现代码块在第三章

 一、本文介绍

本文为读者详细介绍了YOLOv8模型的最新改进,带来的改进机制是最新的损失函数MPDIoU和融合了最新的Inner思想的InnerMPDIoU(效果打爆之前的所有的损失函数)提升检测精度和处理细节方面的作用。通过深入探讨MPDIoU和InnerMPDIoU(全网首发)的工作原理和实际代码实现,本文旨在指导读者如何将这些先进的损失函数技术应用到YOLOv8模型中,以提高其性能和准确性。文章内容涵盖从理论基础、代码实现,到实际教你如何添加本文的机制到你的模型中

  专栏回顾:YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备

实验效果图如下所示-> 

因为资源有限我发的文章都要做对比实验所以本次实验我只用了一百张图片检测的是安全帽训练了一百个epoch,该结果只能展示出该机制有效,但是并不能产生决定性结果,因为具体的效果还要看你的数据集和实验环境所影响。

分析下这个结果图片:最左面的是基础版本没做任何修改的,中间的只是修改了MPDIoU可以看到涨点相对于基础版本的大概有0.05个点左右,但是我增加了InnerMPDIoU的效果基本持平(我个人觉得是我的数据集原因)所以大家自己进行实验的时候可以多做一轮进行一下对比。 

目录

 一、本文介绍

二、MPDIoU的机制原理

三、MPDIoU的代码复现 

四、手把手教你添加MPDIoU到你的模型中 

 4.1 CARAFE的添加教程

五、全文总结


二、MPDIoU的机制原理

问题提出:文章指出,在目标检测和实例分割的过程中,传统的边界框回归(BBR)损失函数难以优化预测框和真实框在宽高比相同但具体尺寸不同时的情况,下面是描述现有的边界框回归的方法的计算因素总结(包括GIoU、DIoU、CIoU和EIoU)的计算因素。这些度量方法是用于评估和优化边界框回归模型性能的关键工具。虽然文章没有直接展示下图的内容,但它们包括以下几个方面:

  • GIoU(Generalized IoU):除了传统的IoU(交并比)之外,GIoU还考虑了边界框之间的包含关系和空间分布。

  • DIoU(Distance IoU):在IoU的基础上,DIoU还考虑了边界框中心点之间的距离,以改进对齐和尺度不一致的情况。

  • CIoU(Complete IoU):结合了DIoU的特点,并加入了宽高比的考虑,进一步提高了对边界框的精确度。

  • EIoU(Expected IoU):这是一种更高级的度量方法,考虑了预测边界框与真实边界框之间的预期相似度。

文章提出的MPDIoU是在这些现有度量方法的基础上发展起来的,旨在通过直接最小化预测框和真实框之间的关键点距离,提供一种易于实现的解决方案,用于计算两个轴对齐矩形之间的MPDIoU​

 

  

MPDIoU的提出:为了克服这一挑战,文章提出了一种新的边界框相似度度量方法——MPDIoU(Minimum Point Distance Intersection over Union)。MPDIoU是基于水平矩形的最小点距离来计算的,能够综合考虑重叠区域、中心点距离以及宽度和高度的偏差。

下图展示了两种不同的边界框回归结果情况。其中,绿色框代表真实的边界框而红色框代表预测的边界框。在这两种情况下,传统的损失函数(如GIoU、DIoU、CIoU和EIoU)计算出的损失值是相同的,但是使用MPDIoU方法计算出的损失值却有所不同。这说明传统方法在某些特定情况下可能无法区分不同的预测结果,而MPDIoU能更准确地反映预测框和真实框之间的差异。

这个发现突显了MPDIoU在处理边界框回归问题上的优势,尤其是在区分具有相同宽高比但不同尺寸或位置的边界框时。MPDIoU通过直接计算预测框和真实框之间的关键点距离,提供了更精确的损失度量方法。

LMPDIoU损失函数:基于MPDIoU的概念,文章定义了一种新的损失函数LMPDIoU。LMPDIoU的公式如下:

LMPDIoU=1-MPDIoU

这一公式表明LMPDIoU损失函数与MPDIoU的相似度成反比关系,即MPDIoU越高,LMPDIoU损失越低,这推动模型预测的边界框更加接近真实框。

公式推理:在下图展示了作者提出的LMPDIoU损失函数的各种因素。

这些因素包括如何在训练阶段通过最小化损失函数来使模型预测的边界框接近其真实边界框。具体来说,每个预测的边界框

B_{prd} = \left[ \begin{array}{c} x_{prd} \\ y_{prd} \\ w_{prd} \\ h_{prd} \end{array} \right]

通过最小化以下损失函数来逼近其真实边界框:

B_{gt} = [x_{gt}, y_{gt}, w_{gt}, h_{gt}]^T 

L = \min_{\Theta} L(B_{gt}, B_{prd} | \Theta) 

其中,B_{gt} 是真实边界框的集合,而 \Theta 是回归深度模型的参数。文章中提出的LMPDIoU损失函数公式为: 

LMPDIoU=1-MPDIoU

实验验证:通过在多个数据集(如PASCAL VOC、MS COCO和IIIT5k)上对YOLACT和YOLOv7等模型的训练和测试,文章验证了MPDIoU和LMPDIoU在实际应用中的有效性。实验结果显示,这种新的损失函数在多个方面优于传统的损失函数,尤其是在处理具有相似宽高比但不同尺寸的边界框时。

下面是一些检测效果对比图 

总结来说,文章通过引入MPDIoU和LMPDIoU(我又将其和Inner的思想结合了在一起形成了InnerMPDIoU双重提高了效果),提供了一种新的视角来优化目标检测中的边界框回归问题,同时通过实验验证了其在提高检测模型准确性方面的有效性。

三、MPDIoU的代码复现 

论文中不仅提出了MPDIoU还提出了一个LMPDIoU但是这个LMPDIoU我用了以后模型根本收敛不了,所以我不知道这是我数据集的原因还是其它原因导致的,但是MPDIoU我使用效果是非常好的,其中我还添加了Focus和Inner的思想, 如果你Inner和MPDIoU都设置为True使用的就是InnerMPDIoU,如果Inner为False但是MPDIoU设置为True就是MPDIoU,Focus同理,支持FocusInnerMPDIoU,所以大家可以多进行尝试。 

class WIoU_Scale:''' monotonous: {None: origin v1True: monotonic FM v2False: non-monotonic FM v3}momentum: The momentum of running mean'''iou_mean = 1.monotonous = False_momentum = 1 - 0.5 ** (1 / 7000)_is_train = Truedef __init__(self, iou):self.iou = iouself._update(self)@classmethoddef _update(cls, self):if cls._is_train: cls.iou_mean = (1 - cls._momentum) * cls.iou_mean + \cls._momentum * self.iou.detach().mean().item()@classmethoddef _scaled_loss(cls, self, gamma=1.9, delta=3):if isinstance(self.monotonous, bool):if self.monotonous:return (self.iou.detach() / self.iou_mean).sqrt()else:beta = self.iou.detach() / self.iou_meanalpha = delta * torch.pow(gamma, beta - delta)return beta / alphareturn 1def bbox_iou(box1, box2, x1y1x2y2=True, ratio=1, GIoU=False, DIoU=False, CIoU=False, SIoU=False,EIoU=False, WIoU=False, MPDIoU=False, LMPDIoU=False, Inner=False, Focal=False, alpha=1, gamma=0.5,scale=False, eps=1e-7):if Inner:(x1, y1, w1, h1), (x2, y2, w2, h2) = box1.chunk(4, -1), box2.chunk(4, -1)w1_, h1_, w2_, h2_ = w1 / 2, h1 / 2, w2 / 2, h2 / 2# Inner-IoU      #Inner-IoU        #Inner-IoU        #Inner-IoU        #Inner-IoU        #Inner-IoU        #Inner-IoUb1_x1, b1_x2, b1_y1, b1_y2 = x1 - w1_ * ratio, x1 + w1_ * ratio, \y1 - h1_ * ratio, y1 + h1_ * ratiob2_x1, b2_x2, b2_y1, b2_y2 = x2 - w2_ * ratio, x2 + w2_ * ratio, \y2 - h2_ * ratio, y2 + h2_ * ratiointer = (torch.min(b1_x2, b2_x2) - torch.max(b1_x1, b2_x1)).clamp(0) * \(torch.min(b1_y2, b2_y2) - torch.max(b1_y1, b2_y1)).clamp(0)union = w1 * ratio * h1 * ratio + w2 * ratio * h2 * ratio - inter + epsiou = inter / union  # inner_iouelse:# Returns the IoU of box1 to box2. box1 is 4, box2 is nx4box2 = box2.T# Get the coordinates of bounding boxesif x1y1x2y2:  # x1, y1, x2, y2 = box1b1_x1, b1_y1, b1_x2, b1_y2 = box1[0], box1[1], box1[2], box1[3]b2_x1, b2_y1, b2_x2, b2_y2 = box2[0], box2[1], box2[2], box2[3]else:  # transform from xywh to xyxyb1_x1, b1_x2 = box1[0] - box1[2] / 2, box1[0] + box1[2] / 2b1_y1, b1_y2 = box1[1] - box1[3] / 2, box1[1] + box1[3] / 2b2_x1, b2_x2 = box2[0] - box2[2] / 2, box2[0] + box2[2] / 2b2_y1, b2_y2 = box2[1] - box2[3] / 2, box2[1] + box2[3] / 2# Intersection areainter = (torch.min(b1_x2, b2_x2) - torch.max(b1_x1, b2_x1)).clamp(0) * \(torch.min(b1_y2, b2_y2) - torch.max(b1_y1, b2_y1)).clamp(0)# Union Areaw1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1 + epsw2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1 + epsunion = w1 * h1 + w2 * h2 - inter + eps# IoU# iou = inter / union # ori iouiou = torch.pow(inter / (union + eps), alpha)  # alpha iouif scale:self = WIoU_Scale(1 - (inter / union))if CIoU or DIoU or GIoU or EIoU or SIoU or WIoU or MPDIoU or LMPDIoU:cw = b1_x2.maximum(b2_x2) - b1_x1.minimum(b2_x1)  # convex (smallest enclosing box) widthch = b1_y2.maximum(b2_y2) - b1_y1.minimum(b2_y1)  # convex heightif CIoU or DIoU or EIoU or SIoU or WIoU or MPDIoU or LMPDIoU:  # Distance or Complete IoU# https://arxiv.org/abs/1911.08287v1c2 = (cw ** 2 + ch ** 2) ** alpha + eps  # convex diagonal squaredrho2 = (((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 + (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4) ** alpha  # center dist ** 2if CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47v = (4 / math.pi ** 2) * (torch.atan(w2 / h2) - torch.atan(w1 / h1)).pow(2)with torch.no_grad():alpha_ciou = v / (v - iou + (1 + eps))if Focal:return iou - (rho2 / c2 + torch.pow(v * alpha_ciou + eps, alpha)), torch.pow(inter / (union + eps),gamma)  # Focal_CIoUelse:return iou - (rho2 / c2 + torch.pow(v * alpha_ciou + eps, alpha))  # CIoUelif MPDIoU:d1 = (b2_x1 - b1_x1) ** 2 + (b2_y1 - b1_y1) ** 2d2 = (b2_x2 - b1_x2) ** 2 + (b2_y2 - b1_y2) ** 2w = (b2_x2 - b2_x1)   # x2 - x1h = (b2_y2 - b2_y1)  # y2 - y1if Focal:return iou - ((d1 + d2) / (w ** 2 + h ** 2)), torch.pow(inter / (union + eps), gamma)  # Focal_MPDIoUelse:return iou - ((d1 + d2)/(w ** 2 + h ** 2))elif LMPDIoU:d1 = (b2_x1 - b1_x1) ** 2 + (b2_y1 - b1_y1) ** 2d2 = (b2_x2 - b1_x2) ** 2 + (b2_y2 - b1_y2) ** 2w = (b2_x2 - b2_x1)   # x2 - x1h = (b2_y2 - b2_y1)  # y2 - y1if Focal:return 1 - (iou - ((d1 + d2)/(w ** 2 + h ** 2))), torch.pow(inter / (union + eps), gamma)  # Focal_MPDIo  # MPDIoUelse:return 1 - (iou - ((d1 + d2) / (w ** 2 + h ** 2)))elif EIoU:rho_w2 = ((b2_x2 - b2_x1) - (b1_x2 - b1_x1)) ** 2rho_h2 = ((b2_y2 - b2_y1) - (b1_y2 - b1_y1)) ** 2cw2 = torch.pow(cw ** 2 + eps, alpha)ch2 = torch.pow(ch ** 2 + eps, alpha)if Focal:return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2), torch.pow(inter / (union + eps),gamma)  # Focal_EIouelse:return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2)  # EIouelif SIoU:# SIoU Loss https://arxiv.org/pdf/2205.12740.pdfs_cw = (b2_x1 + b2_x2 - b1_x1 - b1_x2) * 0.5 + epss_ch = (b2_y1 + b2_y2 - b1_y1 - b1_y2) * 0.5 + epssigma = torch.pow(s_cw ** 2 + s_ch ** 2, 0.5)sin_alpha_1 = torch.abs(s_cw) / sigmasin_alpha_2 = torch.abs(s_ch) / sigmathreshold = pow(2, 0.5) / 2sin_alpha = torch.where(sin_alpha_1 > threshold, sin_alpha_2, sin_alpha_1)angle_cost = torch.cos(torch.arcsin(sin_alpha) * 2 - math.pi / 2)rho_x = (s_cw / cw) ** 2rho_y = (s_ch / ch) ** 2gamma = angle_cost - 2distance_cost = 2 - torch.exp(gamma * rho_x) - torch.exp(gamma * rho_y)omiga_w = torch.abs(w1 - w2) / torch.max(w1, w2)omiga_h = torch.abs(h1 - h2) / torch.max(h1, h2)shape_cost = torch.pow(1 - torch.exp(-1 * omiga_w), 4) + torch.pow(1 - torch.exp(-1 * omiga_h), 4)if Focal:return iou - torch.pow(0.5 * (distance_cost + shape_cost) + eps, alpha), torch.pow(inter / (union + eps), gamma)  # Focal_SIouelse:return iou - torch.pow(0.5 * (distance_cost + shape_cost) + eps, alpha)  # SIouelif WIoU:if Focal:raise RuntimeError("WIoU do not support Focal.")elif scale:return getattr(WIoU_Scale, '_scaled_loss')(self), (1 - iou) * torch.exp((rho2 / c2)), iou  # WIoU https://arxiv.org/abs/2301.10051else:return iou, torch.exp((rho2 / c2))  # WIoU v1if Focal:return iou - rho2 / c2, torch.pow(inter / (union + eps), gamma)  # Focal_DIoUelse:return iou - rho2 / c2  # DIoUc_area = cw * ch + eps  # convex areaif Focal:return iou - torch.pow((c_area - union) / c_area + eps, alpha), torch.pow(inter / (union + eps),gamma)  # Focal_GIoU https://arxiv.org/pdf/1902.09630.pdfelse:return iou - torch.pow((c_area - union) / c_area + eps,alpha)  # GIoU https://arxiv.org/pdf/1902.09630.pdfif Focal:return iou, torch.pow(inter / (union + eps), gamma)  # Focal_IoUelse:return iou  # IoU

四、手把手教你添加MPDIoU到你的模型中 

 4.1 CARAFE的添加教程

添加教程这里不再重复介绍、因为专栏内容有许多,添加过程又需要截特别图片会导致文章大家读者也不通顺如果你已经会添加注意力机制了,可以跳过本章节,如果你还不会,大家可以看我下面的文章,里面详细的介绍了拿到一个任意机制(C2f、Conv、Bottleneck、Loss、DetectHead)如何添加到你的网络结构中去。

本为提到损失函数里面也有详细版本的教程,再次强调一下使用方法:如果你Inner和MPDIoU都设置为True使用的就是InnerMPDIoU,如果Inner为False但是MPDIoU设置为True就是MPDIoU,Focus同理,还支持FocusInnerMPDIoU。 

添加教程->YOLOv8改进 | 如何在网络结构中添加注意力机制、C2f、卷积、Neck、检测头

这里顺便推荐一下我之前的博客讲的是InnerIoU这个损失函数的思想我做了很多次实验都可以有效涨点,里面进行了详细的介绍大家有兴趣可以进行回顾。

InnerIoU回顾:YOLOv8改进 | 2023 | InnerIoU、InnerSIoU、InnerWIoU、FocusIoU等损失函数

五、全文总结

到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv8改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,目前本专栏免费阅读(暂时,大家尽早关注不迷路~),如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

专栏回顾:YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备

 

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

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

相关文章

二十一、数组(6)

本章概要 数组排序Arrays.sort的使用并行排序binarySearch二分查找parallelPrefix并行前缀 数组排序 根据对象的实际类型执行比较排序。一种方法是为不同的类型编写对应的排序方法,但是这样的代码不能复用。 编程设计的一个主要目标是“将易变的元素与稳定的元素…

Maven项目下详细的SSM整合流程

文章目录 🎉SSM整合流程一、两个容器整合✨ 1、先准备好数据库config.properties连接、mybatis-config.xml🎊 2、容器一:优先配置spring.xml文件🎊 3、容器二:配置springMVC.xml文件🎊 4、Tomcat整合spring…

张弛语言课,战争电影配音声音细致声音来复原战场

为战争片进行声音配音是一项挑战性的工作,它要求精确再现战场的紧张感和复杂情绪。配音人员和声音设计团队必须创造出真实的战争声景,从战斗的轰鸣声到士兵的呐喊,这些声音元素都需细致打造,以传递战争的惨烈、英勇和人性的复杂。…

RESTful

RestFul API 何为 API? API(Application Programming Interface) 翻译过来是应用程序编程接口的意思。 我们在进行后端开发的时候,主要的工作就是为前端或者其他后端服务提供 API 比如查询用户数据的 API 。 但是, …

【刷题宝典NO.4】

目录 公交站间的距离 生命游戏 公交站间的距离 https://leetcode.cn/problems/distance-between-bus-stops/ 环形公交路线上有 n 个站,按次序从 0 到 n - 1 进行编号。我们已知每一对相邻公交站之间的距离,distance[i] 表示编号为 i 的车站和编号为 …

【Web】CmsEasy 漏洞复现

访问主页 到处点一点没啥发现 扫目录 访问/admin 账号密码都是admin admin,不知道为什么,这里就先当作是默认吧 (其实都是信息检索,能在网上搜到就行hhh) 登录成功 看到左边列表有模板,心里大概有数了哈 进行一波历…

vue005——vue组件入门(非单文件组件和单文件组件)

一、非单文件组件 1.1、单文件组件的使用 1.1.1、局部注册 1、第一步&#xff1a;创建school组件 2、第二步&#xff1a;注册组件&#xff08;局部注册&#xff09; 3、第三步&#xff1a;使用组件&#xff08;编写组件标签&#xff09; <!DOCTYPE html> <html>…

没搞懂二维差分是什么怎么办???

摸鱼的时候画的&#xff0c;根据公式反推 一维差分倒是懂了 a[10]{1,2,6,9,11,12,17,21,32,67}; c[10]{1,1,4,3,2,1,5,4,11,35}; 现要把[3,7]的值都增加3 c[10]{1,1,7,3,2,1,5,1,11,35}; 要查询的时候再用for循环相加 结论&#xff1a;成立且适用于多次修改 不知道为什么这个…

接口自动化测试是个啥?如何开始?什么是框架?带你揭开神秘面纱

自动化测试 自动化测试&#xff0c;这几年行业内的热词&#xff0c;也是测试人员进阶的必备技能&#xff0c;更是软件测试未来发展的趋势。 特别是在敏捷模式下&#xff0c;产品迭代速度快&#xff0c;市场不断调整&#xff0c;客户需求不断变化&#xff0c;单纯的手工测试越…

某图app sig、client_session

文章目录 声明目标加密参数定位代码实现声明 本文章中所有内容仅供学习交流,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请私信我立即删除! 目标 这次看一下某图秀秀app 搜索接口: 抓一下包 url参数提取 url = "https://api.x…

1.前端--基本概念【2023.11.25】

1.网站与网页 网站是网页集合。 网页是网站中的一“页”&#xff0c;通常是 HTML 格式的文件&#xff0c;它要通过浏览器来阅读。 2.Web的构成 主要包括结构&#xff08;Structure&#xff09; 、表现&#xff08;Presentation&#xff09;和行为&#xff08;Behavior&#xff…

操作系统:操作系统教程第六版(骆斌、葛季栋、费翔林)习题二处理器管理

目录 前言1. 简答题2. 应用题 前言 本系列文章是针对操作系统教程第六版&#xff08;骆斌、葛季栋、费翔林&#xff09;的习题解答&#xff0c;其中简答题部分为博主自己搜索整理的&#xff0c;错漏之处在所难免。应用题部分有答案为依据。 1. 简答题 &#xff08;1&#xf…