Box是标注信息的3Dbox:一个Box信息为(center,size,orientation,label,score,velocity,name,token)
center: sample_annotation中的‘translation’,x,y,z;
size:sample_annotation中的‘size’,w、l、h
orientation:sample_annotation中的’rotation‘。
label:为可选项,int类型。
score:分类的得分,可选
velocity:center的各自变化速度。
name:box的名字,类别的名字。
token: sample_annotation的唯一token。
代码如下:
from nuscenes import NuScenes
nusc = NuScenes(version='v1.0-mini',dataroot=r'E:\nuScenes\nuscenes_mini',verbose=True)
my_sample = nusc.sample[5] # 得到一个sample
ann_list = my_sample['anns'] # 取出该sample的所有sample_annotation_token
for ann in ann_list:
box = nusc.get_box(ann)
*注: 这里涉及到nuScenes数据集坐标系的转换。先看代码,
代码如下:
import os.path
import cv2
import numpy as np
from nuscenes.utils.geometry_utils import view_points
from pyquaternion import Quaternion
from nuscenes import NuScenes
nusc = NuScenes(version='v1.0-mini',dataroot=r'E:\nuScenes\nuscenes_mini',verbose=True)
my_sample = nusc.sample[0] # 得到一个sample
ann_list = my_sample['anns'] # 取出该sample的所有sample_annotation_token
sample_data_token = my_sample['data']['CAM_FRONT']
sd_rec = nusc.get('sample_data', sample_data_token)
filename = sd_rec['filename']
img_path = os.path.join(nusc.dataroot, filename)
img = cv2.imread(img_path)
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'])
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'])
ann_recs = [nusc.get('sample_annotation', token) for token in s_rec['anns']]
track_class = {'car', 'truck', 'trailer', 'bus', 'bicycle', 'motorcycle', 'pedestrian'}
for ann_rec in ann_recs:
ann_rec['sample_annotation_token'] = ann_rec['token']
ann_rec['sample_data_token'] = sample_data_token
# 世界坐标系下的box标注信息
box = nusc.get_box(ann_rec['token'])
# 从世界坐标系->车身坐标系
box.translate(-np.array(pose_rec['translation']))
box.rotate(Quaternion(pose_rec['rotation']).inverse)
# 从车身坐标系->相机坐标系
box.translate(-np.array(cs_rec['translation']))
box.rotate(Quaternion(cs_rec['rotation']).inverse)
# 过滤掉不在不在图像传感器前面的点
corners_3d = box.corners()
# print('+++++++++++++++++++++++++++++', corners_3d)
# in_front = np.argwhere(corners_3d[2, :] > 0).flatten()
# corners_3d = corners_3d[:, in_front]
print('------------------------------', corners_3d)
# 从相机坐标系->像素坐标系
view = np.eye(4)
view[:3, :3] = np.array(camera_intrinsic)
in_front = corners_3d[2, :] > 0.1
if all(in_front) is False:
continue
points = corners_3d
points = np.concatenate((points, np.ones((1, points.shape[1]))), axis=0)
points = np.dot(view, points)[:3, :]
points /= points[2, :]
box_img = points.astype(np.int32)
color = (64, 128, 255)
# print(box_img)
b = list(set(ann_rec['category_name'].split('.')).intersection(track_class))
if len(b) == 0:
continue
else:
for i in range(4):
j = (i + 1) % 4
# 下底面
cv2.line(img, (box_img[0, i], box_img[1, i]), (box_img[0, j], box_img[1, j]), color, thickness=1)
# 上底面
cv2.line(img, (box_img[0, i + 4], box_img[1, i + 4]), (box_img[0, j + 4], box_img[1, j + 4]), color, thickness=1)
# 侧边线
cv2.line(img, (box_img[0, i], box_img[1, i]), (box_img[0, i + 4], box_img[1, i + 4]), color, thickness=1)
cv2.imshow('图像的3D框', img)
cv2.waitKey(0)
nuScenes数据集存在四个坐标系:全局坐标系,车身坐标系,相机坐标系,雷达(Rader,Lidar)坐标系。因为标注信息是在全局坐标系下,所以需要进行坐标转换才能得到对应图像的box信息。
下一步会更新如何从图像的3Dbox转换到2Dbox。此处先放一下2D效果图:
3d Box转2d Box已经更新在文章nuScenes 3dBox转2dBox。