MapTR的BEV结果可视化到PV图中

news2025/2/22 11:50:22

MapTRv2这篇工作很有意思的一点是预测可视化的时候,在Argoverse数据集上把BEV的预测结果投影到PV图中,来更直观地评估预测结果的好坏,如下图所示。

这部分的代码在maptrv2分支中的tools/maptrv2/av2_vis_pred.py中

def points_ego2img(pts_ego, lidar2img):
    pts_ego_4d = np.concatenate([pts_ego, np.ones([len(pts_ego), 1])], axis=-1)
    pts_img_4d = lidar2img @ pts_ego_4d.T
    
  
    uv = pts_img_4d.T
    uv = remove_nan_values(uv)
    depth = uv[:, 2]
    uv = uv[:, :2] / uv[:, 2].reshape(-1, 1)

    return uv, depth
def draw_polyline_ego_on_img(polyline_ego, img_bgr, lidar2img, map_class, thickness):
    # if 2-dimension, assume z=0
    if polyline_ego.shape[1] == 2:
        zeros = np.zeros((polyline_ego.shape[0], 1))
        polyline_ego = np.concatenate([polyline_ego, zeros], axis=1)

    polyline_ego = interp_fixed_dist(line=LineString(polyline_ego), sample_dist=0.2)
    
    uv, depth = points_ego2img(polyline_ego, lidar2img)

    h, w, c = img_bgr.shape

    is_valid_x = np.logical_and(0 <= uv[:, 0], uv[:, 0] < w - 1)
    is_valid_y = np.logical_and(0 <= uv[:, 1], uv[:, 1] < h - 1)
    is_valid_z = depth > 0
    is_valid_points = np.logical_and.reduce([is_valid_x, is_valid_y, is_valid_z])

    if is_valid_points.sum() == 0:
        return
    
    tmp_list = []
    for i, valid in enumerate(is_valid_points):
        
        if valid:
            tmp_list.append(uv[i])
        else:
            if len(tmp_list) >= 2:
                tmp_vector = np.stack(tmp_list)
                tmp_vector = np.round(tmp_vector).astype(np.int32)
                draw_visible_polyline_cv2(
                    copy.deepcopy(tmp_vector),
                    valid_pts_bool=np.ones((len(uv), 1), dtype=bool),
                    image=img_bgr,
                    color=COLOR_MAPS_BGR[map_class],
                    thickness_px=thickness,
                    map_class=map_class
                )
            tmp_list = []
    if len(tmp_list) >= 2:
        tmp_vector = np.stack(tmp_list)
        tmp_vector = np.round(tmp_vector).astype(np.int32)
        draw_visible_polyline_cv2(
            copy.deepcopy(tmp_vector),
            valid_pts_bool=np.ones((len(uv), 1), dtype=bool),
            image=img_bgr,
            color=COLOR_MAPS_BGR[map_class],
            thickness_px=thickness,
            map_class=map_class,
        )

def render_anno_on_pv(cam_img, anno, lidar2img):
    for key, value in anno.items():
        for pts in value:
            draw_polyline_ego_on_img(pts, cam_img, lidar2img, 
                       key, thickness=10)

def main():
        ##
    pred_anno = {'divider':[],'ped_crossing':[],'boundary':[],'centerline':[]}
    class_by_index=['divider','ped_crossing','boundary']
    for pred_score_3d,  pred_label_3d, pred_pts_3d in zip(scores_3d[keep], labels_3d[keep], pts_3d[keep]):
            if pred_label_3d == 3:
                instance = LineString(pred_pts_3d.numpy()).simplify(0.2, preserve_topology=True)
                pts = np.array(list(instance.coords))
                pred_anno['centerline'].append(pts)
                pred_centerlines.append(pts)
                x = np.array([pt[0] for pt in pts])
                y = np.array([pt[1] for pt in pts])
                plt.quiver(x[:-1], y[:-1], x[1:] - x[:-1], y[1:] - y[:-1], scale_units='xy', angles='xy', scale=1, color='green',headwidth=5,headlength=6,width=0.006,alpha=0.8,zorder=-1)
            else: 
                pred_pts_3d = pred_pts_3d.numpy()
                pred_anno[class_by_index[pred_label_3d]].append(pred_pts_3d)
                pts_x = pred_pts_3d[:,0]
                pts_y = pred_pts_3d[:,1]
                plt.plot(pts_x, pts_y, color=colors_plt[pred_label_3d],linewidth=1,alpha=0.8,zorder=-1)
        #         plt.scatter(pts_x, pts_y, color=colors_plt[pred_label_3d],s=1,alpha=0.8,zorder=-1)

        plt.imshow(car_img, extent=[-1.5, 1.5, -1.2, 1.2])
        map_path = osp.join(sample_dir, 'PRED_MAP.png')
        plt.savefig(map_path, bbox_inches='tight', format='png',dpi=1200)
        plt.close()

        rendered_cams_dict = {}
        for key, cam_dict in img_path_dict.items():
            cam_img = cv2.imread(osp.join(data_path_prefix,cam_dict['filepath']))
            render_anno_on_pv(cam_img,pred_anno,cam_dict['lidar2img'])
            if 'front' not in key:
        #         cam_img = cam_img[:,::-1,:]
                cam_img = cv2.flip(cam_img, 1)
            lw = 8
            tf = max(lw - 1, 1)
            w, h = cv2.getTextSize(caption_by_cam[key], 0, fontScale=lw / 3, thickness=tf)[0]  # text width, height
            p1 = (0,0)
            p2 = (w,h+3)
            color=(0, 0, 0)
            txt_color=(255, 255, 255)
            cv2.rectangle(cam_img, p1, p2, color, -1, cv2.LINE_AA)  # filled
            cv2.putText(cam_img,
                        caption_by_cam[key], (p1[0], p1[1] + h + 2),
                        0,
                        lw / 3,
                        txt_color,
                        thickness=tf,
                        lineType=cv2.LINE_AA)
            rendered_cams_dict[key] = cam_img

     

具体来说,利用lidar2img矩阵将BEV下自车ego坐标系中的结果转换到每张PV图坐标系中,然后进行可视化。

然而对应nuScenes可视化的脚本里没有实现这个功能。因此笔者尝试手动迁移。

然而效果不如意。。

在比较了argoverse和nuScenes的区别后,发现两者的坐标系定义是不同的。

无人驾驶中常用坐标系及相互转换的数学原理介绍_相机 imu 世界坐标系转换-CSDN博客

具体来说,Argoverse的坐标系中,自车ego坐标系=标注坐标系,因此所有标注点/预测点的z=0.具体体现在

def draw_polyline_ego_on_img(polyline_ego, img_bgr, lidar2img, map_class, thickness):
    # if 2-dimension, assume z=0
    if polyline_ego.shape[1] == 2:
        zeros = np.zeros((polyline_ego.shape[0], 1))
        polyline_ego = np.concatenate([polyline_ego, zeros], axis=1)

这一步人工加了一个z维度,而argoverse所有的点z=0。意味着地面点都在lidar坐标系z=0中。

然而nuScenes不同。标注是在lidar坐标系中的,因此lidar的z=0是跟lidar平高的,然而地面点是低于lidar的,因此需要设置一个z。参考projects/mmdet3d_plugin/datasets/nuscenes_offlinemap_dataset.py中对于gt_pv_seg_mask的生成中z=-1.6。因此在可视化nuScenes的时候也设置成z=-1.6

相对拟合一点。但是实际上还是跟实际情况有出入。。。。到这里卡住了,记录一下问题,不知道怎么解决。

注:实际上笔者认为,BEV下的标注是ego坐标系下的,而如果要用lidar2img转换为图像坐标系下进行可视化,中间还需要进行一步ego2lidar。

因此我有一次做了一点改动,想着先将ego转化为lidar再转化为img

def points_ego2img(pts_ego, lidar2img, lidar2ego):
    pts_ego_4d = np.concatenate([pts_ego, np.ones([len(pts_ego), 1])], axis=-1)
    
    ego2lidar = np.linalg.inv(lidar2ego)
    pts_img_4d = lidar2img @ ego2lidar @ pts_ego_4d.T
    
    # pts_img_4d = lidar2img @ pts_ego_4d.T
    pdb.set_trace()
    pix_coords = perspective(pts_ego_4d, lidar2img)

但是可视化完全崩了。。希望有大佬能指点一二。

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

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

相关文章

爬取央视榜单节目

爬取结果&#xff1a; 热播榜&#xff1a; 动画片&#xff1a; 电视剧&#xff1a; 纪录片&#xff1a; 特别节目&#xff1a; 代码部分&#xff1a; import re import pymongoimport requestsres requests.get(https://tv.cctv.com/top/index.shtml?spmC28340.PdNvWY0LYxC…

5款文案生成器,高效率生成短剧解说文案

短剧解说在自媒体写作中很受大家的欢迎&#xff0c;相比其它的视频内容写作&#xff0c;短剧解说不仅写作更简单&#xff0c;而且也更容易带来好的流量&#xff0c;但是&#xff0c;对于短剧解说写作者来说&#xff0c;让人觉得麻烦的一点是短剧解说的文案问题&#xff0c;然而…

如何兼顾PACS方案性能、容量和成本?一文了解SmartX分布式存储与应用一体化平台

重点内容 PACS 应用场景及 IT 基础设施需求分析现有 PACS 应用场景方案优缺点分析SmartX 分布式存储与应用一体化平台方案与关键技术解读SmartX 针对 PACS 应用场景的解决方案针对不同规模的 PACS 资源池配置模拟 PACS&#xff08;Picture Archiving and Communication Syste…

vue3 + tsx 实现音乐播放器

1、效果图 2、文件路径 3、调用方式 audioData为音频的相关数据,lrc为歌词原文(带时间的字符串),举个例子: const lrc = ` [00:00.06]︿☆我不配☆︿ [au:]飒飒飒飒仨撒撒所所撒撒 [00:00.75] [00:01.11]演唱:周杰伦 [00:18.40]这街上太拥挤 太多人有秘密 ` 播放器调用…

[机器学习]--线性回归算法

线性回归算法原理 线性关系在生活中有很多案例: 摄氏度和华氏度的转化: F C ⋅ 9 5 32 F C \cdot\frac{9}{5}32 FC⋅59​32学科最终成绩的计算: 最终成绩 0.3 \times 平时成绩 0.7 \times 期末成绩 线性回归(Linear regression)就是利用回归函数对一个或多个自变量…

Linux系统编程:IPC通信和网络通信

1.IPC通信 IPC 进程间通信方式&#xff1a; 共享内存是最高效的进程间通信方式 共享内存: 1.是一块&#xff0c;内核预留的空间 2.最高效的通信方式&#xff0c;避免了用户空间到内核空间的数据拷贝 IPC通信方式 ---操作流程类…

BaseCTF2024 WP (主要为Rev)

Rev Rev视频解析&#xff1a;[Rev0&#xff1a;从零开始的逆向生活]BaseCTF2024 Week1 Rev 讲解_哔哩哔哩_bilibili [Week1] You are good at IDA [Week1] UPX mini 脱UPX标准壳&#xff0c;解base64 [Week1] Ez Xor 简单的反向异或&#xff0c;数据动调取一下 #base_xor e…

自开发多功能Vue组件:可定义滚动速度[回到顶部/底部]图标组件的安装与使用!

samdy-chan/vue3-goto-top-or-bottom Preview&#xff08;本组件使用效果预览图&#xff09; 本组件使用过程中的 GIF 动态效果图&#xff08;图片经过压缩&#xff0c;视觉可能会有所模糊&#xff09;&#xff1a; Functional Description&#xff08;功能描述&#xff09; …

关于LLC知识10

在LLC谐振腔中能够变化的量 1、输入电压 2、Rac&#xff08;负载&#xff09; 所以增益曲线为红色&#xff08;Rac无穷大&#xff09;已经是工作的最大极限了&#xff0c;LLC不可能工作在红色曲线之外 负载越重时&#xff0c;增益曲线越往里面 假设&#xff1a; 输入电压…

谷歌反垄断案:美国科技史上最大的垄断诉讼与未来展望

引言 近年来&#xff0c;随着全球科技巨头的迅猛崛起&#xff0c;反垄断诉讼逐渐成为各国监管机构打击科技公司滥用市场地位的重要手段。美国作为全球科技产业的发源地&#xff0c;其对反垄断的关注也从未减弱。2023年&#xff0c;美国联邦法院针对谷歌发起的反垄断诉讼&#…

《Spring Cloud 微服务架构核心组件与 Nacos 配置管理详解》

微服务 1.SpringCloud中的核心组件 Spring Cloud Netflix组件 组件名称作用Eureka服务注册中心RibbonRibbonFeign声明式服务调⽤Hystrix客户端容错保护ZuulAPI服务⽹关 Spring Cloud Alibaba组件 组件名称作用Nacos服务注册中心Sentinel客户端容错保护 Spring Cloud原⽣及…

【python】JS逆向中,手把手教会你如何层层突破瑞数加密

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

Python中matplotlib使用4

在matplotlib中&#xff0c;可以通过绘制“饼图”来展示各类别在总体中所占的比例。 1 绘制基本“饼图” 通过matplotlib中的pie()函数绘制饼图&#xff0c;代码如图1所示。 图1 绘制基本“饼图”的代码 从图1中可以看出&#xff0c;pie()函数的参数y即为要绘制的数据&#…

微服务的基本理解和使用

目录​​​​​​​ 一、微服务基础知识 1、系统架构的演变 &#xff08;1&#xff09;单体应用架构 &#xff08;2&#xff09;垂直应用架构 &#xff08;3&#xff09;分布式SOA架构 &#xff08;4&#xff09;微服务架构 &#xff08;5&#xff09;SOA与微服务的关系…

Qt 0821作业

一、思维导图

一种针对自然语言文本的提示策略

文章介绍了一种创新的提示策略&#xff0c;旨在利用大型语言模型从自然语言文本中提取业务流程相关信息&#xff0c;例如活动和参与者等&#xff0c;并建立它们之间的关系。通过这种方法&#xff0c;研究人员能够在无需大量数据的情况下实现高质量的信息提取&#xff0c;进而用…

Apache Commons-IO 库

Apache Commons-IO是Apache开源基金组织提供的一组有关IO&#xff08;Input/Output&#xff09;操作的小框架。这个库的主要目的是为了提高IO流的开发效率&#xff0c;减少在进行文件读写、目录遍历等操作时编写的样板代码量。通过使用Commons-IO库&#xff0c;开发者可以更加简…

为一个花店编写一个库存管理程序,花点库存的花用花的名称、颜色、单价和株的数量来表示。(可直接运行)

为一个花店编写一个库存管理程序&#xff0c;花点库存的花用花的名称、颜色、单价和株的数量来表示。 要求&#xff1a; &#xff08;1&#xff09;说明一个结构数组&#xff0c;存储库存的鲜花数据。 &#xff08;2&#xff09;编写一个函数input_data()&#xff0c;输入现…

【学习笔记】卫星网络(NTN)的窄带物联网(NB-IoT)研究 -- 3GPP TR 36.763(四)

目录 8. 后续研究方向的建议 8.1 来自RAN1的建议 8.1.1 针对NR NTN和IoT NTN的共同增强建议 8.1.2 Release-17时间框架内RAN1建议的总结 8.2 来自RAN2的建议 关于卫星网络&#xff08;NTN&#xff09;的窄带物联网&#xff08;NB-IoT&#xff09;/增强型机器类型通信&#…

【论文阅读33】Deep learning optoacoustic tomography with sparse data

Deep learning optoacoustic tomography with sparse data 论文题目:基于稀疏数据的深度学习光声断层扫描 论文链接:Deep learning optoacoustic tomography with sparse data | Nature Machine Intelligence 代码链接:GitHub - ndavoudi/sparse_artefact_unet 数据链接…