3D目标检测实用技巧(二)- 实现点云(or 体素)向图像平面的投影并可视化

一、引言

受Focals Conv的启发,该论文中通过将点云投影到图片中清晰展现出点云学习后的情况:

本次实现的是体素向图像投影并显示,实现出来的效果如下:

二、 实现细节

1、体素投影到图像坐标系

这里我们参考的是VirConv的投影函数:

def index2uv(batch_dict, indices, batch_size, calib, stride, x_trans_train, trans_param):
    """
    convert the 3D voxel indices to image pixel indices.将3D的voxel索引转换成图像像素
    """
    # 变换维度的索引
    inv_idx = torch.Tensor([2, 1, 0]).long().cuda()
    batch_index = indices[:, 0]
    new_uv = indices.new(size=(indices.shape[0], 3))
    depth = indices.new(size=(indices.shape[0], 1)).float()
    for b_i in range(batch_size):
        # 找到对应的batch
        cur_in = indices[indices[:, 0] == b_i]
        # 转换成voxel3d特征
        cur_pts = index2points(cur_in, stride=stride)
        if trans_param is not None:
            # 反增强
            transed = x_trans_train.backward_with_param({'points': cur_pts[:, 1:4],
                                                         'transform_param': trans_param[b_i]})
            cur_pts = transed['points']  # .cpu().numpy()
        else:
            cur_pts = cur_pts[:, 1:4]  # .cpu().numpy() 除了batch以外都取出来
        # 投影到相机坐标系
        pts_rect = calib[b_i].lidar_to_rect_cuda(cur_pts[:, 0:3])
        # 投影到图像坐标系
        pts_img, pts_rect_depth = calib[b_i].rect_to_img_cuda(pts_rect)
        # 转换成整型
        pts_img = pts_img.int()
        # pts_img = torch.from_numpy(pts_img).to(new_uv.device)
        # 找到对应的batch,把他的像素坐标取出来
        new_uv[indices[:, 0] == b_i, 1:3] = pts_img
        # pts_rect_depth = torch.from_numpy(pts_rect_depth).to(new_uv.device).float()
        # 深度信息
        depth[indices[:, 0] == b_i, 0] = pts_rect_depth[:]

    # batch对应
    new_uv[:, 0] = indices[:, 0]
    # 控制一下像素坐标
    # new_uv[:, 1] = torch.clamp(new_uv[:, 1], min=0, max=1400 - 1) // stride
    # new_uv[:, 2] = torch.clamp(new_uv[:, 2], min=0, max=600 - 1) // stride

    return new_uv, depth

以上代码具体可参考VirConv源码,这里不赘述。

调用:

# 读取体素坐标
pointxyz = sparse_t.indices
# 传入参数:从左向右依次是batch_dict总字典,pointxyz体素坐标,batchsize大小,calib标定矩阵,stride步长,TED独有的全局变换,trans_param增强参数
pc_xy, depth_pc = index2uv(batch_dict, pointxyz, batch_size, calib, 1, x_trans_train,
                               trans_param)

以上是我目前能找的最有效,最简单的体素投影方法。

2、读取图像并根据深度来画体素

# 根据batch id 依次取出数据    
for batch_id in range(batch_size):
        # image的路径,这里我是放到batch_dict提前存好,所以这里可以直接改为路径
        img_path = str(batch_dict['image_path'][batch_id]).split('/')[-1]
        # 像素大小×255
        pcimg_batch = pcimg[batch_id] * 255
        # 根目录
        root_path = '/home/xd/xyy/VirConv-master/voxel_vision/vision_pcimg/' + img_path + '/'
        # 输出路径
        output_path = root_path + name + '_' + str(batch_id) + '.jpg'
        # 创建路径
        if not os.path.exists(root_path):
            os.makedirs(root_path)
        # 根据batch_id读取出当前batch下的体素坐标
        pc_xyz_indices = pc_xyz[pc_xyz[:, 0] == batch_id][:, 1:]
        for idx, pc in enumerate(pc_xyz_indices):
            # 根据深度确定颜色深度
            color = int((pc[2] / depth_max) * 255)
            # rectangle函数的主要作用是给指定的区域加上长宽分别为2的矩形边框
            if isinstance(pcimg_batch, torch.Tensor):
                pcimg_batch = pcimg_batch.cpu().numpy()
            if pc[0] < W and pc[1] < H:
                # 画体素
                cv2.rectangle(pcimg_batch, (int(pc[0] - 1), int(pc[1] - 1)), (int(pc[0] + 1), int(pc[1] + 1)),
                              (0, 0, color), -1)
        cv2.imwrite(output_path, pcimg_batch)

3、完整代码

def vision_pc_img(sparse_t, pcimg, name, batch_dict, batch_size, calib, x_trans_train, trans_param, H=376, W=1241):
    pointxyz = sparse_t.indices

    pc_xy, depth_pc = index2uv(batch_dict, pointxyz, batch_size, calib, 1, x_trans_train,
                               trans_param)
    # 保存pc_xy
    # for batch_id in range(batch_size):
    #     img_path = str(batch_dict['image_path'][batch_id]).split('/')[-1]
    #     name_2d = img_path + '/' + name
    #     save_2d(pc_xy[pc_xy[:,0]==batch_id], name_2d)
    # vision(sparse_t)

    pc_xyz = torch.cat((pc_xy, depth_pc), dim=1)
    depth_max, _ = torch.max(depth_pc.squeeze(1), dim=0)

    for batch_id in range(batch_size):
        img_path = str(batch_dict['image_path'][batch_id]).split('/')[-1]
        pcimg_batch = pcimg[batch_id] * 255
        root_path = '/home/xd/xyy/VirConv-master/voxel_vision/vision_pcimg/' + img_path + '/'
        output_path = root_path + name + '_' + str(batch_id) + '.jpg'
        if not os.path.exists(root_path):
            os.makedirs(root_path)
        pc_xyz_indices = pc_xyz[pc_xyz[:, 0] == batch_id][:, 1:]
        for idx, pc in enumerate(pc_xyz_indices):
            color = int((pc[2] / depth_max) * 255)
            # rectangle函数的主要作用是给指定的区域加上长宽分别为2的矩形边框
            if isinstance(pcimg_batch, torch.Tensor):
                pcimg_batch = pcimg_batch.cpu().numpy()
            if pc[0] < W and pc[1] < H:
                cv2.rectangle(pcimg_batch, (int(pc[0] - 1), int(pc[1] - 1)), (int(pc[0] + 1), int(pc[1] + 1)),
                              (0, 0, color), -1)
        cv2.imwrite(output_path, pcimg_batch)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

通过matlab分别对比PSO,反向学习PSO,多策略改进反向学习PSO三种优化算法

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 粒子群优化算法 (PSO) 4.2 反向学习粒子群优化算法 (OPSO) 4.3 多策略改进反向学习粒子群优化算法 (MSO-PSO) 5.完整程序 1.程序功能描述 分别对比PSO,反向学习PSO,多策略改进反向学…

百货商场用户画像描绘与价值分析

目录 内容概述数据说明实现目标技术点主要内容导入模块1.项目背景1.1 项目背景与挖掘目标 2.数据探索与预处理2.1 结合业务对数据进行探索并进行预处理2.2 将会员信息表和销售流水表关联与合并 3 统计分析3.1 分析会员的年龄构成、男女比例等基本信息3.2 分析会员的总订单占比&…

Python 入门指南(四)

原文&#xff1a;zh.annas-archive.org/md5/97bc15629f1b51a0671040c56db61b92 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第十章&#xff1a;哈希和符号表 我们之前看过列表&#xff0c;其中项目按顺序存储并通过索引号访问。索引号对计算机来说很有效。它们是整…

使用 Docker 部署 SurveyKing 调查问卷系统

1&#xff09;SurveyKing 介绍 SurveyKing 是一款功能强大、操作简便的开源问卷系统。它不仅满足了用户对问卷调查的基本需求&#xff0c;还提供了丰富的逻辑设置和灵活的问题设置&#xff0c;使得问卷制作更加智能化和个性化。此外&#xff0c;SurveyKing 还具有快速部署和安全…

笔记本电脑上的聊天机器人: 在英特尔 Meteor Lake 上运行 Phi-2

对应于其强大的能力&#xff0c;大语言模型 (LLM) 需要强大的算力支撑&#xff0c;而个人计算机上很难满足这一需求。因此&#xff0c;我们别无选择&#xff0c;只能将它们部署至由本地或云端托管的性能强大的定制 AI 服务器上。 为何需要将 LLM 推理本地化 如果我们可以在典配…

elmentui树形表格使用Sortable拖拽展开行时拖拽bug

1、使用elemntui的el-table使用Sortable进行拖拽&#xff0c;如下 const el this.$el.querySelector(.el-table__body-wrapper tbody) Sortable.create(el, {onEnd: (event) > {const { oldIndex, newIndex } event//拿到更新前后的下标即可完成数据的更新} })2、但是我这…

docker 环境变量设置实现方式

1、前言 docker在当前运用的越来广泛&#xff0c;很多应用或者很多中间软件都有很多docker镜像资源&#xff0c;运行docker run 启动镜像资源即可应用。但是很多应用或者中间件有很多配置参数。这些参数在运用过程怎么设置给docker 容器呢&#xff1f;下面介绍几种方式 2 、do…

Day91:API攻防-接口安全SOAPOpenAPIRESTful分类特征导入项目联动检测

目录 API分类特征-SOAP&OpenAPI&RESTful API分类特征 API常见漏洞 API检测流程 API检测项目-Postman&APIKit&XRAY 工具自动化-SOAP - WSDL Postman 联动burpxray APIKit插件(可联动xray) 工具自动化-OpenApi - Swagger Postman 联动burpxray APIKit…

HarmonyOS开发实例:【分布式邮件】

概述 基于TS扩展的声明式开发范式编程语言编写的一个分布式邮件系统&#xff0c;可以由一台设备拉起另一台设备&#xff0c;每次改动邮件内容&#xff0c;都会同步更新两台设备的信息。效果图如下&#xff1a; 搭建OpenHarmony开发环境 完成本篇Codelab我们首先要完成开发环境…

OpenStack:开源云计算的崛起与发展

目录 一&#xff0c;引言 二&#xff0c;OpenStack的起源 三&#xff0c;OpenStack的版本演进 四&#xff0c;OpenStack跟虚拟化的区别 五&#xff0c;OpenStack组件介绍 1&#xff09;Horizon介绍 2&#xff09;KeyStone介绍 Keystone 功能概览 Keystone 架构详解 3&a…

RabbitMQ 各种通信模式的Python实现

一、RabbitMQ 原理 1、基本原理 RabbitMQ是流行的开源消息队列系统&#xff0c;用erlang语言开发。RabbitMQ是AMQP&#xff08;高级消息队列协议&#xff09;的标准实现。支持多种客户端&#xff0c;如&#xff1a;Python、Java、Javascript、C#、C/C,Go等&#xff0c;支持AJ…

RabbitMQ Stream插件使用详解

2.4版为RabbitMQ流插件引入了对RabbitMQStream插件Java客户端的初始支持。 RabbitStreamTemplateStreamListener容器 将spring rabbit流依赖项添加到项目中&#xff1a; <dependency><groupId>org.springframework.amqp</groupId><artifactId>sprin…

【echarts】使用 ECharts 绘制3D饼图

使用 ECharts 绘制3D饼图 在数据可视化中&#xff0c;饼图是表达数据占比信息的常见方式。ECharts 作为一个强大的数据可视化库&#xff0c;除了标准的二维饼图&#xff0c;也支持更加生动的三维饼图绘制。本文将指导你如何使用 ECharts 来创建一个3D饼图&#xff0c;提升你的…

百度智能云万源全新一代智能计算操作系统发布:引领AI新纪元,开启智能未来

随着科技的迅猛发展&#xff0c;人工智能&#xff08;AI&#xff09;逐渐渗透到我们生活的每个角落&#xff0c;为人类社会带来前所未有的变革。在这场科技革命的浪潮中&#xff0c;百度作为中国AI领域的领军企业&#xff0c;始终站在技术创新的前沿&#xff0c;不断引领行业发…

【数据结构与算法】用两个栈实现一个队列

题目 用两个栈&#xff0c;实现一个队列功能 add delete length 队列 用数组可以实现队列&#xff0c;数组和队列的区别是&#xff1a;队列是逻辑结构是一个抽象模型&#xff0c;简单地可以用数组、链表实现&#xff0c;所以数组和链表是一个物理结构&#xff0c;队列是一个逻…

Rust腐蚀服务器修改背景和logo图片操作方法

Rust腐蚀服务器修改背景和logo图片操作方法 大家好我是艾西一个做服务器租用的网络架构师。在我们自己搭建的rust服务器游戏设定以及玩法都是完全按照自己的想法设定的&#xff0c;如果你是一个社区服那么对于进游戏的主页以及Logo肯定会有自己的想法。这个东西可以理解为做一…

MaxCompute 近实时增全量处理一体化新架构和使用场景介绍

随着当前数据处理业务场景日趋复杂&#xff0c;对于大数据处理平台基础架构的能力要求也越来越高&#xff0c;既要求数据湖的大存储能力&#xff0c;也要求具备海量数据高效批处理能力&#xff0c;同时还可能对延时敏感的近实时链路有强需求&#xff0c;本文主要介基于 MaxComp…

Docker安装xxl-job分布式任务调度平台

文章目录 Docker安装xxl-job分布式任务调度平台1.xxl-job介绍2. 初始化“调度数据库”3、docker挂载运行xxl-job容器3.1、在linux的opt目录下创建xxl_job文件夹&#xff0c;并在里面创建logs文件夹和application.properties文件3.2、配置application.properties文件&#xff0c…

基于Qt的二维码生成与识别

基于Qt的二维码生成与识别 一、获取QZxing开源库 1.通过封装的QZxing开源库生成和识别二维码&#xff0c;下载地址&#xff1a;GitCode - 开发者的代码家园https://gitcode.com/mirrors/ftylitak/qzxing/tree/master。 2.下载解压后&#xff0c;使用Qt Creator xx&#xff0…

Yolo-world+Python-OpenCV之摄像头视频实时目标检测

上一次介绍了如何使用最基本的 Yolo-word来做检测&#xff0c;现在我们在加opencv来做个实时检测的例子 基本思路 1、读取离线视频流 2、将视频帧给yolo识别 3、根据识别结果 对视频进行绘制边框、加文字之类的 完整代码如下&#xff1a; import datetimefrom ultralytics …