Nuscenes——实现世界坐标3D点投影到像素坐标系中

这篇具有很好参考价值的文章主要介绍了Nuscenes——实现世界坐标3D点投影到像素坐标系中。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

BBOX投影

首先在mmdetection3d/tools/data_converter/nuscenes_converter.py中,get_2d_boxes()可以直接从nuscenes原始sample数据中获取已标注的3D box信息,因此该函数就可以实现整体投影过程。

投影原理

投影过程分为以下几步:

  • 世界坐标系 ——> Ego坐标系(自身)

    • 这里需要世界坐标系原点变换到自身的 平移 T+旋转 R
      Nuscenes——实现世界坐标3D点投影到像素坐标系中
  • Ego坐标系 ——> 相机坐标系

    • 这里需要自身原点位置变换到相机位置的 平移 T+旋转 R(即相机外参) ;
      Nuscenes——实现世界坐标3D点投影到像素坐标系中
  • 相机坐标系 ——> 像素坐标系

    • 此处需要相机内参即可;
      Nuscenes——实现世界坐标3D点投影到像素坐标系中

重要概念

  • box坐标点的origin
    在Nuscenes中,默认get_box()函数获取到的中心点为

代码重构

  • 重构get_2d_boxes()函数如下:(改动处均已标注出)
def get_2d_boxes(nusc,
                 sample_data_token: str,
                 visibilities: List[str],
                 mono3d=True):
    """Get the 2D annotation records for a given `sample_data_token`.

    Args:
        sample_data_token (str): Sample data token belonging to a camera
            keyframe.
        visibilities (list[str]): Visibility filter.
        mono3d (bool): Whether to get boxes with mono3d annotation.

    Return:
        list[dict]: List of 2D annotation record that belongs to the input
            `sample_data_token`.
    """

    # Get the sample data and the sample corresponding to that sample data.
    sd_rec = nusc.get('sample_data', sample_data_token)

    assert sd_rec[
        'sensor_modality'] == 'camera', 'Error: get_2d_boxes only works' \
        ' for camera sample_data!'
    if not sd_rec['is_key_frame']:
        raise ValueError(
            'The 2D re-projections are available only for keyframes.')

    s_rec = nusc.get('sample', sd_rec['sample_token'])
    
    # --------------------------------------------
    # 获取图像,用于可视化
    cam_rec = nusc.get('sample_data', s_rec['data']['CAM_FRONT'])
    imgname = os.path.join('/home/pc/Workspaces/Reaserch/mmdetection3d/data/nuscenes/trainval', \
                                cam_rec['filename'])
	# --------------------------------------------
	
    # Get the calibrated sensor and ego pose
    # record to get the transformation matrices.
    cs_rec = nusc.get('calibrated_sensor', sd_rec['calibrated_sensor_token'])
    pose_rec = nusc.get('ego_pose', sd_rec['ego_pose_token'])
    camera_intrinsic = np.array(cs_rec['camera_intrinsic'])

    # Get all the annotation with the specified visibilties.
    ann_recs = [
        nusc.get('sample_annotation', token) for token in s_rec['anns']
    ]
    ann_recs = [
        ann_rec for ann_rec in ann_recs
        if (ann_rec['visibility_token'] in visibilities)
    ]

    repro_recs = []
    box_list = []       # visualization
    for ann_rec in ann_recs:
        # Augment sample_annotation with token information.
        ann_rec['sample_annotation_token'] = ann_rec['token']
        ann_rec['sample_data_token'] = sample_data_token

        # Get the box in global coordinates.
        box = nusc.get_box(ann_rec['token'])

        # Move them to the ego-pose frame.
        box.translate(-np.array(pose_rec['translation']))
        box.rotate(Quaternion(pose_rec['rotation']).inverse)

        # Move them to the calibrated sensor frame.
        box.translate(-np.array(cs_rec['translation']))
        box.rotate(Quaternion(cs_rec['rotation']).inverse)

        # Filter out the corners that are not in front of the calibrated
        # sensor.
        corners_3d = box.corners()
        in_front = np.argwhere(corners_3d[2, :] > 0).flatten()
        corners_3d = corners_3d[:, in_front]

        # Project 3d box to 2d.
        corner_coords = view_points(corners_3d, camera_intrinsic,
                                    True).T[:, :2].tolist()

        # Keep only corners that fall within the image.
        final_coords = post_process_coords(corner_coords)

        # Skip if the convex hull of the re-projected corners
        # does not intersect the image canvas.
        if final_coords is None:
            continue
        else:
            min_x, min_y, max_x, max_y = final_coords

        # Generate dictionary record to be included in the .json file.
        repro_rec = generate_record(ann_rec, min_x, min_y, max_x, max_y,
                                    sample_data_token, sd_rec['filename'])

        # If mono3d=True, add 3D annotations in camera coordinates
        if mono3d and (repro_rec is not None):
            loc = box.center.tolist()

            dim = box.wlh
            dim[[0, 1, 2]] = dim[[1, 2, 0]]  # convert wlh to our lhw
            dim = dim.tolist()

            rot = box.orientation.yaw_pitch_roll[0]
            rot = [-rot]  # convert the rot to our cam coordinate

            global_velo2d = nusc.box_velocity(box.token)[:2]
            global_velo3d = np.array([*global_velo2d, 0.0])
            e2g_r_mat = Quaternion(pose_rec['rotation']).rotation_matrix
            c2e_r_mat = Quaternion(cs_rec['rotation']).rotation_matrix
            cam_velo3d = global_velo3d @ np.linalg.inv(
                e2g_r_mat).T @ np.linalg.inv(c2e_r_mat).T
            velo = cam_velo3d[0::2].tolist()

            repro_rec['bbox_cam3d'] = loc + dim + rot
            repro_rec['velo_cam3d'] = velo

            center3d = np.array(loc).reshape([1, 3])
            
            
            center2d = points_cam2img(
                center3d, camera_intrinsic, with_depth=False)
            repro_rec['center2d'] = center2d.squeeze().tolist()
            
            # normalized center2D + depth
            # if samples with depth < 0 will be removed
            # --------------------------------------------
            # if repro_rec['center2d'][2] <= 0:
                # continue
            # --------------------------------------------

            ann_token = nusc.get('sample_annotation',
                                 box.token)['attribute_tokens']
            if len(ann_token) == 0:
                attr_name = 'None'
            else:
                attr_name = nusc.get('attribute', ann_token[0])['name']
            attr_id = nus_attributes.index(attr_name)
            repro_rec['attribute_name'] = attr_name
            repro_rec['attribute_id'] = attr_id
            # --------------------------------------------
            box_list.append(torch.tensor(repro_rec['bbox_cam3d']))
        	# --------------------------------------------
        repro_recs.append(repro_rec)
    # --------------------------------------------
    from mmdet3d.core.visualizer.image_vis import draw_camera_bbox3d_on_img
    import cv2
    img = cv2.imread(imgname)
    from mmdet3d.core.bbox.structures.cam_box3d import CameraInstance3DBoxes
    bbox_cam3d = torch.stack(box_list, dim=0) # repro_rec['bbox_cam3d']
    bbox_cam3d = CameraInstance3DBoxes(bbox_cam3d,origin=(0.5,0.5,0.5))
    draw_camera_bbox3d_on_img(bbox_cam3d,
                        raw_img=img,
                        cam2img=camera_intrinsic,
                        img_metas=None,
                        color=(0, 255, 0),
                        thickness=1)
    # --------------------------------------------

投影效果

Nuscenes——实现世界坐标3D点投影到像素坐标系中

点投影

Nuscenes——实现世界坐标3D点投影到像素坐标系中文章来源地址https://www.toymoban.com/news/detail-509217.html

到了这里,关于Nuscenes——实现世界坐标3D点投影到像素坐标系中的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 相机坐标系、像素坐标系转换

    相机内参矩阵是相机的重要参数之一,它描述了相机光学系统的内部性质,例如焦距、光学中心和图像畸变等信息。在计算机视觉和图形学中,相机内参矩阵通常用于将图像坐标系中的像素坐标转换为相机坐标系中的三维坐标,或者将相机坐标系中的三维坐标投影到图像坐标

    2024年02月13日
    浏览(27)
  • 相机坐标系的正向投影和反向投影

    世界3D坐标系(x, y, z) 到图像像素坐标(u,v)的映射过程 (1) 世界坐标系 到 相机坐标系 的映射。 两个坐标系的转换比较简单,就是 旋转矩阵 + 平移矩阵 ,旋转矩阵则是绕X, Y,Z 轴旋转获得。 R 属于世界坐标系到相机坐标系的旋转矩阵, 旋转矩阵为 R = R(z) * R(y) * R(x) , 具体根

    2024年02月10日
    浏览(24)
  • arcgis自定义坐标系,以WGS 1984 Albers投影坐标系为例

    最近在使用arcgis中遇到了很多的问题,其中印象最深刻的就是坐标系的问题,如果arcgis中自带的坐标系中没有找到想要的坐标系,该怎么自定义一个新的坐标系。在使用过程中,我发现arcgis并没有我所需要的albers投影坐标系,所以我尝试着自定义一个albers投影坐标系,具体步

    2024年02月04日
    浏览(58)
  • ArcGIS地图投影与坐标系转换的方法

      本文介绍在 ArcMap 软件中,对矢量图层或栅格图层进行 投影 (即将 地理坐标系 转为 投影坐标系 )的原理与操作方法。   首先,地理坐标系与投影坐标系最简单的区别就是,地理坐标系用 经度 、 纬度 作为空间衡量指标,而投影坐标系用 米 、 千米 等 长度单位 作为

    2024年02月08日
    浏览(27)
  • 世界坐标系、相机坐标系和图像坐标系的转换

    之前只是停留在会用的阶段,一直没去读懂计算的原理,今天通读了大佬的文章,写的言简意赅,感谢感谢~~特此记录一下,仅用作个人笔记 贴链接,十分感谢~ https://blog.csdn.net/weixin_44278406/article/details/112986651 https://blog.csdn.net/guyuealian/article/details/104184551 将三维物体转换成照

    2023年04月15日
    浏览(45)
  • 机器人坐标系转换从局部坐标系转换到世界坐标系

    矩阵方式: 下面是代码: 函数方式: 根据三角函数的特性,可以进行一下简化: 下面是简化前的代码示例:

    2024年04月16日
    浏览(44)
  • 初识Unity——基本模型、场景操作、世界坐标系和局部坐标系

    目录 基本模型 创建基本模型 基本模型的复制  复杂模型 场景操作 聚焦 旋转 移动 场景视野  世界坐标系 基本介绍 原点 局部坐标系    创建基本模型之后,会在我们视野中心生成这个模型;当我们需要复制模型的时候,可以使用 “Duplicate”来进行复制,随后拖出来,不使

    2024年02月08日
    浏览(32)
  • 【Python&GIS】面矢量数据投影转换(WGS84转地方坐标系)

            之前分享过点矢量怎么进行投影转换,今天跟大家分享下面矢量如何投影转换。代码与之前的类似,只要注意一下GDAL对矢量文件划分的关系层次即可。         ogr库是一个处理地理空间矢量数据的开源库。它可以读取多种数据格式,进行地理处理、属性表操作、

    2024年02月14日
    浏览(27)
  • Unity坐标系的转换—世界坐标转为UI坐标

    直接调用WorldToAnchorPos,传入对应的参数返回UGUI坐标

    2024年04月13日
    浏览(30)
  • Android OpenGL ES 学习(九) – 坐标系统和实现3D效果

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投影 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序 Android OpenG

    2024年01月25日
    浏览(32)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包