栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

IOU和NMS图解(附Python和C++代码)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

IOU和NMS图解(附Python和C++代码)

1 IOU计算: 交并比 1.1 先上代码

Python版

class Iou:
    def compute_iou(self, x1, y1, x2, y2, x3, y3, x4, y4):
    
        #两矩阵面积之和
        area = (x2 - x1) * (y2 - y1) + (x4 - x3) * (y4 - y3)
		# 两矩阵相交部分的左上角和右下角坐标确定
        middle_x1 = max(x1, x3)
        middle_x2 = min(x2, x4)
        middle_y1 = max(y1, y3)
        middle_y2 = min(y2, y4)
        middle_w = max(0.0, middle_x2 - middle_x1)
        middle_h = max(0.0, middle_y2 - middle_y1)
        
        #两矩阵之交
        middle_area = middle_w * middle_h
        
        # return 交 / 并
        return middle_area / (area - middle_area)


if __name__=="__main__":
    rec1 = [27, 661, 47, 679]
    rec2 = [27, 662, 47, 682]
    a = Iou().compute_iou(*rec1, *rec2)
    print(f"a: {a}")

C++ 版

1.2 推导过程

IOU公式如下:

I O U = 两 矩 阵 交 / 两 矩 阵 并 IOU = 两矩阵交 /两矩阵并 IOU=两矩阵交/两矩阵并

以左上角为远点。已知两个矩阵的左上角和右下角坐标,计算IOU。具体地,
第一个矩形rec1,左上:(x1, y1) ,右下:(x2, y2) ;
第二个矩形rec2,左上:(x3, y3) ,右下:(x4, y4) ;
很容易计算两个矩阵的和,公式如下:
a r e a = r e c 1 + r e c 2 = ( x 2 − x 1 ) ∗ ( y 2 − y 1 ) + ( x 4 − x 3 ) ∗ ( y 4 − y 3 ) area = rec1 + rec2 = (x2 - x1)*(y2 - y1) + (x4 - x3)*(y4 - y3) area=rec1+rec2=(x2−x1)∗(y2−y1)+(x4−x3)∗(y4−y3)
要计算两矩阵的交,则要确定相交的面积的左上和右下坐标,则有:
m i d d l e _ l e f t = m a x ( x 1 , x 3 ) middle_left = max(x1, x3) middle_left=max(x1,x3)
m i d d l e _ r i g h t = m i n ( x 2 , x 4 ) middle_right = min(x2, x4) middle_right=min(x2,x4)
m i d d l e _ t o p = m a x ( y 1 , y 3 ) middle_top = max(y1, y3) middle_top=max(y1,y3)
m i d d l e _ b u t t o m = m i n ( y 2 , y 4 ) middle_buttom = min(y2, y4) middle_buttom=min(y2,y4)
因此矩阵的交为:
m i d d l e _ a r e a = ( m i d d l e _ r i g h t − m i d d l e _ l e f t ) ∗ ( m i d d l e _ b u t t o m − m i d d l e _ t o p ) middle_area = (middle_right - middle_left) * (middle_buttom - middle_top) middle_area=(middle_right−middle_left)∗(middle_buttom−middle_top)

矩阵的并为:
矩 阵 的 并 = 矩 阵 的 和 − 矩 阵 的 交 矩阵的并 = 矩阵的和 - 矩阵的交 矩阵的并=矩阵的和−矩阵的交
因此最终公式为
I O U = m i d d l e _ a r e a a r e a − m i d d l e _ a r e a IOU = frac{middle_area}{area - middle_area} IOU=area−middle_areamiddle_area​

2 NMS:非极大值抑制(Non-Maximum Suppression, NMS) 2.1 先上代码
import numpy as np
import matplotlib.pyplot as plt

class Solution:
    def nms(self, boxes, threshold):

        # 计算所有候选框面积,利用numpy一次计算所有的候选框
        x1, y1, x2, y2, score = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3],  boxes[:, 4]

        #计算每个框的面积
        areas = (x2 - x1 + 1) * (y2 - y1 + 1)

        # 对每个框的置信度进行从小到大排序,order存储的是对应score中从小到大的索引值
        order = np.argsort(score)

        # keep是返回值,经过 NMS 后挑选出的框
        keep = []

        while order.size > 0:
            # 将当前置信度最大的框加入返回值,并用其抑制iou>给定阈值的框,小于阈值的框继续做NMS,直到所有框被挑选完
            index = order[-1]
            keep.append(index)

            # 计算置信度最大的框和其余框的iou,这里计算的数量为当前order.size - 1.
            middle_x1 = np.maximum(x1[index], x1[order[:-1]])
            middle_x2 = np.minimum(x2[index], x2[order[:-1]])
            middle_y1 = np.maximum(y1[index], y1[order[:-1]])
            middle_y2 = np.minimum(y2[index], y2[order[:-1]])

            # 特殊情况处理,对左上角和右下角框的坐标进行判断:右下角坐标 - 左上角坐标 > 0 返回对应值,否则返回 0
            middle_w = np.maximum(0.0, middle_x2 - middle_x1 + 1)
            middle_h = np.maximum(0.0, middle_y2 - middle_y1 + 1)
            middle_area = middle_h * middle_w

            # 计算当前置信度最大的框与其余框的iou,将iou大于阈值的框删除
            iou_ratio = middle_area / (areas[index] + areas[order[:-1]] - middle_area)

            # 挑选小于给定阈值的iou继续进行 NMS
            left = np.where(iou_ratio < threshold)

            # 将所有< threshold的索引取出来
            order = order[left]

        return keep
    def plot_bbox(self, dets, c='k'):
        x1 = dets[:, 0]
        y1 = dets[:, 1]
        x2 = dets[:, 2]
        y2 = dets[:, 3]

        plt.plot([x1, x2], [y1, y1], c)
        plt.plot([x1, x1], [y1, y2], c)
        plt.plot([x1, x2], [y2, y2], c)
        plt.plot([x2, x2], [y1, y2], c)
        plt.title(" nms")



if __name__=="__main__":
    boxes = np.array([[100, 100, 250, 250, 0.8],
                      [250, 250, 420, 420, 0.95],
                      [220, 220, 320, 330, 0.92],
                      [100, 100, 210, 210, 0.7],
                      [230, 240, 325, 330, 0.81],
                      [220, 230, 315, 340, 0.9]])
    threshold = 0.7

    s1 = Solution()
    a = s1.nms(boxes, threshold)
    for i in boxes[a]:
        print(f"boxes_nms: {i}")

    # 可视化 NMS 效果
    plt.figure(1)
    ax1 = plt.subplot(1, 2, 1)
    ax2 = plt.subplot(1, 2, 2)

    plt.sca(ax1)
    s1.plot_bbox(boxes, 'k')  # before nms

    keep = a
    plt.sca(ax2)
    s1.plot_bbox(boxes[keep], 'r')  # after nm
    plt.show()
2.2 推导过程
  1. 我们先将所有候选框的置信度排序,因为我们最终是要最大的
  2. 将置信度最大的加入到最终的返回值中
  3. 将其他的候选框和当前置信度最大的框计算iou
  4. 如果iou大于一个阈值,则可删除(说明和置信度大的那个是重叠的)
  5. 将剩下的框重复以上过程
来源

python计算iou以及nms
python实现IOU计算

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/997436.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号