MMDet3D——数据增强Pipline‘GlobalRotScaleTrans‘和‘RandomFlip3D‘的Pytorch逆变换实现

这篇具有很好参考价值的文章主要介绍了MMDet3D——数据增强Pipline‘GlobalRotScaleTrans‘和‘RandomFlip3D‘的Pytorch逆变换实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在点云的3D感知算法中,常用RandomFlip3DGlobalRotScaleTrans的数据增强方式,这两个可以有效地增强模型的鲁棒性,提升模型的性能。

		transforms=[
            dict(
                type='RandomFlip3D',
                sync_2d=False,
                flip_ratio_bev_horizontal=0.5,
                flip_ratio_bev_vertical=0.5),
            dict(
                type='GlobalRotScaleTrans',
                rot_range=[-0.78539816, 0.78539816],
                scale_ratio_range=[0.95, 1.05]),

而本文的出发点在于当我们同时对相同的data使用了多种不同的随机增强方式时,当我们需要在模型中将不同增强方法下的Feature map或者GT 3D Box进行对齐时,就需要涉及到逆变换。
尤其适用于半监督等同时有label和unlabel data的代码。

简单粗暴,我们直接上代码,注释直接写在代码中:(代码可以直接copy使用)

	def align_aug_dataV2(self, pts_feats, # 可以是feature map, shape为 [B,C,H,W]
                         gt_bboxes_3d,# Nuscenes默认的LidarBox格式, shape为 [B,N,x], x=7或9,有无速度的区别
                         img_metas,
                         return_tensor=True,			# 如果想返回的pts_feats是tensor形式,默认True
                         interploate_mode='bilinear'):	# grid_sample的插值方式,如果是feat map,建议bilinear
        '''
        目前的box.tensor的格式为[x, y, z, x_size, y_size, z_size, yaw, vx, vy],shape为[N, 9]
        所以对gt_box做flip需要分别处理x,y,yaw和vx,vy
        '''
        # feature_map: [B,C,H,W]
        def horizontal_flip(feature_map):# 水平翻转
            return torch.flip(feature_map, [2])
        def vertical_flip(feature_map):# 垂直翻转
            return torch.flip(feature_map, [1])
        def box_flip(boxes, bev_direction='horizontal'):
            assert bev_direction in ('horizontal', 'vertical')
            if bev_direction == 'horizontal':
                boxes.tensor[:, 1] = -boxes.tensor[:, 1]    # y
                boxes.tensor[:, 6] = -boxes.tensor[:, 6] + np.pi 
                boxes.tensor[:, 7] = boxes.tensor[:, 7]    # vx
                boxes.tensor[:, 8] = -boxes.tensor[:, 8]    # vy
            elif bev_direction == 'vertical':
                boxes.tensor[:, 0] = -boxes.tensor[:, 0]    # x
                boxes.tensor[:, 6] = -boxes.tensor[:, 6]
                boxes.tensor[:, 7] = -boxes.tensor[:, 7]    # vx
                boxes.tensor[:, 8] = boxes.tensor[:, 8]    # vy
            return boxes
        aligned_pts_feats = []
        aligned_gt_bboxes_3d = deepcopy(gt_bboxes_3d)
        for idx, (pts_feat, boxes_3d, img_meta) in enumerate(
            zip(pts_feats, aligned_gt_bboxes_3d, img_metas)):
            # 数据增强Pipline处理时aug顺序: RandomFlip3D, GlobalRotScaleTrans(rot, scale, trans)
            # 逆变换align顺序需要倒过来
            # ----------------------------------------------------
            pts_feat = pts_feat.unsqueeze(0)
            tgt_size = pts_feat.shape
            dev = pts_feat.device
            # GlobalRotScaleTrans
            if 'pcd_trans' in img_meta:
                if not (img_meta['pcd_trans'] == 0.).all():
                	# assert (img_meta['pcd_trans'] == 0.).all(), \
                #     "Translation is not allowed in `GlobalRotScaleTrans`, [0.,0.,0.] only."
                if not (img_meta['pcd_trans'] == 0.).all():
                    # 1. feat map
                    Trans = torch.zeros_like(img_meta['pcd_rotation'].T)    # [3,3]
                    Trans[0,0], Trans[1,1] = 1, 1
                    # 需要归一化`pcd_trans`,默认的`pcd_trans`为pc_range范围的参数
                    w, h = self.bbox_coder.pc_range
                    w, h = abs(w*2), abs(h*2)
                    Trans[0,2], Trans[1,2] = img_meta['pcd_trans'][0]/w, \
                                             img_meta['pcd_trans'][1]/h
                    
                    Trans = Trans[:2,:].unsqueeze(0)        # [B,2,3]
                    grid = F.affine_grid(Trans, tgt_size).to(dev)   # # 仿射变换矩阵
                    pts_feat = F.grid_sample(pts_feat, # 输入tensor,shape为[B,C,W,H]
                                        grid, # 上一步输出的gird,shape为[B,C,W,H]
                                        mode=interploate_mode)
                    # 2. gt_boxes
                    boxes_3d.translate(-img_meta['pcd_trans'])
            
            if 'pcd_scale_factor' in img_meta:
                if img_meta['pcd_scale_factor'] != 1.:
                    # 1. feat map
                    Scl = torch.zeros_like(img_meta['pcd_rotation'].T)    # [3,3]
                    Scl[0,0], Scl[1,1] = 1/img_meta['pcd_scale_factor'], 1/img_meta['pcd_scale_factor']
                    Scl = Scl[:2,:].unsqueeze(0)        # [B,2,3]
                    grid = F.affine_grid(Scl, tgt_size).to(dev)   # # 仿射变换矩阵
                    pts_feat = F.grid_sample(pts_feat, # 输入tensor,shape为[B,C,W,H]
                                        grid, # 上一步输出的gird,shape为[B,C,W,H]
                                        mode=interploate_mode)
                    # 2. gt_boxes
                    boxes_3d.scale(1/img_meta['pcd_scale_factor'])
                    
            if 'pcd_rotation' in img_meta:
                if img_meta['pcd_rotation'][0,0] != 1.:
                    # 1. feat map
                    Rot = img_meta['pcd_rotation'].T    # [3,3]
                    Rot = Rot[:2,:].unsqueeze(0)        # [B,2,3]
                    grid = F.affine_grid(Rot, tgt_size).to(dev)   # # 仿射变换矩阵
                    pts_feat = F.grid_sample(pts_feat, # 输入tensor,shape为[B,C,W,H]
                                        grid, # 上一步输出的gird,shape为[B,C,W,H]
                                        mode=interploate_mode)
                    # 2. gt_boxes
                    boxes_3d.rotate(img_meta['pcd_rotation'].T)
            pts_feat = pts_feat[0]
            
            # ----------------------------------------------------
            # RandomFlip3D
            if 'pcd_vertical_flip' in img_meta:
                if img_meta['pcd_vertical_flip']:
                    # 1. feat map
                    pts_feat = vertical_flip(pts_feat)
                    # 2. gt_boxes
                    boxes_3d = box_flip(boxes_3d, bev_direction='vertical')

            if 'pcd_horizontal_flip' in img_meta:
                if img_meta['pcd_horizontal_flip']:
                    # 1. feat map
                    pts_feat = horizontal_flip(pts_feat)
                    # 2. gt_boxes
                    # boxes_3d.flip(bev_direction='horizontal')
                    boxes_3d = box_flip(boxes_3d, bev_direction='horizontal')
                    
            aligned_pts_feats.append(pts_feat)
            aligned_gt_bboxes_3d[idx] = boxes_3d
        if return_tensor:
            aligned_pts_feats = torch.stack(aligned_pts_feats)

        return aligned_pts_feats, aligned_gt_bboxes_3d

有几点需要注意:

  • feat map在经过Flip之后也不全是一一对应,因为在卷积过程中,翻转后对应的位置不同,所以feat在经过翻转变换之后略有不同是正常现象;
  • yaw角差360°(2*3.14)是正常情况,因为转换成cos和sin后数值相同。

测试效果

测试一下把有aug的feat map和GT都 对齐到没有aug的情况下:

# 测试代码: (1-3应当相同)
# 1.aligned_aug     aligned_gt_bboxes_3d[0].tensor[0]
# 2.aligned_aug     aligned_gt_bboxes_3d[4].tensor[0]
# 3.无aug           gt_bboxes_3d[4].tensor[0]
# 4.有aug           gt_bboxes_3d[0].tensor[0]
  • 加上RandomFlip3D:(标红的为有aug的原始值
    MMDet3D——数据增强Pipline‘GlobalRotScaleTrans‘和‘RandomFlip3D‘的Pytorch逆变换实现

  • 加上RandomFlip3DScale
    MMDet3D——数据增强Pipline‘GlobalRotScaleTrans‘和‘RandomFlip3D‘的Pytorch逆变换实现

  • 加上RandomFlip3DRotate
    MMDet3D——数据增强Pipline‘GlobalRotScaleTrans‘和‘RandomFlip3D‘的Pytorch逆变换实现

  • 只有Translation的结果:
    MMDet3D——数据增强Pipline‘GlobalRotScaleTrans‘和‘RandomFlip3D‘的Pytorch逆变换实现

  • 加上RandomFlip3DGlobalRotScaleTrans所有aug的对齐结果:
    MMDet3D——数据增强Pipline‘GlobalRotScaleTrans‘和‘RandomFlip3D‘的Pytorch逆变换实现

参考文章:文章来源地址https://www.toymoban.com/news/detail-472501.html

  • Pytorch——实现Tensor矩阵的任意角度旋转、平移操作
  • Pytorch中实现矩阵的的仿射变换,平移、旋转、放缩(affine_grid)

到了这里,关于MMDet3D——数据增强Pipline‘GlobalRotScaleTrans‘和‘RandomFlip3D‘的Pytorch逆变换实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • mmdet.structures.DetDataSample 数据结构解析

    官方文档  https://mmdetection.readthedocs.io/zh-cn/latest/api.html#mmdet-structures ``gt_instances``(InstanceData): Ground truth of instance annotations. 标注的数据 ``pred_instances``(InstanceData): Instances of detection predictions. 预测的数据 ``ignored_instances``(InstanceData): Instances to be ignored during training/testing. 训练或测试

    2024年01月20日
    浏览(33)
  • CVPR2022 3D目标检测(GLENet )增强型3D目标检测网络

    图 1:(a) 给定一个不完整 LiDAR 观测的对象,可能存在多个具有不同大小和形状的潜在合理的真实边界框。 (b) 当注释来自 2D 图像和部分点时,标签过程中的模糊和不准确是不可避免的。在给定的情况下,只有后部的汽车类别的类似点云可以用不同长度的不同真实值框进行注释

    2023年04月08日
    浏览(38)
  • Blender增强现实3D模型制作指南【AR】

    推荐:用 NSDT编辑器 快速搭建可编程3D场景 将静态和动画 3D 内容集成到移动增强现实 (AR) 体验中是增强用户沉浸感和参与度的高效方法。 然而,为 AR 创建 3D 对象可能相当艰巨,尤其是对于那些缺乏 3D 建模经验的人来说。 与添加视频或照片 AR 图层不同,生成 3D 对象需要技

    2024年02月12日
    浏览(70)
  • 电商增强现实3D模型优化需要关注的4个方面

    到目前为止,AR技术已经发展到足以在更广泛的范围内实施。 在电子商务中,这项技术有望提供更令人兴奋的购物体验。 为了实现这一目标,在这篇博客中,我将介绍如何针对电子商务中的 AR 优化 3D 模型。 推荐:用 NSDT编辑器 快速搭建可编程3D场景。 未来是高度未知的,部

    2024年02月12日
    浏览(49)
  • 线上3d党史展览馆增强了观众的民族自信力

    民族的历史文化是增强民族自信的重要基础,美术展览馆自然成为第一批文化溯源的基础,web3d开发公司利用数字化web3d开发技术,制作了3D虚拟美术展览馆,为艺术家和观众创造更逼真、沉浸式的艺术体验,成为一座连接艺术家和观众的桥梁,推动艺术的交流和互动、传承与

    2024年02月03日
    浏览(37)
  • 基于深度学习的3D城市模型增强【Mask R-CNN】

    在这篇文章中,我们描述了一个为阿姆斯特丹 3D 城市模型自动添加门窗的系统(可以在这里访问)。 计算机视觉用于从城市全景图像中提取有关门窗位置的信息。 由于这种类型的街道级图像广泛可用,因此该方法可用于较大的地理区域。 推荐:用 NSDT编辑器 快速搭建可编程

    2024年02月13日
    浏览(44)
  • 51-32 CVPR’24 | 3DSFLabelling,通过伪自动标注增强 3D 场景流估计

    24 年 2 月,鉴智机器人、剑桥大学和上海交通大学联合发布CVPR\\\'24工作,3DSFLabelling: Boosting 3D Scene Flow Estimation by Pseudo Auto-labelling。 提出 3D 场景自动标注新框架,将 3D 点云打包成具有不同运动属性的 Boxes,通过优化每个 Box 运动参数并将源点云 Warp 扭曲到目标点云中,创建了

    2024年04月09日
    浏览(45)
  • 【Unity 3D】使用EasyAR实现单图识别的AR增强现实功能(附实现步骤)

    接下来使用AR插件制作案例 EasyAR是免费 好用的全平台AR引擎,支持使用平面目标的AR 支持1000以上本地目标的流畅加载和识别,支持基于硬解码的视频的播放,支持二维码识别、支持多目标同时跟踪,支持PC和移动设备等多个平台,EasyAR不会现实水印,也没有识别次数限制 在拿

    2024年02月06日
    浏览(50)
  • Jenkins-Pipline实现原理

    本文仅探讨jenkins pipline 的原理,是流水线的一个demo版本实现,不能代表Jenkins pipline的具体实现,仅供参考。 Jenkinsfile流水线是Jenkins CI/CD工具中用来定义、构建和管理软件交付流程的一种声明式文件。 它允许将整个软件交付流程以代码的形式进行描述,从而实现对软件交付过

    2024年02月15日
    浏览(44)
  • jenkins pipline 拉取git历史版本

    我的理解是:我们每次提交git的时候,除了保存我们修改的代码外,也缓存了之前提交的代码,可以用于我们查看更新的内容,而Commit ID 就是为了识别这些历史的提交版本 我这里只展示了一个关于 git 版本的字符信息,也是本文最重要的一个,其他都不是必要的 其他的我设

    2024年02月06日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包