熟悉mmdetection3d数据在模型中的处理流程

news2024/11/27 0:25:36

目录

    • 1、搭建模型
    • 2、读取数据
    • 3、运行流程
      • 3.1 图像特征获取
      • 3.2 点云特征获取
      • 3.3 head
      • 3.4 编码bbox
    • 4、可视化
    • 5、总结

  • 本图文数据集采取KITTI数据集
  • 配置文件的介绍可以参考博主上一篇图文
  • 本图文旨在利用一条数据,走完整个多模态数据处理分支,获得bbox,并可视化在图像上

1、搭建模型

  • 本次教程选用的模型为MVXNet,是一个多模态融合的3D目标检测模型

  • 配置文件: mmdetection3d/configs/mvxnet/dv_mvx-fpn_second_secfpn_adamw_2x8_80e_kitti-3d-3class.py

  • 本次使用预训练模型,可以在mmdetection3d的mozel zoo中下载 MVXNet模型

from mmdet3d.apis import init_model
config_file = '/home/wistful/work/mmdetection3d/configs/mvxnet/dv_mvx-fpn_second_secfpn_adamw_2x8_80e_kitti-3d-3class.py'
checkpoint_file = '/home/wistful/ResultDir/my_pth/mxvnet/dv_mvx-fpn_second_secfpn_adamw_2x8_80e_kitti-3d-3class_20210831_060805-83442923.pth'

model = init_model(config_file, checkpoint_file, 'cuda:1')

在这里插入图片描述

2、读取数据

from mmdet3d.datasets import build_dataset
from mmcv import Config

cfg = Config.fromfile(config_file)
# 读取数据集
datasets = [build_dataset(cfg.data.train)]
# 我们取其中的一条数据,作为演示用例
one_data = datasets[0][0]
  • 根据我们的配置文件,我们得到的datasets为一个长度为7424(KITTI训练集长度)的列表,每一项包括4个字段:[‘img_metas’, ‘points’, ‘img’, ‘gt_bboxes_3d’, ‘gt_labels_3d’]

  • 接下来所有数据均使用这一个one_data

3、运行流程

MVXNet结构图如下:

在这里插入图片描述

MVXNet简化版模型结构:

model = dict(
    type='DynamicMVXFasterRCNN',
    img_backbone=dict(), # 图像骨干
    img_neck=dict(), # 图像neck
    pts_voxel_layer=dict(), # 体素层
    pts_voxel_encoder=dict(), # 体素编码层
    pts_middle_encoder=dict(), # 中间编码层
    pts_backbone=dict(), # 点云骨干
    pts_neck=dict(), # 点云neck
    pts_bbox_head=dict() # bbox head)

结合结构图,以上配置文件的最简理解是,图像经过骨干、neck得到图像特征;点云经过体素、编码得到点云特征;查看原版配置文件就可以看到,会在一个层融合图像和点云特征;随后经过head,产出bbox。接下来,我们先来获取图像特征:

3.1 图像特征获取

extract_img_feat = model.extract_img_feat
# 获取图像特征,此处获取的是图像经过骨干和neck之后的数据,为5个通道数为256的特征
img_feats = extract_img_feat((one_data.get('img').data).unsqueeze(dim=0).cuda(), [one_data.get('img_metas').data])
for i in img_feats:
    print(i.shape)
    
# extrac_img_feat代码:
def extract_img_feat(self, img, img_metas):
    """Extract features of images."""
    if self.with_img_backbone and img is not None:
        input_shape = img.shape[-2:]  # 获取图片的尺寸
        # update real input shape of each single img
        for img_meta in img_metas:
            img_meta.update(input_shape=input_shape)  # 更新一下img_metas

        if img.dim() == 5 and img.size(0) == 1:  # 维度等于5的话去除一个维度(只取一个图片)
            img.squeeze_()
        elif img.dim() == 5 and img.size(0) > 1:  # 取出批量、图片个数、通道、高、宽
            B, N, C, H, W = img.size()
            img = img.view(B * N, C, H, W)  # 重构为 [批量*数量, 通道, 高, 宽]
        img_feats = self.img_backbone(img)  # 送入骨干
    else:
        return None
    if self.with_img_neck:
        img_feats = self.img_neck(img_feats)  # 将骨干再送入neck
    return img_feats

输出如下:

image-20230310194626048

3.2 点云特征获取

extract_pts_feat = model.extract_pts_feat
# 获取点云特征,此处同上面各个字段的类型需要去代码里看定义
img_feat_list = list(img_feats)
pts_feats = extract_pts_feat([one_data.get('points').data.cuda()], img_feat_list, [one_data.get('img_metas').data])

# extract_pts_feat代码:
def extract_pts_feat(self, pts, img_feats, img_metas):
    """Extract features of points."""
    if not self.with_pts_bbox:
        return None
    voxels, num_points, coors = self.voxelize(pts)  # 体素化
    # 体素编码器
    voxel_features = self.pts_voxel_encoder(voxels, num_points, coors,
                                            img_feats, img_metas)
    batch_size = coors[-1, 0] + 1
    x = self.pts_middle_encoder(voxel_features, coors, batch_size)
    x = self.pts_backbone(x)
    if self.with_pts_neck:
        x = self.pts_neck(x)
    return x

此时,我们已经得到图像特征和点云特征了,下面将特征送入head

3.3 head

# 此处的head为Anchor3DHead,返回值有三个: cls_score, bbox_pred, dir_cls_preds
# 其中,clas_score 通道数为  num_classes * num_anchors, num_classes在配置文件中
# bbox_pred 通道数为 num_anchors * box_code_size
# dir_cls_preds 通道数为 num_anchors * 2
# 得到head的输出后,还需要运行一下解码模块,才能得到最终的bbox和分类情况
pts_bbox_head = model.pts_bbox_head
pts_out = pts_bbox_head(pts_feats)  # tuple[list[torch.Tensor]]
cls_score, bbox_pred, dir_cls_preds = pts_out
print("cls_score:", cls_score[0].shape)
print("bbox_pred:", bbox_pred[0].shape)
print("dir_cls_preds:", dir_cls_preds[0].shape)

在这里插入图片描述

3.4 编码bbox

# 将head得到的输出编码为bboxer
bboxes = model.pts_bbox_head.get_bboxes(cls_score, bbox_pred, dir_cls_preds, [one_data.get('img_metas').data])
print(type(bboxes[0][0]))  # 是在LiDAR坐标系下
bboxes_data = bboxes[0][0]  # 得到了n个预测框
bboxes_data

image-20230310195117153

以上是最简版的一条数据在模型里的流动过程,还有n多实现细节,需要去深扒代码

4、可视化

这一部分,我们可视化我们在3.4中得到的bbox,程序自己看吧

import cv2
from mmdet3d.core import show_multi_modality_result

img_metas = one_data.get('img_metas').data
img_file_path = img_metas['filename'] # 获取one_data对应的图像文件名

img = cv2.imread(img_file_path) # 读取图像
front_mat = one_data.get('img_metas').data.get('lidar2img') # 获取投影矩阵

gt_boxes = one_data.get('gt_bboxes_3d').data # 从one_data中获取gt_bboxes
print(gt_boxes)
print(bboxes_data)
# gt_bboxes_cam
bboxes_data = bboxes_data.to('cpu')
# 保存可视化图像到out_dir
show_multi_modality_result(img=img,
                           box_mode='lidar',
                           gt_bboxes=gt_boxes,
                           img_metas=img_metas,
                           pred_bboxes=bboxes_data,
                           proj_mat=front_mat,
                           out_dir="/home/wistful/work/mmdetection3d/visual_img/",
                           filename="test",
                           show=False)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GcltvkGl-1678449986037)(null)]

这里我得到了四个输出,是因为我改动了一下show_multi_modality_result方法,加了一个将地面真相bbox和预测bbox绘制到一张图像上的方法。如下图所示,橙色为地面真相bbox,蓝色为预测框

在这里插入图片描述

5、总结

简单画了一个流程图,橙色代表我们获取的数据内容,蓝色代表网络,绿色代表我们得到的东西

在这里插入图片描述

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

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

相关文章

Linux内核里的传输层数据流

传输层发送数据包socket sendto系统调用应用程序通过socket调用sendto系统调用发送数据包,根据网络层协议调用inet_sendmsg或者inet6_sendmsg()函数,将数据包送入协议栈发送。SYSCALL_DEFINE6(sendto...) - net/socket.csock_sendmsg() - net/socket.cso…

compose系列教程-2. 显示图片

要在Android中使用Compose显示图片,需要使用Image组件。以下是一个简单的例子,它显示了一张图片: Composable fun MyApp() { val image painterResource(id R.drawable.my_image) Image(painter image, contentDescription "…

dynamics 365的增删改查

今天需要完成对dynamics 365的增删改查,网上一直找不到合适的教程,官方文档看不懂,实在没办法了,于是下载了chatgpt,对他进行了提问。 我:怎么用visual studio基于dynamics 365进行增删改查? ChatGPT 中文…

Python笔记 -- 类

文章目录1、引入2、操作属性3、继承4、将实例用作属性5、导入类1、引入 类和实例 使用类可以模拟任何东西,下面是一个小狗的简单类Dog,它表示任意小狗,实例my_dog表示一个具体的小狗方法 类中的函数称为方法,有关函数的一切均适用…

兔c同学的一篇:使用python 的 unittest模块对类和函数进行测试

文章目录1. 测试函数简单的函数测试单元测试和测试用例可通过的测试不可通过的测试测试未通过时怎么办2. 测试类各种断言方法测试一个类测试 AnonymousSurvey方法setUp()导言 在编写函数或类时,还可为其编写测试。通过测试,可以确定代码面对各种输入都能…

面试官必问--谈谈Spring Bean对象的生命周期吧

现在是时候讨论Spring Bean从产生到销毁整个过程的细节了,也就是Spring Bean的生命周期。在这里文哥先温馨提示:Spring Bean的生命周期是面试高频点之一,希望大家好好掌握哦~一. Spring Bean生命周期的概述如果没有Spring的环境,J…

张力控制之开环模式

张力控制的相关知识也可以参看专栏的其它文章,链接如下: 张力闭环控制之传感器篇(精密调节气阀应用)_RXXW_Dor的博客-CSDN博客跳舞轮对应张力调节范围,我们可以通过改变气缸的气压方式间接改变,张力跳舞轮在收放卷闭环控制上的详细应用,可以参看下面的文章链接,这里我…

人工智能实验一:利用遗传算法求解 TSP(旅行商)问题

1.任务描述 本关任务:利用遗传算法求解 TSP 问题。 2.相关知识 为了完成本关任务,你需要掌握:1. 遗传算法;2. TSP问题。 遗传算法 一个后继状态由两个父状态决定,以k个随机产生的状态开始(population&…

Kaggle赛题解析:Diffusion Prompt生成

文章目录一、比赛信息二、比赛背景三、比赛任务四、评价指标五、数据描述六、解题思路一、比赛信息 比赛名称:Stable Diffusion - Image to Prompts 推断生成高度详细、清晰的焦点、插图、宏伟、史诗般的 3d 渲染图像的prompt 比赛链接:https://www.k…

python----获取一部小说

1、需求说明 获取一部小说的标题内容,以txt文档形式保存 2、项目说明 3、代码 # 怎么发送请求 # pip install requests import requests# pip install lxml->从标签里提起文字 #from lxml import etree from lxml import html etreehtml.etree # 发送给谁 url…

Android---系统启动流程

目录 Android 系统启动流程 init 进程分析 init.rc 解析 Zygote 概叙 Zygote 触发过程 Zygote 启动过程 什么时Runtime? System Server 启动流程 Fork 函数 总结 面试题 Android 是 google 公司开发的一款基于 Linux 的开源操作系统。 Android 系统启动…

Web3中文|一波未平一波又起:Silvergate将走向何处

Silvergate Capital(SI)这一加密公司曾经的重要银行合作伙伴,现在正处于崩溃的边缘。这家总部位于加州拉荷亚的公司上周五晚上表示,其暂停了Silvergate交易所网络(SEN:Silvergate Exchange Network&#xf…

Foxit PDF SDK ActiveX 5.9.7 Crack

Foxit PDF SDK ActiveX对于刚接触PDF或不愿投入过多精力学习PDF技术的产品管理者及开发者来说,Foxit PDF SDK ActiveX无疑是理想的选择。破解版它拥有操作简单的特性,提供可支持定制的可视化编程组件,开发者通过简单的拖放动作,就…

扬帆配资|建筑业景气度持续回升,多只概念股业绩有望增长

新式城镇化概念股遭到商场重视。 今天早盘,新式城镇化概念股冲高,恒锋信息、ST花王涨停。蕾奥规划、筑博规划一度冲高至15%,冠龙节能、杭州园林、美晨生态跟涨。 国家出台一系列城镇化相关方针 城镇化,是人口向城镇会集的进程。…

【Kubernetes】第二十三篇 - 布署 nodejs 后端项目(上)

一,前言 上一篇,介绍了 MySQL 服务的部署; 本篇,介绍 nodejs 后端项目的布署(将后端项目构建成为 docker 镜像,并推送至镜像仓库); 二,准备项目 创建后端项目&#xf…

8、LSM树

一、前言 最近在调研NoSQL数据库,发现RocksDB、LevelDB、HBase以及Prometheus等,其底层的存储引擎都是基于LSM树,于是决定花时间彻底吃透LSM树这一数据结构。 不幸的是,在查阅资料学习的过程中,发现网上各种文章汗牛…

浅谈对Promise的理解以及在工作中的应用

浅谈对Promise的理解以及在工作中的应用Promise的概念背景知识JavaScript的同步和异步JavaScript事件循环回调函数进行异步操作解决方案:PromisePromise 在工作中的运用创建PromisePromise封装AJAXPromise链式操作Promise.all()Promise.race()async和await总结Promi…

轻松转换文档:antennahouse/Office Server Document Converter

关于 Office Server 文档转换器 (OSDC)破解版 无需 Microsoft Office 或 Adob​​e 软件即可快速准确地转换文档。 Office Server 文档转换器 (OSDC) 会将您在 Microsoft Office(Word、Excel、PowerPoint)中创建的重要文档转换为高质量的 PDF 或图像格式…

国内32位MCU在电机控制上的应用方案

电机(Electric machinery,俗称“马达”)是依据电磁感应定律,实现电能转换或传递的一种电磁装置,其主要作用是产生驱动转矩,为用电器或各类机械提供动力。电机作为工业世界的动力之源,几乎用于所…

ThinkPHP 6.1 模板篇之布局与继承

本文主要讲述ThinkPHP 6.1版本模板几种布局的方法和如何实现继承, 可以与《ThinkPHP 6.1 模板篇之文件加载》结合来看。 模板布局 布局方式有两种可以实现。 布局方法1 开启配置 默认情况下,不支持模版布局功能,需要在配置文件中开启&…