目标检测中的非最大值抑制算法
计算机视觉是人工智能的一个重要领域,它可以识别和理解图像和场景。
它包括图像识别、目标检测、图像分割、图像生成、图像超分辨率等多个子领域。由于大量的实际用例,目标检测可能应用地最广。
目标检测
目标检测是指计算机系统定位图像中的目标并识别每个目标的能力。目标检测已广泛应用于人脸检测、车辆检测、行人计数、安全系统和自动驾驶汽车。
目标检测模型从端到端学习范式的发展中受益匪浅:建议、特征和分类器成为一个神经网络,使一般目标检测的结果提高了两倍[1]通常,所有现代目标检测模型都遵循三个步骤:
1. 建议窗口的搜索空间(通过滑动窗口或使用建议的稀疏窗口)。
2. 使用分类器/回归器对窗口评分。
3. 组合可能属于同一对象的窗口。
最后一步称为“非最大抑制”
边界框
在目标检测中,我们通常使用边界框来描述目标在图像中的空间位置。
边界框是一个矩形,使用左上角和右下角坐标绘制。另一种常用的边界框表示法包含矩形的中心以及矩形的高度和宽度。
非最大值算法(NMS)
可以使用以下步骤解释该算法:
输入:边界框列表以及类名称和检测到的每个对象的输出概率。
1. 删除输出概率得分小于指定阈值的边界框。
2. 按输出概率的降序排列剩余边界框的列表。
3. 遍历已排序的边界框列表,直到至少剩下一个元素。
4. 从列表中删除第一个边界框,并将其标记为“当前元素”。此外,检查交并比(IOU)。如果IOU高于指定的阈值,则从列表中删除该元素,并将当前元素附加到“最终列表”中
5. 重复步骤3和4。
6. 返回“最终列表”
NMS算法试运行
假设下面的图像(图1)包含两条狗(左一条:Maya,右一条:Zoro),我们有一个对象检测模型,可以区分图像中的Maya和Zoro。
在使用上图对我们的目标检测模型(无NMS)进行推断时,我们将得到如图2所示的输出。在这里,我们可以看到,我们在单个对象上得到了多个具有各自概率分数的边界框。
我们的目标是为对象选择最合适的边界框。换句话说,我们必须从概率为0.94、0.68和0.47的三个框中选择一个Maya边界框。同样,我们也必须从概率为0.9和0.58的两个边界框中找到Zoro的最佳边界框。
根据算法,我们将首先丢弃所有概率分数低于指定阈值的边界框。例如,如果我们将阈值设置为0.5,我们将丢弃Maya概率为0.47的边界框。
此外,我们将找到概率得分最高的边界框,并将其IOU与同类的所有其他边界框进行检查。如果IOU高于阈值(表示相同的对象),则丢弃概率分数较低的边界框。
同样,我们将对图像中所有检测到的对象执行以下步骤。最终输出如图3所示。
代码
首先,我们将初始化概率置信阈值和IOU阈值。例如,如果一个边界框的概率低于概率置信阈值,那么我们将丢弃该边界框。同样,如果IOU分数高于定义的阈值,我们不会考虑输出概率低的边界框。
import cv2 class NMS: def __init__(self) -> None: self.conf = 0.5 self.iou_threshsold = 0.4
下面截取的代码中的IOU函数计算两个区域的IOU。IOU是两个区域的相交面积与两个区域的并集的比率。在IOU函数中,bboxes1和bboxes2是一个包含以下四个元素的列表:
[ X(top-left), Y(top-left), X(bottom-right), Y(bottom-right) ]
def IOU(self, bboxes1, bboxes2): bboxes1 = [int(i) for i in bboxes1] bboxes2= [int(i) for i in bboxes2] xA = max(bboxes1[0], bboxes2[0]) yA = max(bboxes1[1], bboxes2[1]) xB = min(bboxes1[2], bboxes2[2]) yB = min(bboxes1[3], bboxes2[3]) intersection_area = max(0, xB - xA + 1) * max(0, yB - yA + 1) box1_area = (bboxes1[2] - bboxes1[0] + 1) * (bboxes1[3] - bboxes1[1] + 1) box2_area = (bboxes2[2] - bboxes2[0] + 1) * (bboxes2[3] - bboxes2[1] + 1) iou = intersection_area / float(box1_area + box2_area - intersection_area) return iou
下面的代码在图像上绘制边界框,并将概率分数放在框的顶部。参数“images”是图像对象,“bboxes_list”包含检测到的对象的坐标、类和概率输出。
bboxes_list = [class, X(top-left), Y(top-left), X(bottom-right), Y(bottom-right), output_probability] Sample values: 0 187 90 586 607 0.94 0 120 116 600 370 0.68 1 511 185 961 418 0.58 0 340 145 568 478 0.47 1 524 70 920 565 0.92
def draw_overlay(self, image, bboxes_list): overlay_color = { '0' : (0, 255, 0), '1' : (255, 0, 0) } overlay_thickness = 3 font = cv2.FONT_HERSHEY_SIMPLEX for coord in bboxes_list: class_name = coord[0] start_point = (int(coord[1]), int(coord[2])) end_point = (int(coord[3]), int(coord[4])) prob = float(coord[5]) text_start_point = (int(coord[1]), int(coord[2]) - 10) image = cv2.rectangle(image, start_point, end_point, overlay_color[class_name], overlay_thickness) image = cv2.putText(image, str(prob), text_start_point, font, 0.8, overlay_color[class_name], overlay_thickness - 1, cv2.LINE_AA) cv2.imshow("im", image) cv2.waitKey(0) cv2.destroyAllWindows()
以下函数是上述NMS算法的实现。此函数用于在应用非最大值抑制算法后返回所需的边界框。
def nms(self, image, bboxes_list): req_bboxes, final_boxes = [], [] for coord in bboxes_list: prob = float(coord[5]) if prob > self.conf: req_bboxes.append(coord) # sorting the bounding boxes based on probability score bboxes_sorted = sorted(req_bboxes, reverse=True, key=lambda x: x[5]) while len(bboxes_sorted) > 0: # removing the best probability bounding box box = bboxes_sorted.pop(0) for b in bboxes_sorted: # comparing with the same class if box[0] == b[0]: iou = self.IOU(box[1:-1], b[1:-1]) if iou >= self.iou_threshsold: # if IOU is large then discard the box with lowest probability bboxes_sorted.remove(b) print(len(bboxes_sorted)) final_boxes.append(box) return final_boxes
以下是NMS类的驱动程序代码。我们首先读取coordinates.txt获取边界框的坐标和其他详细信息;然后,我们应用NMS算法来获得所需的边界框。
if __name__ == "__main__": image = cv2.imread("zoraya.jpg") with open("coordinates.txt", 'r') as f: data = f.readlines() data = [i[:-1].split(' ') for i in data] obj = NMS() obj.draw_overlay(image, data) final_boxes = obj.nms(image, data) obj.draw_overlay(image, final_boxes)
coordinates.txt 0 187 90 586 607 0.94 0 120 116 600 370 0.68 1 511 185 961 418 0.58 0 340 145 568 478 0.47 1 524 70 920 565 0.92
结论
本文概述了对非最大值抑制算法的需求以及python实现。此外,我们还使用一个图像示例解释了该算法。
原文标题:目标检测中的非最大值抑制算法
-
免疫检查点抑制剂的获得性耐药机制
2022-07-04 -
AI算法影像时代:苹果的对手,变了
2022-04-27 -
算法的“有毒泡泡”,当真可以戒掉吗?
2022-04-07 -
新的充电算法可以延长电动汽车的电池寿命
2022-03-30 -
详解JVM的垃圾回收算法和垃圾回收器
2022-03-22 -
沙特阿拉伯抑制石油出口以应对价格下跌
2022-03-05 -
“高”油价已经在抑制需求
2022-03-01 -
对网络暴力Say NO!AI算法如何辨“好坏”?
2022-02-25 -
免疫检查点抑制剂的慢性免疫毒性
2022-02-09 -
百度Apollo7.0 规划算法框架解析
2022-02-07 -
电动车不会很快抑制石油需求
2022-01-29 -
低油价抑制了开发新型喷气燃料的动力
2022-01-27 -
炼油厂提高产量,但Irma可能抑制需求
2022-01-26 -
脂肪生成抑制剂药物开发的机遇与挑战
2022-01-20 -
非最大抑制算法是如何工作的?
2022-01-20