目标检测(Object Detection)

文章介绍了目标检测任务,包括模型能检测的物体类型和位置信息的表示,如极坐标和中心点坐标。IoU是评估检测框与真实框匹配程度的指标,而NMS用于消除重叠检测框,保留最佳结果。文章提供了NMS的原理和实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

        ⽬标检测中能检测出来的物体取决于当前任务(数据集)需要检测的物体 有哪些。假设我们的⽬标检测模型定位是检测动物(⽜、⽺、猪、狗、猫 五种结果),那么模型对任何⼀张图⽚输出结果不会输出鸭⼦、书籍等其 它类型结果。

        ⽬标检测的位置信息⼀般由两种格式(以图⽚左上⻆为原点(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:⽬标检测框的宽、⾼

        假设在下⾯的图像中进⾏检测:

IOU

        在⽬标检测算法中,IoU(intersection over union,交并⽐)是⽬标检测 算法中⽤来评价2个矩形框之间相似度的指标:

        IoU = 两个矩形框相交的⾯积 / 两个矩形框相并的⾯积, 如下图所示:

 

        那我们就可以通过预测结果与真实结果之间的交并⽐来衡量两者之间的相 似度。⼀般情况下对于检测框的判定都会存在⼀个阈值,也就是 IoU 的 阈值,⼀般可以设置当 IoU 的值⼤于 0.5 的时候,则可认为检测到⽬标物体。

实现⽅法:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
# 定义⽅法计算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]-box1[3]/2.0)
        # 第⼆个框右下⻆坐标
        xmax2, ymax2 = int(box2[0]+box2[2]/2.0), int(box2[1]+box1[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
# 真实框与预测框
# [xmin,ymin:x,y坐标的最⼩值xmin,ymin:x,y坐标的最⼤值]
True_bbox, predict_bbox = [10, 25, 350, 260], [40, 150, 355,398]
# bbox是bounding box的缩写
img = plt.imread('E:/1.jpg')
fig = plt.imshow(img)
# 将边界框(左上x, 左上y, 右下x, 右下y)格式转换成matplotlib格式:(
# 真实框绘制
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(True_bbox,predict_bbox)

 NMS(⾮极⼤值抑制)

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

        在⽬标检测中,NMS的⽬的就是要去除冗余的检测框,保留最好的⼀个, 如下图所示:

        NMS的原理是对于预测框的列表B及其对应的置信度S,选择具有最⼤

        score的检测框M,将其从B集合中移除并加⼊到最终的检测结果D中.通常将 B中剩余检测框中与M的IoU⼤于阈值Nt的框从B中移除.重复这个过程,直 到B为空。

使⽤流程如下图所示:

        ⾸先是检测出⼀系列的检测框

        将检测框按照类别进⾏分类

        对同⼀类别的检测框应⽤NMS获取最终的检测结果

        

        通过⼀个例⼦看些NMS的使⽤⽅法,假设定位⻋辆,算法就找出了⼀系列的矩形框,我们需要判别哪些矩形框是没⽤的,需要使⽤NMS的⽅法来实现。

假设现在检测窗⼝有:A、B、C、D、E 5个候选框,接下来进⾏迭代计 算:

        第⼀轮:因为B是得分最⾼的,与B的IoU>0.5删除。A,CDE中现在 与B计算IoU,DE结果>0.5,剔除DE,B作为⼀个预测结果,有个检 测框留下B,放⼊集合

        第⼆轮:A的得分最⾼,与A计算IoU,C的结果>0.5,剔除C,A作 为⼀个结果 最终结果为在这个5个中检测出了两个⽬标为A和B。

单类别的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)

返回结果:

        阈值threshold为: 0.3

        NMS后得到的bbox是: [array([187, 82, 337, 317])]

        NMS后得到的bbox的confidences是: [0.9]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XMM-struggle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值