从零实现NMS

文章详细介绍了非极大值抑制(NMS)的实现过程,该算法常用于目标检测中去除重叠的边界框。通过排序置信度,计算IoU(交并比),并依据阈值逐步筛选,直至只剩单个框。提供的PyTorch代码示例展示了NMS的完整流程。

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

说多说少都是泪,被问到NMS如何实现的时候侃侃而谈,但是一旦从零手写就捉襟见肘,往后再学习的时候一定作到从零书写每一块代码。

import torch


# 如果是大框完全包住小框,则为over/Smin
# 1.先对置信度进行排序,2.取最大的置信度与后面的进行iou比较,筛选iou满足条件的(小于阈值的),
# 3.再从筛选后的框中选置信度最大的(前面哪个最大的已经保留到别处了,此时不再参选),与后面剩下的框进行iou比较.
# 以此类推,直到最后一部分只剩下一个框,结束nms!
def iou(box, boxes, isMin=False):
    box_area = (box[2] - box[0]) * (box[3] - box[1])
    boxes_areas = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])

    # 交集
    xx1 = torch.max(box[0], boxes[:, 0])
    yy1 = torch.max(box[1], boxes[:, 1])
    xx2 = torch.min(box[2], boxes[:, 2])
    yy2 = torch.min(box[3], boxes[:, 3])

    w, h = torch.maximum(torch.Tensor([0]), xx2 - xx1), torch.maximum(torch.Tensor([0]), yy2 - yy1)
    over_area = w * h
    if isMin:
        return over_area / torch.min(box_area, boxes_areas)
    else:
        return over_area / (box_area + boxes_areas - over_area)


def nms(boxes, thresh=0.3, isMin=False):
    new_boxes = boxes[boxes[:, 0].argsort(descending=True)]
    # argsort只能返回位置坐标[2,1,0],也就是原boxes根据置信度降序排序的原位置
    # print(new_boxes)
    keep_boxes = []
    while len(new_boxes) > 0:
        _box = new_boxes[0]
        keep_boxes.append(_box)
        if len(new_boxes) > 1:
            _boxes = new_boxes[1:]
            new_boxes = _boxes[iou(_box, _boxes, isMin) < thresh]
        else:
            break

    return torch.stack(keep_boxes)


if __name__ == "__main__":
    boxes = torch.tensor(([0.5, 1, 1, 10, 10], [0.5, 1, 2, 11, 11], [0.6, 1, 1, 5, 5], [0.9, 1, 1, 5, 5]))
    # print(iou(box, boxes))
    print(nms(boxes, 0.1))

### STM32从开始入门教程 #### 工具准备 要实现STM32的第一个项目,首先需要准备好必要的开发环境和硬件设备。根据参考资料[^2],以下是所需的主要工具: - **开发板**:一块支持STM32系列微控制器的开发板。 - **集成开发环境 (IDE)**:推荐使用Keil MDK或者STM32CubeIDE作为主要编程平台。 - **仿真器/调试器**:用于将编写的程序下载到目标板并进行调试。 #### 创建工程项目 在完成上述准备工作之后,按照以下流程创建一个新的STM32工程: 1. 打开所选的IDE软件(例如Keil MDK或STM32CubeIDE)。 2. 新建一个针对特定型号STM32芯片的工程模板。 3. 配置项目的选项设置,比如时钟源的选择。虽然可以通过PLL调整频率以获得更高的性能,但对于初学者来说,默认使用的8MHz内部RC振荡器已经足够满足基本需求[^4]。 #### 编程实践 下面是一个简单的LED闪烁程序示例,它展示了如何控制GPIO端口来点亮外部连接的一个发光二极管: ```c #include "stm32f10x.h" int main(void){ //使能GPIOC外设时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE); //配置PC13为推挽输出模式 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC,&GPIO_InitStruct); while(1){ //设置PC13高电平 GPIO_SetBits(GPIOC,GPIO_Pin_13); Delay_ms(500); //设置PC13低电平 GPIO_ResetBits(GPIOC,GPIO_Pin_13); Delay_ms(500); } } //延时函数定义 void Delay_ms(u16 nms){ u32 j,i; for(i=nms;i>0;i--) for(j=11999;j>0;j--); } ``` 此代码片段实现了通过不断改变指定引脚的状态从而让接在其上的LED灯周期性亮灭的效果。其中包含了几个重要部分:初始化系统时钟、设定目标IO口的工作方式以及循环执行状态切换逻辑。 #### 总结 综上所述,对于想要了解如何基于STM32构建首个实际应用的人来说,理解单片机的基本概念及其架构是非常重要的起点[^3]。与此同时,熟悉整个软硬件搭建过程也是不可或缺的一环。以上介绍的内容涵盖了从安装必要组件直至编写简单应用程序的所有关键环节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值