CV

图像检测-上

IOU、mAP、NMS

Posted by 新宇 on July 25, 2020

一、目标检测

目标检测(Object Detection)的任务是找出图像中所有感兴趣的目标,并确定它们的类别和位置。

1. 位置信息的表现形式

  • 目标检测的位置信息一般由两种格式(以图片左上角为原点(0,0)):
    • 1、极坐标表示:(xmin, ymin, xmax, ymax)
      • xmin,ymin:x,y坐标的最小值
      • xmin,ymin:x,y坐标的最大值
    • 2、中心点坐标:(x_center, y_center, w, h)
      • x_center, y_center:目标检测框的中心点坐标
      • w,h:目标检测框的宽、高

2. 常用的开源数据集

2.1 PASCAL VOC数据集

  • PASCAL VOC是目标检测领域的经典数据集。
  • PASCAL VOC包含约10,000张带有边界框的图片用于训练和验证。
  • PASCAL VOC数据集是目标检测问题的一个基准数据集,很多模型都是在此数据集上得到的,
  • 常用的是VOC2007和VOC2012两个版本数据,共20个类别,分别是:
    • 1.人: 人
    • 2.动物: 鸟,猫,牛,狗,马,羊
    • 3.交通工具: 飞机,自行车,船,公共汽车,汽车,摩托车,火车
    • 4.室内: 瓶子,椅子,餐桌,盆栽,沙发,电视/显示器
  • 下载地址:https://pjreddie.com/projects/pascal-voc-dataset-mirror/
  • 目录结构:
    • JPEGImages存放图片文件、
    • Annotations下存放的是xml文件,描述了图片信息
    • ImageSets包含以下4个文件夹:
      • Action下存放的是人的动作(例如running、jumping等等)
      • Layout下存放的是具有人体部位的数据(人的head、hand、feet等等)
      • Segmentation下存放的是可用于分割的数据。
      • Main下存放的是图像物体识别的数据,总共分为20类,这是进行目标检测的重点。该文件夹中的数据对负样本文件进行了描述。

2.2 MS COCO数据集

MS COCO的全称是Microsoft Common Objects in Context,微软于2014年出资标注的Microsoft COCO数据集,与ImageNet竞赛一样,被视为是计算机视觉领域最受关注和最权威的比赛之一。

COCO数据集是一个大型的、丰富的物体检测,分割和字幕数据集。这个数据集以场景理解为目标,主要从复杂的日常场景中截取,图像中的目标通过精确的分割进行位置的标定。图像包括91类目标,328,000影像和2,500,000个label。目前为止目标检测的最大数据集,提供的类别有80 类,有超过33 万张图片,其中20 万张有标注,整个数据集中个体的数目超过150 万个。

3. 常用的评价指标

IOU主要用于单个物体检测评估,而mAP适用于多分类模型的评估

3.1 IOU

在目标检测算法中,IoU(intersection over union,交并比)是目标检测算法中用来评价2个矩形框之间相似度的指标: IoU = 两个矩形框相交的面积 / 两个矩形框相并的面积

import numpy as np

# 定义方法计算IOU

def Iou(box1, box2, wh=False):
    # 判断bbox的表示形式

    if wh == False:
        # 使用极坐标形式表示:直接获取两个bbox的坐标

        xmin1, ymin1, xmax1, ymax1 = box1
        xmin2, ymin2, xmax2, ymax2 = box2
    else:
        # 使用中心点形式表示: 获取两个两个bbox的极坐标表示形式

        # 第一个框左上角坐标

        xmin1, ymin1 = int(box1[0]-box1[2]/2.0), int(box1[1]-box1[3]/2.0)
        # 第一个框右下角坐标

        xmax1, ymax1 = int(box1[0]+box1[2]/2.0), int(box1[1]+box1[3]/2.0)
        # 第二个框左上角坐标

        xmin2, ymin2 = int(box2[0]-box2[2]/2.0), int(box2[1]-box2[3]/2.0)
        # 第二个框右下角坐标

        xmax2, ymax2 = int(box2[0]+box2[2]/2.0), int(box2[1]+box2[3]/2.0)
    # 获取矩形框交集对应的左上角和右下角的坐标(intersection)

    xx1 = np.max([xmin1, xmin2])
    yy1 = np.max([ymin1, ymin2])
    xx2 = np.min([xmax1, xmax2])
    yy2 = np.min([ymax1, ymax2])
    # 计算两个矩形框面积

    area1 = (xmax1-xmin1) * (ymax1-ymin1) 
    area2 = (xmax2-xmin2) * (ymax2-ymin2)
    #计算交集面积

    inter_area = (np.max([0, xx2-xx1])) * (np.max([0, yy2-yy1]))
    #计算交并比

    iou = inter_area / (area1+area2-inter_area+1e-6)
    return iou

假设我们检测结果如下所示,并展示在图像上:

import matplotlib.pyplot as plt
import matplotlib.patches as patches

# 真实框与预测框

True_bbox, predict_bbox = [100, 35, 398, 400], [40, 150, 355, 398]
# bbox是bounding box的缩写

img = plt.imread('dog.jpeg')
fig = plt.imshow(img)
# 将边界框(左上x, 左上y, 右下x, 右下y)格式转换成matplotlib格式:((左上x, 左上y), 宽, 高)
# 真实框绘制

fig.axes.add_patch(plt.Rectangle(
    xy=(True_bbox[0], True_bbox[1]), width=True_bbox[2]-True_bbox[0], height=True_bbox[3]-True_bbox[1],
    fill=False, edgecolor="blue", linewidth=2))
# 预测框绘制

fig.axes.add_patch(plt.Rectangle(
    xy=(predict_bbox[0], predict_bbox[1]), width=predict_bbox[2]-predict_bbox[0], height=predict_bbox[3]-predict_bbox[1],
    fill=False, edgecolor="red", linewidth=2))

# 计算IOU

Iou(True_bbox,predict_bbox)

3.2 mAP(Mean Average Precision)

目标检测问题中的每个图片都可能包含一些不同类别的物体,需要评估模型的物体分类和定位性能。因此,用于图像分类问题的标准指标precision不能直接应用于此。 在目标检测中,mAP是主要的衡量指标。 mAP是多个分类任务的AP的平均值,而AP(average precision)是PR曲线下的面积,所以在介绍mAP之前我们要先得到PR曲线。

AP 是计算某一类 P-R 曲线下的面积,mAP 则是计算所有类别 P-R 曲线下面积的平均值。

4. NMS(非极大值抑制)

  • 非极大值抑制(Non-Maximum Suppression,NMS),顾名思义就是抑制不是极大值的元素。
  • 例如在行人检测中,滑动窗口经提取特征,经分类器分类识别后,每个窗口都会得到一个分数。但是滑动窗口会导致很多窗口与其他窗口存在包含或者大部分交叉的情况。
  • 这时就需要用到NMS来选取那些邻域里分数最高(是行人的概率最大),并且抑制那些分数低的窗口。
  • NMS在计算机视觉领域有着非常重要的应用,如视频目标跟踪、数据挖掘、3D重建、目标识别以及纹理分析等。

4.1 原理

  • NMS的原理是对于预测框的列表B及其对应的置信度S,选择具有最大score的检测框M,将其从B集合中移除并加入到最终的检测结果D中.通常将B中剩余检测框中与M的IoU大于阈值Nt的框从B中移除.重复这个过程,直到B为空。
  • 使用流程:
    • 首先是检测出一系列的检测框
    • 将检测框按照类别进行分类
    • 对同一类别的检测框应用NMS获取最终的检测结果

4.2 NMS的实现方法

import numpy as np
def nms(bboxes, confidence_score, threshold):
    """非极大抑制过程
    :param bboxes: 同类别候选框坐标
    :param confidence: 同类别候选框分数
    :param threshold: iou阈值
    :return:
    """
    # 1、传入无候选框返回空

    if len(bboxes) == 0:
        return [], []
    # 强转数组

    bboxes = np.array(bboxes)
    score = np.array(confidence_score)

    # 取出n个的极坐标点

    x1 = bboxes[:, 0]
    y1 = bboxes[:, 1]
    x2 = bboxes[:, 2]
    y2 = bboxes[:, 3]

    # 2、对候选框进行NMS筛选
    # 返回的框坐标和分数

    picked_boxes = []
    picked_score = []
    # 对置信度进行排序, 获取排序后的下标序号, argsort默认从小到大排序

    order = np.argsort(score)
    areas = (x2 - x1) * (y2 - y1)
    while order.size > 0:
        # 将当前置信度最大的框加入返回值列表中

        index = order[-1]
        #保留该类剩余box中得分最高的一个

        picked_boxes.append(bboxes[index])
        picked_score.append(confidence_score[index])

        # 获取当前置信度最大的候选框与其他任意候选框的相交面积

        x11 = np.maximum(x1[index], x1[order[:-1]])
        y11 = np.maximum(y1[index], y1[order[:-1]])
        x22 = np.minimum(x2[index], x2[order[:-1]])
        y22 = np.minimum(y2[index], y2[order[:-1]])
        # 计算相交的面积,不重叠时面积为0

        w = np.maximum(0.0, x22 - x11)
        h = np.maximum(0.0, y22 - y11)
        intersection = w * h

        # 利用相交的面积和两个框自身的面积计算框的交并比

        ratio = intersection / (areas[index] + areas[order[:-1]] - intersection)
        # 保留IoU小于阈值的box

        keep_boxes_indics = np.where(ratio < threshold)
        # 保留剩余的框

        order = order[keep_boxes_indics]
    # 返回NMS后的框及分类结果  

    return picked_boxes, picked_score
bounding = [(187, 82, 337, 317), (150, 67, 305, 282), (246, 121, 368, 304)]
confidence_score = [0.9, 0.65, 0.8]
threshold = 0.3
picked_boxes, picked_score = nms(bounding, confidence_score, threshold)
print('阈值threshold为:', threshold)
print('NMS后得到的bbox是:', picked_boxes)
print('NMS后得到的bbox的confidences是:', picked_score)

5. 目标检测方法分类

目标检测算法主要分为two-stage(两阶段)和one-stage(单阶段)两类:

5.1 two-stage方法

5.2 one-stage方法