当前位置:   article > 正文

目标检测中的IOU和CIOU原理讲解以及应用(附测试代码))

ciou

                                                   

上期讲解了目标检测中的三种数据增强的方法,这期我们讲讲目标检测中用来评估对象检测算法的IOU和CIOU的原理应用以及代码实现。
 

交并比IOU

交并比IOU(Interp over union)

在目标检测任务中,我们用框框来定位对象,如下图定位图片中这个汽车,假设实际框是图中红色的框框,你的算法预测给出的是紫色的框框,怎么判断你的算法预测的这个框框的效果好坏呢?

这就用到我们的交并比函数IOU了,计算公式如下:

将我们图片汽车的实际红色框记为A,算法的预测框记为B,交并比就是数学中A和B的交集A∩B跟A和B的并集的A∪B的面积之比,非常容易理解。IOU实际上衡量了两个边界框重叠地相对大小,预测框和真实框重叠越大,说明你的算法预测效果比较好,IOU是一个评价指标

那么回到刚刚的问题: 如何利用IOU进行判断算法的预测效果好坏呢?也就是这个预测框是否可以当做正确的定位到我们的目标汽车呢?

在计算机检测任务中,如果我们算法的预测框和实际框之间的交并比IOU≧0.5,那么你的算法预测结果是可以接受的,就说你预测的这个框框是正确的,这个阈值0.5,你可以设置得更高,边界框越精确,在YOLOv3中正是用到这个IOU来对我们的先验框进行了一个筛选,以及计算测试集的模型效果mAP时也用到了IOU进行阈值判断

效果图

首先借助Opencv和numpy框画两个框,然后计算IOU进行展示,如下图。

IOU实现代码

以框的左上角(x1,y1)和右下角(x2,y2)坐标形式来计算它们之间的IOU。

  1. import cv2
  2. import numpy as np
  3. def CountIOU(RecA, RecB):
  4. xA = max(RecA[0], RecB[0])
  5. yA = max(RecA[1], RecB[1])
  6. xB = min(RecA[2], RecB[2])
  7. yB = min(RecA[3], RecB[3])
  8. # 计算交集部分面积
  9. interArea = max(0, xB - xA + 1) * max(0, yB - yA + 1)
  10. # 计算预测值和真实值的面积
  11. RecA_Area = (RecA[2] - RecA[0] + 1) * (RecA[3] - RecA[1] + 1)
  12. RecB_Area = (RecB[2] - RecB[0] + 1) * (RecB[3] - RecB[1] + 1)
  13. # 计算IOU
  14. iou = interArea / float(RecA_Area + RecB_Area - interArea)
  15. return iou
  16. if __name__ == "__main__":
  17. img = np.zeros((512, 512, 3), np.uint8)
  18. img.fill(255)
  19. RecA = [50, 50, 300, 300] # x1,y1,x2,y2
  20. RecB = [60, 60, 320, 320]
  21. cv2.rectangle(img, (RecA[0], RecA[1]), (RecA[2], RecA[3]), (0, 255, 0), 5)
  22. cv2.rectangle(img, (RecB[0], RecB[1]), (RecB[2], RecB[3]), (255, 0, 0), 5)
  23. IOU = CountIOU(RecA, RecB)
  24. font = cv2.FONT_HERSHEY_SIMPLEX
  25. cv2.putText(img, "IOU = %.2f" % IOU, (130, 190), font, 0.8, (0, 0, 0), 2)
  26. cv2.imshow("image", img)
  27. cv2.waitKey()
  28. cv2.destroyAllWindows()

CIOU(Complete-IOU)

CIOU(Complete-IOU)

IoU是比值的概念,对目标物体的尺寸scale是不敏感的。我们在计算框框BBox的回归损失函数进行优化有多种优化方式,如在CIOU之前有GIOU、DIOU,而CIOU解决了一般IoU无法直接优化两个框框没有重叠的部分。

IoU经过GIOU再到DIOU最终发展到CIOU,CIOU将目标与框框anchor之间的距离,重叠率、尺度以及惩罚项都考虑进去,使得目标框回归变得更加稳定,不会像IoU和GIoU一样出现训练过程中发散等问题,而惩罚因子把预测框长宽比拟合目标框的长宽比考虑进去,在最新发布的yolov4中anchor的回归就是用的CIOU方式

CIOU计算公式

其中分别代表了预测框和真实框的中心点的欧式距离,也就是图中的d。代表的是能够同时包含预测框和真实框的最小闭包区域的对角线距离。

CIOU回归时的LOSS计算:

效果图

首先借助Opencv和numpy框画两个框,然后按照公式计算CIOU进行展示,如下图。

 

代码实现:

  1. import torch
  2. import numpy as np
  3. import cv2
  4. import math
  5. def box_ciou(b1, b2):
  6. """
  7. 输入为: ----------
  8. b1: tensor, shape=(batch, feat_w, feat_h, anchor_num, 4), xywh
  9. b2: tensor, shape=(batch, feat_w, feat_h, anchor_num, 4), xywh
  10. 返回为: -------
  11. ciou: tensor, shape=(batch, feat_w, feat_h, anchor_num, 1)
  12. """
  13. # 求出预测框左上角右下角
  14. b1_xy = b1[..., :2]
  15. b1_wh = b1[..., 2:4]
  16. b1_wh_half = b1_wh/2.
  17. b1_mins = b1_xy - b1_wh_half
  18. b1_maxes = b1_xy + b1_wh_half
  19. # 求出真实框左上角右下角
  20. b2_xy = b2[..., :2]
  21. b2_wh = b2[..., 2:4]
  22. b2_wh_half = b2_wh/2.
  23. b2_mins = b2_xy - b2_wh_half
  24. b2_maxes = b2_xy + b2_wh_half
  25. # 求真实框和预测框所有的iou
  26. intersect_mins = torch.max(b1_mins, b2_mins)
  27. intersect_maxes = torch.min(b1_maxes, b2_maxes)
  28. intersect_wh = torch.max(intersect_maxes - intersect_mins, torch.zeros_like(intersect_maxes))
  29. intersect_area = intersect_wh[..., 0] * intersect_wh[..., 1]
  30. b1_area = b1_wh[..., 0] * b1_wh[..., 1]
  31. b2_area = b2_wh[..., 0] * b2_wh[..., 1]
  32. union_area = b1_area + b2_area - intersect_area
  33. iou = intersect_area / (union_area + 1e-6)
  34. # 计算中心的差距
  35. center_distance = torch.sum(torch.pow((b1_xy - b2_xy), 2), axis=-1)
  36. # 找到包裹两个框的最小框的左上角和右下角
  37. enclose_mins = torch.min(b1_mins, b2_mins)
  38. enclose_maxes = torch.max(b1_maxes, b2_maxes)
  39. enclose_wh = torch.max(enclose_maxes - enclose_mins, torch.zeros_like(intersect_maxes))
  40. # 计算对角线距离
  41. enclose_diagonal = torch.sum(torch.pow(enclose_wh,2), axis=-1)
  42. ciou = iou - 1.0 * (center_distance) / (enclose_diagonal + 1e-7)
  43. v = (4 / (math.pi ** 2)) * torch.pow((torch.atan(b1_wh[..., 0]/b1_wh[..., 1]) - torch.atan(b2_wh[..., 0]/b2_wh[..., 1])), 2)
  44. alpha = v / (1.0 - iou + v)
  45. ciou = ciou - alpha * v
  46. return ciou
  47. if __name__ == "__main__":
  48. img = np.zeros((512, 512, 3), np.uint8)
  49. img.fill(255)
  50. RecA = [1, 90, 90, 150, 150]
  51. RecB = [1, 150, 150, 200, 200]
  52. a = torch.tensor(RecA, dtype=torch.float) # tensor, shape=(batch, feat_w, feat_h, anchor_num, 4), xywh
  53. b = torch.tensor(RecB, dtype=torch.float)
  54. cv2.rectangle(img, (int(RecA[1]-RecA[3]/2), int(RecA[2]-RecA[4]/2)), (int(RecA[1]+RecA[3]/2), int(RecA[2]+RecA[4]/2)), (0, 255, 0), 5)
  55. cv2.rectangle(img,(int(RecB[1]-RecB[3]/2), int(RecB[2]-RecB[4]/2)), (int(RecB[1]+RecB[3]/2), int(RecB[2]+RecB[4]/2)), (255, 0, 0), 5)
  56. CIOU = box_ciou(a,b)
  57. font = cv2.FONT_HERSHEY_SIMPLEX
  58. cv2.putText(img, "CIOU = %.2f" % CIOU, (130, 190), font, 0.8, (0, 0, 0), 2)
  59. cv2.imshow("image", img)
  60. cv2.waitKey()
  61. cv2.destroyAllWindows()

所有实现代码,在后台回复关键字:IOU,即可下载使用。

精彩推荐

目标检测中的数据增强方法(附代码讲解)

目标检测中的数据增强方法(附代码讲解)

制作自己的训练数据集之图像标注工具labelimg和labelme

 

关注微信公众号:码农的后花园,后台回复关键字:Python工具,即可获取,查看Python学习系列教程即可快速安装,更有Python系列学习。

                                                                 微信号:码农的后花园

                                                                                     

                                                                                长按识别关注哦

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/719456
推荐阅读
相关标签
  

闽ICP备14008679号