fastbev mmdetection3D 角度和方向损失

news2025/7/19 15:57:13

角度/方向损失

sin(a−b)=sinacosb−cosasinb

config参数

dir_offset=0.7854, # pi/4

dir_limit_offset=0,

box编解码

# Copyright (c) OpenMMLab. All rights reserved.
import torch

from mmdet.core.bbox import BaseBBoxCoder
from mmdet.core.bbox.builder import BBOX_CODERS

import ipdb


@BBOX_CODERS.register_module()
class DeltaXYZWLHRBBoxCoder(BaseBBoxCoder):
    """Bbox Coder for 3D boxes.

    Args:
        code_size (int): The dimension of boxes to be encoded.
    """

    def __init__(self, code_size=7):
        super(DeltaXYZWLHRBBoxCoder, self).__init__()
        self.code_size = code_size

    @staticmethod
    def encode(src_boxes, dst_boxes):
        """Get box regression transformation deltas (dx, dy, dz, dw, dh, dl,
        dr, dv*) that can be used to transform the `src_boxes` into the
        `target_boxes`.

        Args:
            src_boxes (torch.Tensor): source boxes, e.g., object proposals.
            dst_boxes (torch.Tensor): target of the transformation, e.g.,
                ground-truth boxes.

        Returns:
            torch.Tensor: Box transformation deltas.
        """
        box_ndim = src_boxes.shape[-1]
        cas, cgs, cts = [], [], []
        if box_ndim > 7:
            xa, ya, za, wa, la, ha, ra, *cas = torch.split(
                src_boxes, 1, dim=-1)
            xg, yg, zg, wg, lg, hg, rg, *cgs = torch.split(
                dst_boxes, 1, dim=-1)
            cts = [g - a for g, a in zip(cgs, cas)]
        else:
            xa, ya, za, wa, la, ha, ra = torch.split(src_boxes, 1, dim=-1)
            xg, yg, zg, wg, lg, hg, rg = torch.split(dst_boxes, 1, dim=-1)
        za = za + ha / 2
        zg = zg + hg / 2
        diagonal = torch.sqrt(la**2 + wa**2)
        xt = (xg - xa) / diagonal
        yt = (yg - ya) / diagonal
        zt = (zg - za) / ha
        lt = torch.log(lg / la)
        wt = torch.log(wg / wa)
        ht = torch.log(hg / ha)
        rt = rg - ra
        return torch.cat([xt, yt, zt, wt, lt, ht, rt, *cts], dim=-1)

    @staticmethod
    def decode(anchors, deltas):
        """Apply transformation `deltas` (dx, dy, dz, dw, dh, dl, dr, dv*) to
        `boxes`.

        Args:
            anchors (torch.Tensor): Parameters of anchors with shape (N, 7).
            deltas (torch.Tensor): Encoded boxes with shape
                (N, 7+n) [x, y, z, w, l, h, r, velo*].

        Returns:
            torch.Tensor: Decoded boxes.
        """
        cas, cts = [], []
        box_ndim = anchors.shape[-1]
        if box_ndim > 7:
            xa, ya, za, wa, la, ha, ra, *cas = torch.split(anchors, 1, dim=-1)
            xt, yt, zt, wt, lt, ht, rt, *cts = torch.split(deltas, 1, dim=-1)
        else:
            xa, ya, za, wa, la, ha, ra = torch.split(anchors, 1, dim=-1)
            xt, yt, zt, wt, lt, ht, rt = torch.split(deltas, 1, dim=-1)

        za = za + ha / 2
        diagonal = torch.sqrt(la**2 + wa**2)
        xg = xt * diagonal + xa
        yg = yt * diagonal + ya
        zg = zt * ha + za

        lg = torch.exp(lt) * la
        wg = torch.exp(wt) * wa
        hg = torch.exp(ht) * ha
        rg = rt + ra
        zg = zg - hg / 2
        cgs = [t + a for t, a in zip(cts, cas)]
        return torch.cat([xg, yg, zg, wg, lg, hg, rg, *cgs], dim=-1)

训练-方向分类

mmdet3d/models/dense_heads/free_anchor3d_head.py

2个方向 0,1

self.dir_offset = 0.7854 = pi/4

matched_object_targets是编码后的

            matched_anchors = anchors_[matched] # [38,25,9]
            matched_object_targets = self.bbox_coder.encode( # [38,25,9]
                matched_anchors,
                gt_bboxes_.unsqueeze(dim=1).expand_as(matched_anchors))

            if self.use_direction_classifier:
                # also calculate direction prob: P_{ij}^{dir}
                matched_dir_targets = get_direction_target( # [38,25] dir=0,1  0~2*PI
                    matched_anchors,
                    matched_object_targets,
                    self.dir_offset,
                    one_hot=False)
                loss_dir = self.loss_dir(                      # [38,25]
                    dir_cls_preds_[matched].transpose(-2, -1), # [38,2,25] F.cross_entropy
                    matched_dir_targets,                       # [38,25]
                    reduction_override='none')
def get_direction_target(anchors,
                         reg_targets,
                         dir_offset=0,
                         num_bins=2,
                         one_hot=True):
    """Encode direction to 0 ~ num_bins-1.

    Args:
        anchors (torch.Tensor): Concatenated multi-level anchor.
        reg_targets (torch.Tensor): Bbox regression targets.
        dir_offset (int): Direction offset.
        num_bins (int): Number of bins to divide 2*PI.
        one_hot (bool): Whether to encode as one hot.

    Returns:
        torch.Tensor: Encoded direction targets.
    """
    rot_gt = reg_targets[..., 6] + anchors[..., 6]
    offset_rot = limit_period(rot_gt - dir_offset, 0, 2 * np.pi)
    dir_cls_targets = torch.floor(offset_rot / (2 * np.pi / num_bins)).long()
    dir_cls_targets = torch.clamp(dir_cls_targets, min=0, max=num_bins - 1)
    if one_hot:
        dir_targets = torch.zeros(
            *list(dir_cls_targets.shape),
            num_bins,
            dtype=anchors.dtype,
            device=dir_cls_targets.device)
        dir_targets.scatter_(dir_cls_targets.unsqueeze(dim=-1).long(), 1.0)
        dir_cls_targets = dir_targets
    return dir_cls_targets
def limit_period(val, offset=0.5, period=np.pi):
    """Limit the value into a period for periodic function.

    Args:
        val (torch.Tensor): The value to be converted.
        offset (float, optional): Offset to set the value range. \
            Defaults to 0.5.
        period ([type], optional): Period of the value. Defaults to np.pi.

    Returns:
        torch.Tensor: Value in the range of \
            [-offset * period, (1-offset) * period]
    """
    return val - torch.floor(val / period + offset) * period

训练-角度

mmdet3d/models/dense_heads/free_anchor3d_head.py

gt和pre都是编码后的偏移

sin(a−b)=sinacosb−cosasinb

if self.diff_rad_by_sin:
                bbox_preds_[matched], matched_object_targets = \
                    self.add_sin_difference(
                        bbox_preds_[matched], matched_object_targets)
    def add_sin_difference(boxes1, boxes2):
        """Convert the rotation difference to difference in sine function.

        Args:
            boxes1 (torch.Tensor): Original Boxes in shape (NxC), where C>=7
                and the 7th dimension is rotation dimension.
            boxes2 (torch.Tensor): Target boxes in shape (NxC), where C>=7 and
                the 7th dimension is rotation dimension.

        Returns:
            tuple[torch.Tensor]: ``boxes1`` and ``boxes2`` whose 7th \
                dimensions are changed.
        """
        rad_pred_encoding = torch.sin(boxes1[..., 6:7]) * torch.cos(
            boxes2[..., 6:7])
        rad_tg_encoding = torch.cos(boxes1[..., 6:7]) * torch.sin(boxes2[...,
                                                                         6:7])
        boxes1 = torch.cat(
            [boxes1[..., :6], rad_pred_encoding, boxes1[..., 7:]], dim=-1)
        boxes2 = torch.cat([boxes2[..., :6], rad_tg_encoding, boxes2[..., 7:]],
                           dim=-1)
        return boxes1, boxes2

test

mmdet3d/models/dense_heads/anchor3d_head.py   get_bboxes

self.dir_limit_offset = 0

self.dir_offset = 0.7854   = PI/4

            bboxes = self.bbox_coder.decode(anchors, bbox_pred)

           
             dir_rot = limit_period(bboxes[..., 6] - self.dir_offset,
                                   self.dir_limit_offset, np.pi)
            bboxes[..., 6] = (
                dir_rot + self.dir_offset +
                np.pi * dir_scores.to(bboxes.dtype))
def limit_period(val, offset=0.5, period=np.pi):
    """Limit the value into a period for periodic function.

    Args:
        val (torch.Tensor): The value to be converted.
        offset (float, optional): Offset to set the value range. \
            Defaults to 0.5.
        period ([type], optional): Period of the value. Defaults to np.pi.

    Returns:
        torch.Tensor: Value in the range of \
            [-offset * period, (1-offset) * period]
    """
    return val - torch.floor(val / period + offset) * period

gt_bboxes_3d

limit rad to [-pi, pi]

参考

PointPillars论文解析和OpenPCDet代码解析_pointpillars代码解析-CSDN博客

https://github.com/open-mmlab/OpenPCDet/issues/80

MMDetection3D:数据加载简析 - 龙雪 - 博客园

https://zhuanlan.zhihu.com/p/270314921

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2343278.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一种专用车辆智能配电模块的设计解析:技术革新与未来展望

关键词:智能配电模块、STM32、CAN总线、电子开关、新能源汽车 引言:传统配电系统的痛点与智能化转型 传统配电系统依赖继电器和保险丝,存在体积大、寿命短、智能化低等缺陷(如图1)。而新能源汽车和无人驾驶技术对配电…

《深入浅出ProtoBuf:从环境搭建到高效数据序列化》​

ProtoBuf详解 1、初识ProtoBuf2、安装ProtoBuf2.1、ProtoBuf在Windows下的安装2.2、ProtoBuf在Linux下的安装 3、快速上手——通讯录V1.03.1、步骤1:创建.proto文件3.2、步骤2:编译contacts.proto文件,生成C文件3.3、步骤3:序列化…

Java实现加密(七)国密SM2算法的签名和验签(附商用密码检测相关国家标准/国密标准下载)

目录 一、国密标准中,关于SM2签名验签的定义二、SM2签名和验签的实现原理1. 前置知识2. 签名生成过程3. 验签过程4. 数学正确性证明5. 安全性与注意事项 三、带userId、不带userId的区别1. 核心区别2.算法区别(1) 哈希计算过程(2) 签名验签流程 四、Java代码实现1. …

【华为HCIP | 华为数通工程师】821—多选解析—第十七页

多选835、IS-IS协议所使用的NSAP地址主要由哪几个部分构成? A、AREA ID B、SEL C、DSCp D、SYSTEM ID 解析:NSAP地址:网络服务访问点(Network Service Access Point)是 OSI 协议中用于定位资源的地址。NSAP 的地址结构如图所示,它由 IDP(Initial Domain …

函数的定义与使用(python)

lst[:]是传入lst的拷贝。改变它对原始lst没有任何影响。 *list一个*的元素在函数体内会被当成一个元组。 以下是对图中 Python 代码的详细解释: 代码总体功能 这段代码定义了一个生成器函数 getItem ,用于依次返回多个列表中的元素。然后通过循环遍历…

List findIntersection getUnion

List findIntersection & getUnion 求两个列表的交集和并集 package zwf;import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List;/*** 列表工具类* * author ZengWenFeng* date 2025.04.22* mobile 13805029595* email 117791303qq.com*/ p…

乒乓操作(Ping-Pong)

乒乓操作 “ 乒乓操作” 是一个常常应用于数据流控制的设计思想, 典型的乒乓操作方法如下图 所示: ​ T1周期,输入数据流1缓存到数据缓冲模块1中,如上图棕色;T2周期,输入数据流2缓存到数据缓冲模块2中&…

微信小程序文章管理系统开发实现

概述 在内容为王的互联网时代,高效的文章管理系统成为各类平台的刚需。幽络源平台今日分享一款基于SSM框架开发的微信小程序文章管理系统完整解决方案,该系统实现了多角色内容管理、智能分类、互动交流等功能。 主要内容 一、用户端功能模块 ​​多角…

GrassRouter 小草MULE多5G多链路聚合通信路由设备在应急场景的聚合效率测试报告及解决方案

在应急通信场景中,快速、稳定、高效的通信链路是保障救援工作顺利开展的关键。MULE(Multi-Link Unified Link Enhancement)多链路聚合路由通信设备作为一种新型的通信技术解决方案,通过聚合多条通信链路(如4G/5G、卫星…

【MySQL】MySQL索引与事务

目录 前言 1. 索引 (index) 1.1 概念 1.2 作用 1.3 使用场景 1.4 索引的相关操作 查看索引 创建索引 删除索引 2. 索引背后的数据结构 2.1 B树 2.2 B+树的特点 2.3 B+树的优势 3. 事务 3.1 为什么使用事务 3.2 事…

华为网路设备学习-19 IGP路由专题-路由策略

一、 二、 注意: 当该节点匹配模式为permit下时,参考if else 当该节点匹配模式为deny下时: 1、该节点中的apply子语句不会执行。 2、如果满足所有判断(if-match)条件时,拒绝该节点并跳出(即不…

基于DrissionPage的表情包爬虫实现与解析(含源码)

目录 ​编辑 一、环境配置与技术选型 1.1 环境要求 1.2 DrissionPage优势 二、爬虫实现代码 三、代码解析 3.1 类结构设计 3.2 目录创建方法 3.3 图片链接获取 3.4 图片下载方法 四、技术升级对比 4.1 代码复杂度对比 4.2 性能测试数据 五、扩展优化建议 5.1 并…

区间和数量统计 之 前缀和+哈希表

文章目录 1512.好数对的数目2845.统计趣味子数组的数目1371.每个元音包含偶数次的最长子字符串 区间和的数量统计是一类十分典型的问题:记录左边,枚举右边策略前置题目:统计nums[j]nums[i]的对数进阶版本:统计子数组和%modulo k的…

全能 Sui 技术栈,构建 Web3 的未来

本文翻译自:FourPillarsFP,文章仅代表作者观点。 2025 年,SuiNetwork正在以一套全栈区块链策略强势出击,彻底打破加密行业的传统范式。正如 Mysten Labs 联合创始人 Adeniyi Abiodun 所说:“Sui 不只是一条区块链&…

linux安装单节点Elasticsearch(es),安装可视化工具kibana

真的,我安装个es和kibana,找了好多帖子,问了好几遍ai才安装成功,在这里记录一下,我相信,跟着我的步骤走,99%会成功; 为了让大家直观的看到安装过程,我把我服务器的es和ki…

RK3xxx 部分无法连接虚拟机 无法进行adb连接

我发现部分rk板子可以连接到虚拟机上,部分连接不上。其中尝试了一块是安卓系统的rk板子是可以连接虚拟机。但是用了linux系统的rk板子连接不上虚拟机。尝试了很多办法还是无法连接虚拟机。 然后也看到一些相关资料,但是太少了,只有这个链接提…

26考研——存储系统(3)

408答疑 文章目录 一、存储器概述二、主存储器三、主存储器与 CPU 的连接四、外部存储器五、高速缓冲存储器六、虚拟存储器七、参考资料鲍鱼科技课件26王道考研书 八、总结复习提示思考题常见问题和易混淆知识点 一、存储器概述 文章链接: 点击跳转 二、主存储器 文章链接: …

C# 实战_RichTextBox选中某一行条目高亮,离开恢复

C# 中控件richtextbox中某一行的条目内容高亮,未选中保持不变。当鼠标点击某一行的条目高亮,离开该条目就恢复默认颜色。 运行效果: 核心代码实现功能: //高亮指定行的方法private void HighlightLine(RichTextBox rtb,int lineI…

Servlet小结

视频链接:黑马servlet视频全套视频教程,快速入门servlet原理servlet实战 什么是Servlet? 菜鸟教程:Java Servlet servlet: server applet Servlet是一个运行在Web服务器(如Tomcat、Jetty)或应用…

2025上海车展:光峰科技全球首发“灵境”智能车载光学系统

当AI为光赋予思想,汽车将会变成什么样?深圳光峰科技为您揭晓答案。 2025年4月23日,在刚刚开幕的“2025上海车展”上,全球领先的激光核心器件公司光峰科技举办了主题为“AI光影盛宴,智享未来出行”的媒体发布会&#x…