IoU(Intersection over Union),又称重叠度/交并比。
    1 NMS:当在图像中预测多个proposals、pred bboxes时,由于预测的结果间可能存在高冗余(即同一个目标可能被预测多个矩形框),因此可以过滤掉一些彼此间高重合度的结果;具体操作就是根据各个bbox的score降序排序,剔除与高score bbox有较高重合度的低score bbox,那么重合度的度量指标就是IoU;
    2 mAP:得到检测算法的预测结果后,需要对pred bbox与gt bbox一起评估检测算法的性能,涉及到的评估指标为mAP,那么当一个pred bbox与gt bbox的重合度较高(如IoU score > 0.5),且分类结果也正确时,就可以认为是该pred bbox预测正确,这里也同样涉及到IoU的概念;
    提到IoU,大家都知道怎么回事,讲起来也都头头是道,我拿两个图示意下(以下两张图都不是本人绘制):
    image.png
    IOU = gt bbox、pred bbox交集的面积 / 二者并集的面积
    候选框为pre,真实框为gt
    image.png

    代码实现:

    1. from __future__ import print_function, absolute_import
    2. import numpy as np
    3. def get_IoU(pred_bbox, gt_bbox):
    4. # bbox should be valid, actually we should add more judgements, just ignore here...
    5. # assert ((abs(pred_bbox[2] - pred_bbox[0]) > 0) and
    6. # (abs(pred_bbox[3] - pred_bbox[1]) > 0))
    7. # assert ((abs(gt_bbox[2] - gt_bbox[0]) > 0) and
    8. # (abs(gt_bbox[3] - gt_bbox[1]) > 0))
    9. # -----0---- get coordinates of inters
    10. ixmin = max(pred_bbox[0], gt_bbox[0])
    11. iymin = max(pred_bbox[1], gt_bbox[1])
    12. ixmax = min(pred_bbox[2], gt_bbox[2])
    13. iymax = min(pred_bbox[3], gt_bbox[3])
    14. iw = np.maximum(ixmax - ixmin + 1., 0.)
    15. ih = np.maximum(iymax - iymin + 1., 0.)
    16. # -----1----- intersection
    17. inters = iw * ih
    18. # -----2----- union, uni = S1 + S2 - inters
    19. uni = ((pred_bbox[2] - pred_bbox[0] + 1.) * (pred_bbox[3] - pred_bbox[1] + 1.) +
    20. (gt_bbox[2] - gt_bbox[0] + 1.) * (gt_bbox[3] - gt_bbox[1] + 1.) -
    21. inters)
    22. # -----3----- iou
    23. overlaps = inters / uni
    24. return overlaps
    25. def get_max_IoU(pred_bboxes, gt_bbox):
    26. """
    27. given 1 gt bbox, >1 pred bboxes, return max iou score for the given gt bbox and pred_bboxes
    28. :param pred_bbox: predict bboxes coordinates, we need to find the max iou score with gt bbox for these pred bboxes
    29. :param gt_bbox: ground truth bbox coordinate
    30. :return: max iou score
    31. """
    32. # bbox should be valid, actually we should add more judgements, just ignore here...
    33. # assert ((abs(gt_bbox[2] - gt_bbox[0]) > 0) and
    34. # (abs(gt_bbox[3] - gt_bbox[1]) > 0))
    35. if pred_bboxes.shape[0] > 0:
    36. # -----0---- get coordinates of inters, but with multiple predict bboxes
    37. ixmin = np.maximum(pred_bboxes[:, 0], gt_bbox[0])
    38. iymin = np.maximum(pred_bboxes[:, 1], gt_bbox[1])
    39. ixmax = np.minimum(pred_bboxes[:, 2], gt_bbox[2])
    40. iymax = np.minimum(pred_bboxes[:, 3], gt_bbox[3])
    41. iw = np.maximum(ixmax - ixmin + 1., 0.)
    42. ih = np.maximum(iymax - iymin + 1., 0.)
    43. # -----1----- intersection
    44. inters = iw * ih
    45. # -----2----- union, uni = S1 + S2 - inters
    46. uni = ((gt_bbox[2] - gt_bbox[0] + 1.) * (gt_bbox[3] - gt_bbox[1] + 1.) +
    47. (pred_bboxes[:, 2] - pred_bboxes[:, 0] + 1.) * (pred_bboxes[:, 3] - pred_bboxes[:, 1] + 1.) -
    48. inters)
    49. # -----3----- iou, get max score and max iou index
    50. overlaps = inters / uni
    51. ovmax = np.max(overlaps)
    52. jmax = np.argmax(overlaps)
    53. return overlaps, ovmax, jmax
    54. if __name__ == "__main__":
    55. # test1
    56. pred_bbox = np.array([50, 50, 90, 100]) # top-left: <50, 50>, bottom-down: <90, 100>, <x-axis, y-axis>
    57. gt_bbox = np.array([70, 80, 120, 150])
    58. print (get_IoU(pred_bbox, gt_bbox))
    59. # test2
    60. pred_bboxes = np.array([[15, 18, 47, 60],
    61. [50, 50, 90, 100],
    62. [70, 80, 120, 145],
    63. [130, 160, 250, 280],
    64. [25.6, 66.1, 113.3, 147.8]])
    65. gt_bbox = np.array([70, 80, 120, 150])
    66. print (get_max_IoU(pred_bboxes, gt_bbox))