NMS详解及pytorch实现:hard-nms(diou\overlap\merge\batched),soft-nms

2023-05-16

文章目录

  • NMS详解及pytorch实现:hard-nms(diou\overlap\merge\batched),soft-nms
    • 1 简介
    • 2 原理
    • 3 实现
      • 3.1 伪代码
      • 3.2 pytorch源码
      • 3.3 知识点
    • 参考资料

NMS详解及pytorch实现:hard-nms(diou\overlap\merge\batched),soft-nms

1 简介

非极大值抑制算法(Non-maximum suppression, NMS)是有anchor系列目标检测的标配,如今大部分的One-StageTwo-Stage算法在推断(Inference)阶段都使用了NMS作为网络的最后一层,例如YOLOv3、SSD、Faster-RCNN等。

当然NMS在目前最新的anchor-free(https://www.cnblogs.com/yumoye/p/11022800.html)目标检测算法中(CornerNet、CenterNet等)并不是必须的,对这种检测算法提升的精度也有限,但是这并不影响我们学习NMS。

NMS的本质是搜索局部极大值,抑制非极大值元素,在目标检测中,我们经常将其用于消除多余的检测框(从左到右消除了重复的检测框,只保留当前最大confidence的检测框):

《手撕非极大值抑制算法NMS与soft-NMS》

NMS有很多种变体,最为常见的Hard-NMS,我们通常所说的NMS就是指Hard-NMS,还有另外一种NMS叫做Soft-NMS,是Hard-NMS的变体,还有一些其他的一些变体(batched\diou\or\and\merge-nms)。

2 原理

最为常见的,也就是咱们提到的nms及为hard-nms,所以这里将以hard-nms入手,剖析内部操作原理。

  • 选取当前类别box中scores最大的那一个,记为current_box,并保留它(为什么保留它,因为它预测出当前位置有物体的概率最大啊,对于我们来说当前confidence越大说明当前box中包含物体的可能行就越大)
  • 计算current_box与其余的box的IOU
  • 如果其IOU大于我们设定的阈值,那么就舍弃这些boxes(由于可能这两个box表示同一目标,因此这两个box的IOU就比较大,会超过我们设定的阈值,所以就保留分数高的那一个)
  • 从最后剩余的boxes中,再找出最大scores的那一个(之前那个大的已经保存到输出的数组中,这个是从剩下的里面再挑一个最大的),如此循环往复

3 实现

3.1 伪代码

在这里插入图片描述

各种nms特点一句话总结:

Hard-nms–直接删除相邻的同类别目标,密集目标的输出不友好。

Soft-nms–改变其相邻同类别目标置信度(有关iou的函数),后期通过置信度阈值进行过滤,适用于目标密集的场景。

or-nms–hard-nms的非官方实现形式,只支持cpu。

vision-nms–hard-nms的官方实现形式(c函数库),可支持gpu(cuda),只支持单类别输入。

vision-batched-nms–hard-nms的官方实现形式(c函数库),可支持gpu(cuda),支持多类别输入。

and-nms–在hard-nms的逻辑基础上,增加是否为单独框的限制,删除没有重叠框的框(减少误检)。

merge-nms–在hard-nms的基础上,增加保留框位置平滑策略(重叠框位置信息求解平均值),使框的位置更加精确。

diou-nms–在hard-nms的基础上,用diou替换iou,里有参照diou的优势。

3.2 pytorch源码

nms实现函数:

def non_max_suppression(prediction, conf_thres=0.5, nms_thres=0.5, multi_cls=True, method='vision'):
    """
    Removes detections with lower object confidence score than 'conf_thres'
    Non-Maximum Suppression to further filter detections.
    Returns detections with shape:
        (x1, y1, x2, y2, object_conf, conf, class)
    """
    # NMS methods https://github.com/ultralytics/yolov3/issues/679 'or', 'and', 'merge', 'vision', 'vision_batch'

    # Box constraints
    min_wh, max_wh = 2, 4096  # (pixels) minimum and maximium box width and height

    output = [None] * len(prediction)
    for image_i, pred in enumerate(prediction):
        # Apply conf constraint
        pred = pred[pred[:, 4] > conf_thres]

        # Apply width-height constraint
        pred = pred[(pred[:, 2:4] > min_wh).all(1) & (pred[:, 2:4] < max_wh).all(1)]

        # If none remain process next image
        if len(pred) == 0:
            continue

        # Compute conf
        torch.sigmoid_(pred[..., 5:])
        pred[..., 5:] *= pred[..., 4:5]  # conf = obj_conf * cls_conf

        # Box (center x, center y, width, height) to (x1, y1, x2, y2)
        box = xywh2xyxy(pred[:, :4])

        # Detections matrix nx6 (xyxy, conf, cls)
        if multi_cls or conf_thres < 0.01:
            i, j = (pred[:, 5:] > conf_thres).nonzero().t()
            pred = torch.cat((box[i], pred[i, j + 5].unsqueeze(1), j.float().unsqueeze(1)), 1)
        else:  # best class only
            conf, j = pred[:, 5:].max(1)
            pred = torch.cat((box, conf.unsqueeze(1), j.float().unsqueeze(1)), 1)

        # Apply finite constraint
        pred = pred[torch.isfinite(pred).all(1)]

        # Get detections sorted by decreasing confidence scores
        pred = pred[pred[:, 4].argsort(descending=True)]

        # Batched NMS
        if method == 'vision_batch':
            output[image_i] = pred[torchvision.ops.boxes.batched_nms(pred[:, :4], pred[:, 4], pred[:, 5], nms_thres)]
            continue

        # All other NMS methods
        det_max = []
        cls = pred[:, -1]
        for c in cls.unique():
            dc = pred[cls == c]  # select class c
            n = len(dc)
            if n == 1:
                det_max.append(dc)  # No NMS required if only 1 prediction
                continue
            elif n > 500:
                dc = dc[:500]  # limit to first 500 boxes: https://github.com/ultralytics/yolov3/issues/117

            if method == 'vision':
                det_max.append(dc[torchvision.ops.boxes.nms(dc[:, :4], dc[:, 4], nms_thres)])

            elif method == 'or':  # default
                while dc.shape[0]:
                    det_max.append(dc[:1])  # save highest conf detection
                    if len(dc) == 1:  # Stop if we're at the last detection
                        break
                    iou = bbox_iou(dc[0], dc[1:])  # iou with other boxes
                    dc = dc[1:][iou < nms_thres]  # remove ious > threshold

            elif method == 'and':  # requires overlap, single boxes erased
                while len(dc) > 1:
                    iou = bbox_iou(dc[0], dc[1:])  # iou with other boxes
                    if iou.max() > 0.5:
                        det_max.append(dc[:1])
                    dc = dc[1:][iou < nms_thres]  # remove ious > threshold

            elif method == 'merge':  # weighted mixture box
                while len(dc):
                    if len(dc) == 1:
                        det_max.append(dc)
                        break
                    i = bbox_iou(dc[0], dc) > nms_thres  # iou with other boxes
                    weights = dc[i, 4:5]
                    dc[0, :4] = (weights * dc[i, :4]).sum(0) / weights.sum()
                    det_max.append(dc[:1])
                    dc = dc[i == 0]
			elif method == 'diounms':  # use diou 
                while dc.shape[0]:
                    det_max.append(dc[:1])  # save highest conf detection
                    if len(dc) == 1:  # Stop if we're at the last detection
                        break
                    diou = bbox_iou(dc[0], dc[1:],DIoU=True)  # diou with other boxes
                    dc = dc[1:][diou < nms_thres]  # remove dious > threshold
            
            elif method == 'soft':  # soft-NMS https://arxiv.org/abs/1704.04503
                sigma = 0.5  # soft-nms sigma parameter
                while len(dc):
                    if len(dc) == 1:
                        det_max.append(dc)
                        break
                    det_max.append(dc[:1])
                    iou = bbox_iou(dc[0], dc[1:])  # iou with other boxes
                    dc = dc[1:]
                    dc[:, 4] *= torch.exp(-iou ** 2 / sigma)  # decay confidences
                    dc = dc[dc[:, 4] > conf_thres]  # https://github.com/ultralytics/yolov3/issues/362

        if len(det_max):
            det_max = torch.cat(det_max)  # concatenate
            output[image_i] = det_max[(-det_max[:, 4]).argsort()]  # sort

    return output

iou计算函数:

def bbox_iou(box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=False):
    # Returns the IoU of box1 to box2. box1 is 4, box2 is nx4
    box2 = box2.t()

    # Get the coordinates of bounding boxes
    if x1y1x2y2:  # x1, y1, x2, y2 = box1
        b1_x1, b1_y1, b1_x2, b1_y2 = box1[0], box1[1], box1[2], box1[3]
        b2_x1, b2_y1, b2_x2, b2_y2 = box2[0], box2[1], box2[2], box2[3]
    else:  # x, y, w, h = box1
        b1_x1, b1_x2 = box1[0] - box1[2] / 2, box1[0] + box1[2] / 2
        b1_y1, b1_y2 = box1[1] - box1[3] / 2, box1[1] + box1[3] / 2
        b2_x1, b2_x2 = box2[0] - box2[2] / 2, box2[0] + box2[2] / 2
        b2_y1, b2_y2 = box2[1] - box2[3] / 2, box2[1] + box2[3] / 2

    # Intersection area
    inter = (torch.min(b1_x2, b2_x2) - torch.max(b1_x1, b2_x1)).clamp(0) * \
            (torch.min(b1_y2, b2_y2) - torch.max(b1_y1, b2_y1)).clamp(0)

    # Union Area
    w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1
    w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1
    union = (w1 * h1 + 1e-16) + w2 * h2 - inter

    iou = inter / union  # iou
    if GIoU or DIoU or CIoU:
        cw = torch.max(b1_x2, b2_x2) - torch.min(b1_x1, b2_x1)  # convex (smallest enclosing box) width
        ch = torch.max(b1_y2, b2_y2) - torch.min(b1_y1, b2_y1)  # convex height
        if GIoU:  # Generalized IoU https://arxiv.org/pdf/1902.09630.pdf
            c_area = cw * ch + 1e-16  # convex area
            return iou - (c_area - union) / c_area  # GIoU
        if DIoU or CIoU:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1
            # convex diagonal squared
            c2 = cw ** 2 + ch ** 2 + 1e-16
            # centerpoint distance squared
            rho2 = ((b2_x1 + b2_x2) - (b1_x1 + b1_x2)) ** 2 / 4 + ((b2_y1 + b2_y2) - (b1_y1 + b1_y2)) ** 2 / 4
            if DIoU:
                return iou - rho2 / c2  # DIoU
            elif CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47
                v = (4 / math.pi ** 2) * torch.pow(torch.atan(w2 / h2) - torch.atan(w1 / h1), 2)
                with torch.no_grad():
                    alpha = v / (1 - iou + v)
                return iou - (rho2 / c2 + v * alpha)  # CIoU

    return iou

pytorch外接c函数库:

#多类别nms时,需要分类别灌入。
#调用方式:torchvision.ops.boxes.nms()
def nms(boxes, scores, iou_threshold):
    """
    Performs non-maximum suppression (NMS) on the boxes according
    to their intersection-over-union (IoU).

    NMS iteratively removes lower scoring boxes which have an
    IoU greater than iou_threshold with another (higher scoring)
    box.

    Parameters
    ----------
    boxes : Tensor[N, 4])
        boxes to perform NMS on. They
        are expected to be in (x1, y1, x2, y2) format
    scores : Tensor[N]
        scores for each one of the boxes
    iou_threshold : float
        discards all overlapping
        boxes with IoU < iou_threshold

    Returns
    -------
    keep : Tensor
        int64 tensor with the indices
        of the elements that have been kept
        by NMS, sorted in decreasing order of scores
    """
    _C = _lazy_import()
    return _C.nms(boxes, scores, iou_threshold)
#多类别nms时,不需要分类别的灌入,内部已通过idxs区分实现。
#调用方式:torchvision.ops.boxes.batched_nms()
def batched_nms(boxes, scores, idxs, iou_threshold):
    """
    Performs non-maximum suppression in a batched fashion.

    Each index value correspond to a category, and NMS
    will not be applied between elements of different categories.

    Parameters
    ----------
    boxes : Tensor[N, 4]
        boxes where NMS will be performed. They
        are expected to be in (x1, y1, x2, y2) format
    scores : Tensor[N]
        scores for each one of the boxes
    idxs : Tensor[N]
        indices of the categories for each one of the boxes.
    iou_threshold : float
        discards all overlapping boxes
        with IoU < iou_threshold

    Returns
    -------
    keep : Tensor
        int64 tensor with the indices of
        the elements that have been kept by NMS, sorted
        in decreasing order of scores
    """
    if boxes.numel() == 0:
        return torch.empty((0,), dtype=torch.int64, device=boxes.device)
    # strategy: in order to perform NMS independently per class.
    # we add an offset to all the boxes. The offset is dependent
    # only on the class idx, and is large enough so that boxes
    # from different classes do not overlap
    max_coordinate = boxes.max()
    offsets = idxs.to(boxes) * (max_coordinate + 1)
    boxes_for_nms = boxes + offsets[:, None]
    keep = nms(boxes_for_nms, scores, iou_threshold)
    return keep

3.3 知识点

1.nms的gpu版本实现:

如有需求请参考:https://blog.csdn.net/qq_21368481/article/details/85722590

2.nms的应用范围:

只应用在前向推理的过程中,在训练中不进行此步。

3.以上几种nms的性能表现:

https://github.com/ultralytics/yolov3/issues/679

Speed mm:ssCOCO mAP @0.5…0.95COCO mAP @0.5
ultralytics 'OR'8:2039.760.3
ultralytics 'AND'7:3839.660.1
ultralytics 'SOFT'12:0039.158.7
ultralytics 'MERGE'11:2540.260.4
torchvision.ops.boxes.nms()5:0839.760.3
torchvision.ops.boxes.batched_nms()6:0039.760.3

参考资料

https://oldpan.me/archives/write-hard-nms-c

https://github.com/ultralytics/yolov3

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NMS详解及pytorch实现:hard-nms(diou\overlap\merge\batched),soft-nms 的相关文章

  • .data 在 pytorch 中还有用吗?

    我是 pytorch 的新手 我读了很多大量使用张量的 pytorch 代码 data成员 但我搜索 data在官方文档和Google中 发现很少 我猜 data包含张量中的数据 但我不知道什么时候需要它 什么时候不需要 data是一个属性
  • 如何在 PyTorch 数据加载器中将 RGB 图像转换为灰度图像?

    我已经从 MNIST 数据集中下载了一些示例图像 jpg格式 现在我正在加载这些图像来测试我的预训练模型 transforms to apply to the data trans transforms Compose transforms
  • 在 Pytorch 中获取负片(倒置)图像

    我想直接从数据加载器获取图像的负片并将其作为张量提供 有我可以使用的库吗 我试过火炬transforms并没有找到任何 不要费力 只需使用255 image它会给你一个负面的形象 试试吧
  • MNIST、torchvision 中的输出和广播形状不匹配

    在 Torchvision 中使用 MNIST 数据集时出现以下错误 RuntimeError output with shape 1 28 28 doesn t match the broadcast shape 3 28 28 这是我的
  • PyTorch 中的截断反向传播(代码检查)

    我正在尝试在 PyTorch 中实现随时间截断的反向传播 对于以下简单情况K1 K2 我下面有一个实现可以产生合理的输出 但我只是想确保它是正确的 当我在网上查找 TBTT 的 PyTorch 示例时 它们在分离隐藏状态 将梯度归零以及这些
  • Win10 64位上CUDA 12的PyTorch安装

    我需要在我的 PC 上安装 PyTorch 其 CUDA 版本 12 0 pytorch 2 的表 https i stack imgur com X13oS png in In 火炬网站 https pytorch org get sta
  • 如何检查 PyTorch 是否正在使用 GPU?

    如何检查 PyTorch 是否正在使用 GPU 这nvidia smi命令可以检测 GPU 活动 但我想直接从 Python 脚本内部检查它 这些功能应该有助于 gt gt gt import torch gt gt gt torch cu
  • Cuda和pytorch内存使用情况

    我在用Cuda and Pytorch 1 4 0 当我尝试增加batch size 我遇到以下错误 CUDA out of memory Tried to allocate 20 00 MiB GPU 0 4 00 GiB total c
  • 如何使用 torch.stack?

    我该如何使用torch stack将两个张量与形状堆叠a shape 2 3 4 and b shape 2 3 没有就地操作 堆叠需要相同数量的维度 一种方法是松开并堆叠 例如 a size 2 3 4 b size 2 3 b torc
  • 二维数组的按行 numpy.isin [重复]

    这个问题在这里已经有答案了 我有两个数组 A np array 3 1 4 1 1 4 B np array 0 1 5 2 4 5 2 3 5 是否可以使用numpy isin二维数组按行排列 我想检查一下是否A i j is in B
  • 在 C++ API 中将一个张量的一大块复制到另一个张量中

    我需要复制一行一个张量 在c API 转换为另一个张量的某些部分 其中开始和结束索引可用 在 C 中我们可以使用类似的东西 int myints 10 20 30 40 50 60 70 std vector
  • 将 CNN Pytorch 中的预训练权重传递到 Tensorflow 中的 CNN

    我在 Pytorch 中针对 224x224 大小的图像和 4 个类别训练了这个网络 class CustomConvNet nn Module def init self num classes super CustomConvNet s
  • 在pytorch张量中过滤数据

    我有一个张量X like 0 1 0 5 1 0 0 1 2 0 我想实现一个名为的函数filter positive 它可以将正数据过滤成新的张量并返回原始张量的索引 例如 new tensor index filter positive
  • 尝试理解 Pytorch 的 LSTM 实现

    我有一个包含 1000 个示例的数据集 其中每个示例都有5特征 a b c d e 我想喂7LSTM 的示例 以便它预测第 8 天的特征 a 阅读 nn LSTM 的 Pytorchs 文档 我得出以下结论 input size 5 hid
  • PyTorch:如何检查训练期间某些权重是否没有改变?

    如何检查 PyTorch 训练期间某些权重是否未更改 据我了解 一种选择可以是在某些时期转储模型权重 并检查它们是否通过迭代权重进行更改 但也许有一些更简单的方法 有两种方法可以解决这个问题 First for name param in
  • 从打包序列中获取每个序列的最后一项

    我试图通过 GRU 放置打包和填充的序列 并检索每个序列最后一项的输出 当然我的意思不是 1项目 但实际上是最后一个 未填充的项目 我们预先知道序列的长度 因此应该很容易为每个序列提取length 1 item 我尝试了以下方法 impor
  • 使 CUDA 内存不足

    我正在尝试训练网络 但我明白了 我将批量大小设置为 300 并收到此错误 但即使我将其减少到 100 我仍然收到此错误 更令人沮丧的是 在 1200 个图像上运行 10 epoch 大约需要 40 分钟 有什么建议吗 错了 我怎样才能加快这
  • pytorch 中的 autograd 可以处理同一模块中层的重复使用吗?

    我有一层layer in an nn Module并在一次中使用两次或多次forward步 这个的输出layer稍后输入到相同的layer pytorch可以吗autograd正确计算该层权重的梯度 def forward x x self
  • Pytorch ValueError:优化器得到一个空参数列表

    当尝试创建神经网络并使用 Pytorch 对其进行优化时 我得到了 ValueError 优化器得到一个空参数列表 这是代码 import torch nn as nn import torch nn functional as F fro
  • 如何有效地对一个数组中某个值在另一个数组中的位置出现的次数求和

    我正在寻找一种有效的 for 循环 避免解决方案来解决我遇到的数组相关问题 我想使用一个巨大的一维数组 A gt size 250 000 用于一维索引的 0 到 40 之间的值 以及用于第二维索引的具有 0 到 9995 之间的值的相同大

随机推荐

  • elasticsearch7.6.0启动报错问题

    elasticsearch7 6 0启动报错 xff1a 2020 04 08T03 00 20 624 WARN o e t TcpTransport node 1 exception caught on transport layer
  • VScode使用之SSH免密登录配置

    终端电脑生成秘钥对 打开cmd xff0c 输入ssh keygen t rsa一路回车 xff0c 秘钥对文件目录需要记录一下后面需要使用 将公钥放到目标机上 将之前生成的id rsa pub这个文件 xff0c 放到目标机上 注意 xf
  • 51单片机-LCD1602显示(无字库)

    51单片机 LCD1602显示 xff08 无字库 xff09 LCD1602液晶显示屏显示字符显示汉字的显示 LCD1602液晶显示屏引脚说明LCD1602液晶显示屏11条控制指令LCD1602读写时序图LCD1602的RAM地址映射LC
  • “curl: (7) Failed to connect to xxx port 443: Connection refused”解决办法

    curl 7 Failed to connect to xxx port 443 Connection refused 解决办法 mac系统下解决方案 第一步 xff1a 打开网站https www ipaddress com 搜索xxx
  • 关于for循环声明int i的位置

    猿问 C 测试 数据结构 qq 阿篮 0 2017 10 22 13 06 28 for int i 61 0 i lt 10 i 43 43 int i 61 0 for i lt 10 i 43 43 请问这两个运行速度是第一个快吗 x
  • 阿里云-轻量应用服务器-Ubuntu-mysql安装-mysql外连配置-远程连接mysql

    按照本文的步骤 xff0c 能让你在外面 xff0c 用连接上的阿里云轻应用服务器 傻瓜式步骤演示 1 服务器防火墙设置 1 xff09 点击打开 轻量级应用服务器控制台 安全 防火墙 2 xff09 观察红框内有没有MYSQL设置 如果没
  • 阿里云-轻量应用服务器-防火墙-ufw-gufw

    序言 在服务器上装了VNC和xfce 启动VNC服务后发现每过一段时间VNC就不能连接了 上网查询报错原因 发现是因为密码输入错误次数过多 龟龟 xff0c 网上这么多坏人的吗 为了使VNC一直启动的同时不会被别人乱输入密码导致停止服务 x
  • 以太网二层技术——VPLS详解

    目录 前言 xff1a xff08 由于时间关系 xff0c 本篇仅先写了关于VPLS相关 xff09 一 VPLS简介 xff1a 二 VPLS基本工作原理及步骤 xff1a 三 VPLS的报文转发过程 xff1a 四 VPLS的缺点 x
  • SR技术概述与基本概念(SR-BE&SR-TE)

    目录 一 SR背景 二 SR概述 xff1a SR具有如下特点 xff1a SR优势 xff1a 三 一些名词的基本概念 基本概念 xff1a Segment 基本概念 xff1a Segment ID 简称SID xff0c 用于标识se
  • 网络同步技术

    一 同步技术 时钟同步包括 xff1a 频率同步 和时间同步 频率同步要求 相同的时间间隔 xff0c 时间同步要求 时间的起始点相同 和 相同的时间间隔 二 同步以太网技术 xff08 频率同步 xff09 xff1a SyncE xff
  • 以太网虚拟专用网络的工作流程(重点3张表与4种路由)

    目录 一 前言 二 EVPN四种类型路由的作用 三 EVPN表项简介 xff1a xff08 重点 四 EVPN的工作流程分为两个阶段 xff1a 4 1 EVPN启动阶段 xff1a 4 2 EVPN流量转发 xff1a Type2 控制
  • 网络工程师Python入门学习笔记-01

    目录 一 Python编码规范 xff1a 1 1 符号 xff1a 1 2 注释 xff1a 1 3 代码缩进 xff1a 很重要 二 Python的函数与模块 三 Python的类与方法 3 1 类 3 2 telnetlib介绍 xf
  • NETCONF、RESTCONF和YANG

    目录 一 NETCONF RESTCONF和YANG是之间什么关系 xff1f 二 Netconf简介 2 1 一般使用工具 xff1a MG Soft 简介 三 Netconf YANG 原理与实践 3 1 NETCONF协议 3 2 Y
  • Telemetry原理

    Telemetry 是一种网络设备监控技术 xff0c 提供 周期采样网络设备内的统计数据和状态数据的能力 一 Telemetry概述 1 1 技术背景 xff1a 网络设备的统一监控和性能管理是运维平台的重要功能 xff0c 设备的监控数
  • 二三层网络设备封装与解封装原理

    1 寻址转发 xff08 寻址指的是寻找IP地址 xff09 路由表放在一个公共的地方 xff0c 比如主控板上 xff0c 由主控板 的CPU运行路由协议 xff0c 计算路由 xff0c 生成和维护路由表 转发表与路由表 xff1a 转
  • BLE外围设备在Advertising中添加ServiceData

    startAdvertising失败 xff0c errorCode 61 1 AdvertiseCallback ADVERTISE FAILED DATA TOO LARGE errorCode解释 xff1a Failed to st
  • SBFD(Seamless Bidirectional Forwarding Detection)

    SBFD简介 xff1a 更适合SR隧道 BFD进行大量链路检测 时 xff0c 其状态机的协商时间会变长 xff0c 不适合Segement Routing SBFD xff08 Seamless Bidirectional Forwar
  • 使用CCProxy+Proxifier实现代理

    目录 1 使用场景2 什么是网络代理 xff1f 3 CCProxy3 1 说明3 2 下载安装3 3 使用说明 4 Proxifier4 1 说明4 2 下载安装4 3 使用说明4 4 Proxifier CPU占用率高问题解决 1 使用
  • 5G/NR PDSCH之频域资源分配

    物理下行共享信道 Physical Downlink Shared CHannel PDSCH 是无线通信系统中物理下行信道的一种 xff0c 用于传输下行用户数据 而在PDSCH进行下行数据传输时 xff0c 是需要基站给下行数据指定分配
  • NMS详解及pytorch实现:hard-nms(diou\overlap\merge\batched),soft-nms

    文章目录 NMS详解及pytorch实现 hard nms diou overlap merge batched soft nms1 简介2 原理3 实现3 1 伪代码3 2 pytorch源码3 3 知识点 参考资料 NMS详解及pyto