解决图像目标检测两框重叠问题

2023-11-09

1 问题现象

使用yolo v3 等目标检测模型训练自己数据集,预测图片时出现问题: 两框重叠,如下图所示:对于同样一辆汽车,模型反复的标记。

在这里插入图片描述
在这里插入图片描述

2 解决办法

解决办法就是:非极大值抑制(Non-Maximum Suppression)

3 Non-Maximum Suppression 原理

3.1 什么是非极大值抑制

非极大值抑制,简称为NMS算法,英文为Non-Maximum Suppression。其思想是搜素局部最大值,抑制极大值。NMS算法在不同应用中的具体实现不太一样,但思想是一样的。非极大值抑制,在计算机视觉任务中得到了广泛的应用,例如边缘检测、人脸检测、目标检测(DPM,YOLO,SSD,Faster R-CNN)等。

3.2 为什么要用非极大值抑制

以目标检测为例:目标检测的过程中在同一目标的位置上会产生大量的候选框,这些候选框相互之间可能会有重叠,此时我们需要利用非极大值抑制找到最佳的目标边界框,消除冗余的边界框。Demo如下图:

在这里插入图片描述
左图是人脸检测的候选框结果,每个边界框有一个置信度得分(confidence score),如果不使用非极大值抑制,就会有多个候选框出现。右图是使用非极大值抑制之后的结果,符合我们人脸检测的预期结果。

3.3 如何使用非极大值抑制

前提:目标边界框列表及其对应的置信度得分列表,设定阈值,阈值用来删除重叠较大的边界框。
IoU:intersection-over-union,即两个边界框的交集部分除以它们的并集。

非极大值抑制的流程如下:

  1. 根据置信度得分进行排序
  2. 选择置信度最高的比边界框添加到最终输出列表中,将其从边界框列表中删除
  3. 计算所有边界框的面积
  4. 计算置信度最高的边界框与其它候选框的IoU。
  5. 删除IoU大于阈值的边界框
  6. 重复上述过程,直至边界框列表为空。

Python代码如下:

#!/usr/bin/env python
# _*_ coding: utf-8 _*_


import cv2
import numpy as np


"""
    Non-max Suppression Algorithm

    @param list  Object candidate bounding boxes
    @param list  Confidence score of bounding boxes
    @param float IoU threshold

    @return Rest boxes after nms operation
"""
def nms(bounding_boxes, confidence_score, threshold):
    # If no bounding boxes, return empty list
    if len(bounding_boxes) == 0:
        return [], []

    # Bounding boxes
    boxes = np.array(bounding_boxes)

    # coordinates of bounding boxes
    start_x = boxes[:, 0]
    start_y = boxes[:, 1]
    end_x = boxes[:, 2]
    end_y = boxes[:, 3]

    # Confidence scores of bounding boxes
    score = np.array(confidence_score)

    # Picked bounding boxes
    picked_boxes = []
    picked_score = []

    # Compute areas of bounding boxes
    areas = (end_x - start_x + 1) * (end_y - start_y + 1)

    # Sort by confidence score of bounding boxes
    order = np.argsort(score)

    # Iterate bounding boxes
    while order.size > 0:
        # The index of largest confidence score
        index = order[-1]

        # Pick the bounding box with largest confidence score
        picked_boxes.append(bounding_boxes[index])
        picked_score.append(confidence_score[index])

        # Compute ordinates of intersection-over-union(IOU)
        x1 = np.maximum(start_x[index], start_x[order[:-1]])
        x2 = np.minimum(end_x[index], end_x[order[:-1]])
        y1 = np.maximum(start_y[index], start_y[order[:-1]])
        y2 = np.minimum(end_y[index], end_y[order[:-1]])

        # Compute areas of intersection-over-union
        w = np.maximum(0.0, x2 - x1 + 1)
        h = np.maximum(0.0, y2 - y1 + 1)
        intersection = w * h

        # Compute the ratio between intersection and union
        ratio = intersection / (areas[index] + areas[order[:-1]] - intersection)

        left = np.where(ratio < threshold)
        order = order[left]

    return picked_boxes, picked_score


# Image name
image_name = 'nms.jpg'

# Bounding boxes
bounding_boxes = [(187, 82, 337, 317), (150, 67, 305, 282), (246, 121, 368, 304)]
confidence_score = [0.9, 0.75, 0.8]

# Read image
image = cv2.imread(image_name)

# Copy image as original
org = image.copy()

# Draw parameters
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 1
thickness = 2

# IoU threshold
threshold = 0.4

# Draw bounding boxes and confidence score
for (start_x, start_y, end_x, end_y), confidence in zip(bounding_boxes, confidence_score):
    (w, h), baseline = cv2.getTextSize(str(confidence), font, font_scale, thickness)
    cv2.rectangle(org, (start_x, start_y - (2 * baseline + 5)), (start_x + w, start_y), (0, 255, 255), -1)
    cv2.rectangle(org, (start_x, start_y), (end_x, end_y), (0, 255, 255), 2)
    cv2.putText(org, str(confidence), (start_x, start_y), font, font_scale, (0, 0, 0), thickness)

# Run non-max suppression algorithm
picked_boxes, picked_score = nms(bounding_boxes, confidence_score, threshold)

# Draw bounding boxes and confidence score after non-maximum supression
for (start_x, start_y, end_x, end_y), confidence in zip(picked_boxes, picked_score):
    (w, h), baseline = cv2.getTextSize(str(confidence), font, font_scale, thickness)
    cv2.rectangle(image, (start_x, start_y - (2 * baseline + 5)), (start_x + w, start_y), (0, 255, 255), -1)
    cv2.rectangle(image, (start_x, start_y), (end_x, end_y), (0, 255, 255), 2)
    cv2.putText(image, str(confidence), (start_x, start_y), font, font_scale, (0, 0, 0), thickness)

# Show image
cv2.imshow('Original', org)
cv2.imshow('NMS', image)
cv2.waitKey(0)

3.4 效果

具体解决办法就是减小 IoU threshold (IoU 阈值)

IoU阈值为0.6的时候:
在这里插入图片描述
IoU阈值为0.4的时候:

在这里插入图片描述

4 参考资料:

  • 《非极大值抑制(Non-Maximum Suppression)》:https://zhuanlan.zhihu.com/p/37489043
  • 《训练自己数据集,预测图片时出现问题》https://github.com/qqwweee/keras-yolo3/issues/354
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

解决图像目标检测两框重叠问题 的相关文章

  • 简单报价单模板_科普:小程序定制和模板开发有什么区别?

    小程序常见的开发方式有三种 自己源代码开发 找外包团队定制开发 使用小程序模板类开发工具 对于不懂技术的小白来说 源代码开发困难太大 那么后两种方式该如何选择呢 它们到底都有什么区别 接下来就跟大家科普一下这些知识 1 成本不同 小程序模板

随机推荐

  • ClickHouse(四)表引擎

    官网 表引擎 ClickHouse文档 表引擎在 ClickHouse 中的作用十分关键 直接决定了数据如何存储和读取 是否支持并发读写 是否支持 index 支持的 query 种类 是否支持主备复制等 1 表引擎概述 ClickHous
  • unity3D之动态的创建球体游戏对象js

    function OnGUI if GUILayout Button 创建立方体 GUILayout Height 50 var objCube GameObject CreatePrimitive PrimitiveType Sphere
  • JS 插入排序

    算法描述 插入排序的算法描述是一种简单直观的排序算法 它的工作原理是通过构建有序序列 对于未排序数据 在已排序序列中从后向前扫描 找到相应位置并插入 一般来说 插入排序都采用in place在数组上实现 具体算法描述如下 从第一个元素开始
  • 【OpenCV4】拉普拉斯算子提取边缘 cv::Laplacian() 用法详解和代码示例(c++)

    作用原理 拉普拉斯算子可以用于边缘检测 同时该算子不具有方向性 可以同时检测到 X 方向和 Y 方向的边缘 综合后检测出图像的边缘 即拉普拉斯算子是 各向同性 的 这在很多情况下是一个优点 因为我们一般来说会同时关注 X 方向和 Y 方向的
  • xcode4的环境变量,Build Settings参数,workspace及联编设置

    一 xcode4中的环境变量 BUILT PRODUCTS DIR build成功后的 最终产品路径 可以在Build Settings参数的Per configuration Build Products Path项里设置 TARGET
  • 英语台词--冰与火之歌

    Your roof your rules 你的地盘 你做主
  • C++基础——常引用与类型转换详解

    通过前两篇对引用的讲解 想必大家都对引用有了较为深刻的理解 没看过的小伙伴可以去看看 C 基础 引用讲解1 C 基础 引用讲解2 目录 一 常引用 1 权限的平移 2 权限的放大 3 权限的缩小 二 引用的类型转换 一 常引用 这次我来说一
  • 史上最全的Python兼职接单挣钱教程,十分详细(附基础教程)

    学python编程能挣钱吗 怎么挣钱 答案是可以的 有两点我都赚到钱的方法 接私活和自媒体 一 赚钱第一种方式 接私活 刚学会python那会 就有认识的朋友介绍做一个网站的私活 当时接单赚了4K 仅代表本人个人收益 后又自己接过开发网站后
  • A2W和W2A 很好的多字节和宽字节字符串的转换宏

    分享一下我老师大神的人工智能教程 零基础 通俗易懂 http blog csdn net jiangjunshow 也欢迎大家转载本篇文章 分享知识 造福人民 实现我们中华民族伟大复兴 作者 朱金灿 来源 http blog csdn ne
  • github CPlusPlusThings 基础学习笔记

    来源 Light City CPlusPlusThings C 那些事 github com 目录 const static this inline sizeof 函数指针 纯虚函数和抽象类 vptr vtable virtual vola
  • Dell R410服务器查看系统raid级别

    注意 raid 如果有问题 会导致机器网络自动断开连接 连不上机器 1 查看inux 怎么查看raid做的 是几 软件raid 只能通过Linux系统本身来查看 cat proc mdstat 可以看到raid级别 状态等信息 硬件raid
  • 前端JSON数据传值到后端接收方式

    前端发送的数据 前端JS请求 1 demo为JSON格式数据 2 let para 3 dataJ JSON stringfiy demo 4 5 这一段是Vue封装的方法 本质就是一条url 6 this http post webRoo
  • js去除url中的localtion.search部分

    localtion search是url中拼接的参数部分 js去除url中的localtion search部分包括 部分 if location search var old url window location href var ne
  • Java算法结构---------线性表

    线性表相关介绍 线性表是一种最常用 最简单的线性结构 线性表的主要操作特定是 可以在任意位置上插入一个数据元素和删除一个数据元素 线性表可以用顺序存储结构和链式存储结构实现 用顺序存储结构实现的线性表称为顺序表 用链式存储结构实现的线性表称
  • node.js(第七章)登录鉴权的方式一Cookie&Session

    1 Cookie Session HTTP 无状态 我们知道 HTTP 是无状态的 也就是说 HTTP 请求方和响应方间无法维护状态 都是一次性的 它不知道前后的请求都发生了什么 但有的场景下 我们需要维护状态 最典型的 一 个用户登陆CS
  • Linux基础笔记15

    文本处理 wc 用于统计文件的字节数 单词数 行数等信息 并将统计结果标准输出到终端 w 统计单词数 c 统计字节数 l 统计行数 m 统计字符数 L 显示最长行的长度 help 显示帮助信息 version 显示版本信息 root iZr
  • PHP静态绑定知识点学习记录

    最近在学习JAVA基础中关于静态方法的知识 回想起PHP可以使用self 或者static 两种方式来进行静态方法的调用 有些忘记两者的差异 因此 做一下学习记录 后期绑定 的意思是说 static 不再被解析为定义当前方法所在的类 而是在
  • Linux 学习笔记1 安装linux详细教程

    系统 CentOS 8 1 1911 x86 64 dvd1 软件 VMware Workstation Pro 16 安装centos VM安装的步骤 1 去BIOS里修改设置开启以常交 f2 f10 2 安装虚拟机软件 vm15 5 演
  • QT(qCompress和qUncompress)与zlib(compress和uncompress)相互调用

    因为QT也是用zlib库的 所以理论上数据是可以直接互通的 但现实是残酷的 通过对qCompress和compress压缩的数据进行打印 可以知道qCompress比compress的数据长四个字节 而这四个字节的内容则未压缩前的数据长度
  • 解决图像目标检测两框重叠问题

    文章目录 1 问题现象 2 解决办法 3 Non Maximum Suppression 原理 3 1 什么是非极大值抑制 3 2 为什么要用非极大值抑制 3 3 如何使用非极大值抑制 3 4 效果 4 参考资料 1 问题现象 使用yolo