Commit b2c43ffd authored by zhangwenwei's avatar zhangwenwei
Browse files

Merge branch 'add_docstring' into 'master'

Add docstrings

See merge request open-mmlab/mmdet.3d!72
parents 613c8844 8f88914d
...@@ -64,19 +64,19 @@ def export(mesh_file, ...@@ -64,19 +64,19 @@ def export(mesh_file,
"""Export original files to vert, ins_label, sem_label and bbox file. """Export original files to vert, ins_label, sem_label and bbox file.
Args: Args:
mesh_file(str): Path of the mesh_file. mesh_file (str): Path of the mesh_file.
agg_file(str): Path of the agg_file. agg_file (str): Path of the agg_file.
seg_file(str): Path of the seg_file. seg_file (str): Path of the seg_file.
meta_file(str): Path of the meta_file. meta_file (str): Path of the meta_file.
label_map_file(str): Path of the label_map_file. label_map_file (str): Path of the label_map_file.
output_file(str): Path of the output folder. output_file (str): Path of the output folder.
Default: None. Default: None.
It returns a tuple, which containts the the following things: It returns a tuple, which containts the the following things:
ndarray: Vertices of points data. np.ndarray: Vertices of points data.
ndarray: Indexes of label. np.ndarray: Indexes of label.
ndarray: Indexes of instance. np.ndarray: Indexes of instance.
ndarray: Instance bboxes. np.ndarray: Instance bboxes.
dict: Map from object_id to label_id. dict: Map from object_id to label_id.
""" """
......
...@@ -39,10 +39,10 @@ def flip_axis_to_camera(pc): ...@@ -39,10 +39,10 @@ def flip_axis_to_camera(pc):
Flip X-right,Y-forward,Z-up to X-right,Y-down,Z-forward. Flip X-right,Y-forward,Z-up to X-right,Y-down,Z-forward.
Args: Args:
pc(ndarray): points in depth axis. pc (np.ndarray): points in depth axis.
Returns: Returns:
ndarray: points in camera axis. np.ndarray: points in camera axis.
""" """
pc2 = np.copy(pc) pc2 = np.copy(pc)
pc2[:, [0, 1, 2]] = pc2[:, [0, 2, 1]] # cam X,Y,Z = depth X,-Z,Y pc2[:, [0, 1, 2]] = pc2[:, [0, 2, 1]] # cam X,Y,Z = depth X,-Z,Y
...@@ -132,10 +132,10 @@ class SUNRGBD_Calibration(object): ...@@ -132,10 +132,10 @@ class SUNRGBD_Calibration(object):
"""Convert pc coordinate from depth to image. """Convert pc coordinate from depth to image.
Args: Args:
pc(ndarray): Point cloud in depth coordinate. pc (np.ndarray): Point cloud in depth coordinate.
Returns: Returns:
pc(ndarray): Point cloud in camera coordinate. pc (np.ndarray): Point cloud in camera coordinate.
""" """
# Project upright depth to depth coordinate # Project upright depth to depth coordinate
pc2 = np.dot(np.transpose(self.Rtilt), np.transpose(pc[:, pc2 = np.dot(np.transpose(self.Rtilt), np.transpose(pc[:,
...@@ -146,11 +146,11 @@ class SUNRGBD_Calibration(object): ...@@ -146,11 +146,11 @@ class SUNRGBD_Calibration(object):
"""Convert pc coordinate from depth to image. """Convert pc coordinate from depth to image.
Args: Args:
pc(ndarray): Point cloud in depth coordinate. pc (np.ndarray): Point cloud in depth coordinate.
Returns: Returns:
ndarray: [N, 2] uv. np.ndarray: [N, 2] uv.
ndarray: [n,] depth. np.ndarray: [n,] depth.
""" """
pc2 = self.project_upright_depth_to_camera(pc) pc2 = self.project_upright_depth_to_camera(pc)
uv = np.dot(pc2, np.transpose(self.K)) # (n,3) uv = np.dot(pc2, np.transpose(self.K)) # (n,3)
...@@ -173,10 +173,10 @@ def rotz(t): ...@@ -173,10 +173,10 @@ def rotz(t):
"""Rotation about the z-axis. """Rotation about the z-axis.
Args: Args:
t(float): Heading angle. t (float): Heading angle.
Returns: Returns:
ndarray: Transforation matrix np.ndarray: Transforation matrix
""" """
c = np.cos(t) c = np.cos(t)
s = np.sin(t) s = np.sin(t)
...@@ -187,11 +187,11 @@ def transform_from_rot_trans(R, t): ...@@ -187,11 +187,11 @@ def transform_from_rot_trans(R, t):
"""Transforation matrix from rotation matrix and translation vector. """Transforation matrix from rotation matrix and translation vector.
Args: Args:
R(ndarray): Rotation matrix. R (np.ndarray): Rotation matrix.
t(ndarray): Translation vector. t (np.ndarray): Translation vector.
Returns: Returns:
ndarray: Transforation matrix. np.ndarray: Transforation matrix.
""" """
R = R.reshape(3, 3) R = R.reshape(3, 3)
t = t.reshape(3, 1) t = t.reshape(3, 1)
...@@ -229,12 +229,12 @@ def extract_pc_in_box3d(pc, box3d): ...@@ -229,12 +229,12 @@ def extract_pc_in_box3d(pc, box3d):
"""Extract point cloud in box3d. """Extract point cloud in box3d.
Args: Args:
pc(ndarray): [N, 3] Point cloud. pc (np.ndarray): [N, 3] Point cloud.
box3d(ndarray): [8,3] 3d box. box3d (np.ndarray): [8,3] 3d box.
Returns: Returns:
ndarray: Selected point cloud. np.ndarray: Selected point cloud.
ndarray: Indices of selected point cloud. np.ndarray: Indices of selected point cloud.
""" """
box3d_roi_inds = in_hull(pc[:, 0:3], box3d) box3d_roi_inds = in_hull(pc[:, 0:3], box3d)
return pc[box3d_roi_inds, :], box3d_roi_inds return pc[box3d_roi_inds, :], box3d_roi_inds
...@@ -258,11 +258,11 @@ def compute_box_3d(obj, calib): ...@@ -258,11 +258,11 @@ def compute_box_3d(obj, calib):
bounding box into the image plane. bounding box into the image plane.
Args: Args:
obj(SUNObject3d): Instance of SUNObject3d. obj (SUNObject3d): Instance of SUNObject3d.
calib(SUNRGBD_Calibration): Instance of SUNRGBD_Calibration. calib (SUNRGBD_Calibration): Instance of SUNRGBD_Calibration.
Returns: Returns:
ndarray: [8,2] array in image coord. np.ndarray: [8,2] array in image coord.
corners_3d: [8,3] array in in upright depth coord. corners_3d: [8,3] array in in upright depth coord.
""" """
center = obj.centroid center = obj.centroid
......
...@@ -85,7 +85,7 @@ class Anchor3DRangeGenerator(object): ...@@ -85,7 +85,7 @@ class Anchor3DRangeGenerator(object):
multiple feature levels. multiple feature levels.
device (str): Device where the anchors will be put on. device (str): Device where the anchors will be put on.
Return: Returns:
list[torch.Tensor]: Anchors in multiple feature levels. list[torch.Tensor]: Anchors in multiple feature levels.
The sizes of each tensor should be [N, 4], where The sizes of each tensor should be [N, 4], where
N = width * height * num_base_anchors, width and height N = width * height * num_base_anchors, width and height
......
...@@ -19,18 +19,18 @@ def box_camera_to_lidar(data, r_rect, velo2cam): ...@@ -19,18 +19,18 @@ def box_camera_to_lidar(data, r_rect, velo2cam):
def corners_nd(dims, origin=0.5): def corners_nd(dims, origin=0.5):
"""generate relative box corners based on length per dim and """Generate relative box corners based on length per dim and
origin point. origin point.
Args: Args:
dims (float array, shape=[N, ndim]): array of length per dim dims (np.ndarray, shape=[N, ndim]): Array of length per dim
origin (list or array or float): origin point relate to smallest point. origin (list or array or float): origin point relate to smallest point.
Returns: Returns:
float array, shape=[N, 2 ** ndim, ndim]: returned corners. np.ndarray, shape=[N, 2 ** ndim, ndim]: Returned corners.
point layout example: (2d) x0y0, x0y1, x1y0, x1y1; point layout example: (2d) x0y0, x0y1, x1y0, x1y1;
(3d) x0y0z0, x0y0z1, x0y1z0, x0y1z1, x1y0z0, x1y0z1, x1y1z0, x1y1z1 (3d) x0y0z0, x0y0z1, x0y1z0, x0y1z1, x1y0z0, x1y0z1, x1y1z0, x1y1z1
where x0 < x1, y0 < y1, z0 < z1 where x0 < x1, y0 < y1, z0 < z1.
""" """
ndim = int(dims.shape[1]) ndim = int(dims.shape[1])
corners_norm = np.stack( corners_norm = np.stack(
...@@ -53,14 +53,14 @@ def corners_nd(dims, origin=0.5): ...@@ -53,14 +53,14 @@ def corners_nd(dims, origin=0.5):
def rotation_2d(points, angles): def rotation_2d(points, angles):
"""rotation 2d points based on origin point clockwise when angle positive. """Rotation 2d points based on origin point clockwise when angle positive.
Args: Args:
points (float array, shape=[N, point_size, 2]): points to be rotated. points (np.ndarray, shape=[N, point_size, 2]): points to be rotated.
angles (float array, shape=[N]): rotation angle. angles (np.ndarray, shape=[N]): rotation angle.
Returns: Returns:
float array: same shape as points np.ndarray: Same shape as points.
""" """
rot_sin = np.sin(angles) rot_sin = np.sin(angles)
rot_cos = np.cos(angles) rot_cos = np.cos(angles)
...@@ -69,16 +69,16 @@ def rotation_2d(points, angles): ...@@ -69,16 +69,16 @@ def rotation_2d(points, angles):
def center_to_corner_box2d(centers, dims, angles=None, origin=0.5): def center_to_corner_box2d(centers, dims, angles=None, origin=0.5):
"""convert kitti locations, dimensions and angles to corners. """Convert kitti locations, dimensions and angles to corners.
format: center(xy), dims(xy), angles(clockwise when positive) format: center(xy), dims(xy), angles(clockwise when positive)
Args: Args:
centers (float array, shape=[N, 2]): locations in kitti label file. centers (np.ndarray, shape=[N, 2]): locations in kitti label file.
dims (float array, shape=[N, 2]): dimensions in kitti label file. dims (np.ndarray, shape=[N, 2]): dimensions in kitti label file.
angles (float array, shape=[N]): rotation_y in kitti label file. angles (np.ndarray, shape=[N]): rotation_y in kitti label file.
Returns: Returns:
[type]: [description] np.ndarray: Corners with the shape of [N, 4, 2].
""" """
# 'length' in kitti format is in x axis. # 'length' in kitti format is in x axis.
# xyz(hwl)(kitti label file)<->xyz(lhw)(camera)<->z(-x)(-y)(wlh)(lidar) # xyz(hwl)(kitti label file)<->xyz(lhw)(camera)<->z(-x)(-y)(wlh)(lidar)
...@@ -141,17 +141,18 @@ def center_to_corner_box3d(centers, ...@@ -141,17 +141,18 @@ def center_to_corner_box3d(centers,
angles=None, angles=None,
origin=(0.5, 1.0, 0.5), origin=(0.5, 1.0, 0.5),
axis=1): axis=1):
"""convert kitti locations, dimensions and angles to corners """Convert kitti locations, dimensions and angles to corners.
Args: Args:
centers (float array, shape=[N, 3]): locations in kitti label file. centers (np.ndarray, shape=[N, 3]): Locations in kitti label file.
dims (float array, shape=[N, 3]): dimensions in kitti label file. dims (np.ndarray, shape=[N, 3]): Dimensions in kitti label file.
angles (float array, shape=[N]): rotation_y in kitti label file. angles (np.ndarray, shape=[N]): Rotation_y in kitti label file.
origin (list or array or float): origin point relate to smallest point. origin (list or array or float): Origin point relate to smallest point.
use (0.5, 1.0, 0.5) in camera and (0.5, 0.5, 0) in lidar. use (0.5, 1.0, 0.5) in camera and (0.5, 0.5, 0) in lidar.
axis (int): rotation axis. 1 for camera and 2 for lidar. axis (int): Rotation axis. 1 for camera and 2 for lidar.
Returns: Returns:
[type]: [description] np.ndarray: Corners with the shape of [N, 8, 3].
""" """
# 'length' in kitti format is in x axis. # 'length' in kitti format is in x axis.
# yzx(hwl)(kitti label file)<->xyz(lhw)(camera)<->z(-x)(-y)(wlh)(lidar) # yzx(hwl)(kitti label file)<->xyz(lhw)(camera)<->z(-x)(-y)(wlh)(lidar)
...@@ -202,13 +203,15 @@ def corner_to_standup_nd_jit(boxes_corner): ...@@ -202,13 +203,15 @@ def corner_to_standup_nd_jit(boxes_corner):
@numba.jit(nopython=True) @numba.jit(nopython=True)
def corner_to_surfaces_3d_jit(corners): def corner_to_surfaces_3d_jit(corners):
"""convert 3d box corners from corner function above """Convert 3d box corners from corner function above
to surfaces that normal vectors all direct to internal. to surfaces that normal vectors all direct to internal.
Args: Args:
corners (float array, [N, 8, 3]): 3d box corners. corners (np.ndarray, [N, 8, 3]): 3d box corners
with the shape of [N, 8, 3].
Returns: Returns:
surfaces (float array, [N, 6, 4, 3]): np.ndarray: Surfaces with the shape of [N, 6, 4, 3].
""" """
# box_corners: [N, 8, 3], must from corner functions in this module # box_corners: [N, 8, 3], must from corner functions in this module
num_boxes = corners.shape[0] num_boxes = corners.shape[0]
...@@ -270,9 +273,10 @@ def corner_to_surfaces_3d(corners): ...@@ -270,9 +273,10 @@ def corner_to_surfaces_3d(corners):
to surfaces that normal vectors all direct to internal. to surfaces that normal vectors all direct to internal.
Args: Args:
corners (float array, [N, 8, 3]): 3d box corners. corners (np.ndarray, [N, 8, 3]): 3d box corners.
Returns: Returns:
surfaces (float array, [N, 6, 4, 3]): np.ndarray: Surfaces with the shape of [N, 6, 4, 3].
""" """
# box_corners: [N, 8, 3], must from corner functions in this module # box_corners: [N, 8, 3], must from corner functions in this module
surfaces = np.array([ surfaces = np.array([
...@@ -318,7 +322,7 @@ def create_anchors_3d_range(feature_size, ...@@ -318,7 +322,7 @@ def create_anchors_3d_range(feature_size,
sizes: [N, 3] list of list or array, size of anchors, xyz sizes: [N, 3] list of list or array, size of anchors, xyz
Returns: Returns:
anchors: [*feature_size, num_sizes, num_rots, 7] tensor. np.ndarray: [*feature_size, num_sizes, num_rots, 7].
""" """
anchor_range = np.array(anchor_range, dtype) anchor_range = np.array(anchor_range, dtype)
z_centers = np.linspace( z_centers = np.linspace(
...@@ -358,10 +362,13 @@ def center_to_minmax_2d(centers, dims, origin=0.5): ...@@ -358,10 +362,13 @@ def center_to_minmax_2d(centers, dims, origin=0.5):
def rbbox2d_to_near_bbox(rbboxes): def rbbox2d_to_near_bbox(rbboxes):
"""convert rotated bbox to nearest 'standing' or 'lying' bbox. """convert rotated bbox to nearest 'standing' or 'lying' bbox.
Args: Args:
rbboxes: [N, 5(x, y, xdim, ydim, rad)] rotated bboxes rbboxes (np.ndarray): [N, 5(x, y, xdim, ydim, rad)] rotated bboxes.
Returns: Returns:
bboxes: [N, 4(xmin, ymin, xmax, ymax)] bboxes np.ndarray: Bboxes with the shpae of
[N, 4(xmin, ymin, xmax, ymax)].
""" """
rots = rbboxes[..., -1] rots = rbboxes[..., -1]
rots_0_pi_div_2 = np.abs(limit_period(rots, 0.5, np.pi)) rots_0_pi_div_2 = np.abs(limit_period(rots, 0.5, np.pi))
...@@ -373,15 +380,16 @@ def rbbox2d_to_near_bbox(rbboxes): ...@@ -373,15 +380,16 @@ def rbbox2d_to_near_bbox(rbboxes):
@numba.jit(nopython=True) @numba.jit(nopython=True)
def iou_jit(boxes, query_boxes, mode='iou', eps=0.0): def iou_jit(boxes, query_boxes, mode='iou', eps=0.0):
"""calculate box iou. note that jit version runs ~10x faster than the """Calculate box iou. note that jit version runs ~10x faster than the
box_overlaps function in mmdet3d.core.evaluation box_overlaps function in mmdet3d.core.evaluation.
Parameters
---------- Args:
boxes: (N, 4) ndarray of float boxes (np.ndarray): (N, 4) ndarray of float
query_boxes: (K, 4) ndarray of float query_boxes (np.ndarray): (K, 4) ndarray of float
Returns
------- Returns:
overlaps: (N, K) ndarray of overlap between boxes and query_boxes np.ndarray: Overlap between boxes and query_boxes
with the shape of [N, K].
""" """
N = boxes.shape[0] N = boxes.shape[0]
K = query_boxes.shape[0] K = query_boxes.shape[0]
...@@ -502,17 +510,19 @@ def _points_in_convex_polygon_3d_jit(points, polygon_surfaces, normal_vec, d, ...@@ -502,17 +510,19 @@ def _points_in_convex_polygon_3d_jit(points, polygon_surfaces, normal_vec, d,
def points_in_convex_polygon_3d_jit(points, def points_in_convex_polygon_3d_jit(points,
polygon_surfaces, polygon_surfaces,
num_surfaces=None): num_surfaces=None):
"""check points is in 3d convex polygons. """Check points is in 3d convex polygons.
Args: Args:
points: [num_points, 3] array. points (np.ndarray): [num_points, 3] array.
polygon_surfaces: [num_polygon, max_num_surfaces, polygon_surfaces (np.ndarray): [num_polygon, max_num_surfaces,
max_num_points_of_surface, 3] max_num_points_of_surface, 3]
array. all surfaces' normal vector must direct to internal. array. all surfaces' normal vector must direct to internal.
max_num_points_of_surface must at least 3. max_num_points_of_surface must at least 3.
num_surfaces: [num_polygon] array. indicate how many surfaces num_surfaces (np.ndarray): [num_polygon] array.
a polygon contain indicate how many surfaces a polygon contain
Returns: Returns:
[num_points, num_polygon] bool array. np.ndarray: Result matrix with the shape of [num_points, num_polygon].
""" """
max_num_surfaces, max_num_points_of_surface = polygon_surfaces.shape[1:3] max_num_surfaces, max_num_points_of_surface = polygon_surfaces.shape[1:3]
# num_points = points.shape[0] # num_points = points.shape[0]
...@@ -528,13 +538,16 @@ def points_in_convex_polygon_3d_jit(points, ...@@ -528,13 +538,16 @@ def points_in_convex_polygon_3d_jit(points,
@numba.jit @numba.jit
def points_in_convex_polygon_jit(points, polygon, clockwise=True): def points_in_convex_polygon_jit(points, polygon, clockwise=True):
"""check points is in 2d convex polygons. True when point in polygon """Check points is in 2d convex polygons. True when point in polygon.
Args: Args:
points: [num_points, 2] array. points (np.ndarray): Input points with the shape of [num_points, 2].
polygon: [num_polygon, num_points_of_polygon, 2] array. polygon (dnarray): Input polygon with the shape of
clockwise: bool. indicate polygon is clockwise. [num_polygon, num_points_of_polygon, 2].
clockwise (bool): Indicate polygon is clockwise.
Returns: Returns:
[num_points, num_polygon] bool array. np.ndarray: Result matrix with the shape of [num_points, num_polygon].
""" """
# first convert polygon to directed lines # first convert polygon to directed lines
num_points_of_polygon = polygon.shape[1] num_points_of_polygon = polygon.shape[1]
...@@ -569,7 +582,7 @@ def points_in_convex_polygon_jit(points, polygon, clockwise=True): ...@@ -569,7 +582,7 @@ def points_in_convex_polygon_jit(points, polygon, clockwise=True):
def boxes3d_to_corners3d_lidar(boxes3d, bottom_center=True): def boxes3d_to_corners3d_lidar(boxes3d, bottom_center=True):
"""convert kitti center boxes to corners """Convert kitti center boxes to corners.
7 -------- 4 7 -------- 4
/| /| /| /|
...@@ -580,12 +593,12 @@ def boxes3d_to_corners3d_lidar(boxes3d, bottom_center=True): ...@@ -580,12 +593,12 @@ def boxes3d_to_corners3d_lidar(boxes3d, bottom_center=True):
2 -------- 1 2 -------- 1
Args: Args:
boxes3d (numpy.array): (N, 7) [x, y, z, w, l, h, ry] in LiDAR coords, boxes3d (np.ndarray): (N, 7) [x, y, z, w, l, h, ry] in LiDAR coords,
see the definition of ry in KITTI dataset see the definition of ry in KITTI dataset
bottom_center (bool): whether z is on the bottom center of object. bottom_center (bool): whether z is on the bottom center of object.
Returns: Returns:
numpy.array: box corners with shape (N, 8, 3) np.ndarray: Box corners with the shape of [N, 8, 3].
""" """
boxes_num = boxes3d.shape[0] boxes_num = boxes3d.shape[0]
w, l, h = boxes3d[:, 3], boxes3d[:, 4], boxes3d[:, 5] w, l, h = boxes3d[:, 3], boxes3d[:, 4], boxes3d[:, 5]
......
...@@ -7,15 +7,15 @@ def limit_period(val, offset=0.5, period=np.pi): ...@@ -7,15 +7,15 @@ def limit_period(val, offset=0.5, period=np.pi):
def corners_nd(dims, origin=0.5): def corners_nd(dims, origin=0.5):
"""generate relative box corners based on length per dim and """Generate relative box corners based on length per dim and
origin point. origin point.
Args: Args:
dims (float array, shape=[N, ndim]): array of length per dim dims (np.ndarray, shape=[N, ndim]): Array of length per dim
origin (list or array or float): origin point relate to smallest point. origin (list or array or float): Origin point relate to smallest point.
Returns: Returns:
float array, shape=[N, 2 ** ndim, ndim]: returned corners. np.ndarray: Corners of boxes in shape [N, 2 ** ndim, ndim].
point layout example: (2d) x0y0, x0y1, x1y0, x1y1; point layout example: (2d) x0y0, x0y1, x1y0, x1y1;
(3d) x0y0z0, x0y0z1, x0y1z0, x0y1z1, x1y0z0, x1y0z1, x1y1z0, x1y1z1 (3d) x0y0z0, x0y0z1, x0y1z0, x0y1z1, x1y0z0, x1y0z1, x1y1z0, x1y1z1
where x0 < x1, y0 < y1, z0 < z1 where x0 < x1, y0 < y1, z0 < z1
...@@ -76,17 +76,21 @@ def center_to_corner_box3d(centers, ...@@ -76,17 +76,21 @@ def center_to_corner_box3d(centers,
angles, angles,
origin=(0.5, 1.0, 0.5), origin=(0.5, 1.0, 0.5),
axis=1): axis=1):
"""convert kitti locations, dimensions and angles to corners """Convert kitti locations, dimensions and angles to corners.
Args: Args:
centers (float array, shape=[N, 3]): locations in kitti label file. centers (np.ndarray): Locations in kitti label file
dims (float array, shape=[N, 3]): dimensions in kitti label file. with the shape of [N, 3].
angles (float array, shape=[N]): rotation_y in kitti label file. dims (np.ndarray): Dimensions in kitti label
origin (list or array or float): origin point relate to smallest point. file with the shape of [N, 3]
angles (np.ndarray): Rotation_y in kitti
label file with the shape of [N]
origin (list or array or float): Origin point relate to smallest point.
use (0.5, 1.0, 0.5) in camera and (0.5, 0.5, 0) in lidar. use (0.5, 1.0, 0.5) in camera and (0.5, 0.5, 0) in lidar.
axis (int): rotation axis. 1 for camera and 2 for lidar. axis (int): Rotation axis. 1 for camera and 2 for lidar.
Returns: Returns:
[type]: [description] torch.Tensor: Corners with the shape of [N, 8, 3].
""" """
# 'length' in kitti format is in x axis. # 'length' in kitti format is in x axis.
# yzx(hwl)(kitti label file)<->xyz(lhw)(camera)<->z(-x)(-y)(wlh)(lidar) # yzx(hwl)(kitti label file)<->xyz(lhw)(camera)<->z(-x)(-y)(wlh)(lidar)
...@@ -130,9 +134,10 @@ def rbbox2d_to_near_bbox(rbboxes): ...@@ -130,9 +134,10 @@ def rbbox2d_to_near_bbox(rbboxes):
"""convert rotated bbox to nearest 'standing' or 'lying' bbox. """convert rotated bbox to nearest 'standing' or 'lying' bbox.
Args: Args:
rbboxes: [N, 5(x, y, xdim, ydim, rad)] rotated bboxes rbboxes (torch.Tensor): [N, 5(x, y, xdim, ydim, rad)] rotated bboxes.
Returns: Returns:
bboxes: [N, 4(xmin, ymin, xmax, ymax)] bboxes torch.Tensor: Bboxes with the shape of [N, 4(xmin, ymin, xmax, ymax)].
""" """
rots = rbboxes[..., -1] rots = rbboxes[..., -1]
rots_0_pi_div_2 = torch.abs(limit_period(rots, 0.5, np.pi)) rots_0_pi_div_2 = torch.abs(limit_period(rots, 0.5, np.pi))
...@@ -154,16 +159,16 @@ def center_to_minmax_2d(centers, dims, origin=0.5): ...@@ -154,16 +159,16 @@ def center_to_minmax_2d(centers, dims, origin=0.5):
def center_to_corner_box2d(centers, dims, angles=None, origin=0.5): def center_to_corner_box2d(centers, dims, angles=None, origin=0.5):
"""convert kitti locations, dimensions and angles to corners. """Convert kitti locations, dimensions and angles to corners.
format: center(xy), dims(xy), angles(clockwise when positive) format: center(xy), dims(xy), angles(clockwise when positive)
Args: Args:
centers (float array, shape=[N, 2]): locations in kitti label file. centers (np.ndarray, shape=[N, 2]): locations in kitti label file.
dims (float array, shape=[N, 2]): dimensions in kitti label file. dims (np.ndarray, shape=[N, 2]): dimensions in kitti label file.
angles (float array, shape=[N]): rotation_y in kitti label file. angles (np.ndarray, shape=[N]): rotation_y in kitti label file.
Returns: Returns:
[type]: [description] torch.Tensor: Corners with the shape of [N, 4, 2].
""" """
# 'length' in kitti format is in x axis. # 'length' in kitti format is in x axis.
# xyz(hwl)(kitti label file)<->xyz(lhw)(camera)<->z(-x)(-y)(wlh)(lidar) # xyz(hwl)(kitti label file)<->xyz(lhw)(camera)<->z(-x)(-y)(wlh)(lidar)
...@@ -180,11 +185,11 @@ def rotation_2d(points, angles): ...@@ -180,11 +185,11 @@ def rotation_2d(points, angles):
"""rotation 2d points based on origin point clockwise when angle positive. """rotation 2d points based on origin point clockwise when angle positive.
Args: Args:
points (float array, shape=[N, point_size, 2]): points to be rotated. points (np.ndarray, shape=[N, point_size, 2]): points to be rotated.
angles (float array, shape=[N]): rotation angle. angles (np.ndarray, shape=[N]): rotation angle.
Returns: Returns:
float array: same shape as points np.ndarray: Same shape as points.
""" """
rot_sin = torch.sin(angles) rot_sin = torch.sin(angles)
rot_cos = torch.cos(angles) rot_cos = torch.cos(angles)
...@@ -213,7 +218,7 @@ def enlarge_box3d_lidar(boxes3d, extra_width): ...@@ -213,7 +218,7 @@ def enlarge_box3d_lidar(boxes3d, extra_width):
def boxes3d_to_corners3d_lidar_torch(boxes3d, bottom_center=True): def boxes3d_to_corners3d_lidar_torch(boxes3d, bottom_center=True):
"""convert kitti center boxes to corners """Convert kitti center boxes to corners.
7 -------- 4 7 -------- 4
/| /| /| /|
......
...@@ -12,21 +12,30 @@ class DeltaXYZWLHRBBoxCoder(BaseBBoxCoder): ...@@ -12,21 +12,30 @@ class DeltaXYZWLHRBBoxCoder(BaseBBoxCoder):
self.code_size = code_size self.code_size = code_size
@staticmethod @staticmethod
def encode(anchors, boxes): def encode(src_boxes, dst_boxes):
""" """Get box regression transformation deltas
:param boxes: (N, 7+n) x, y, z, w, l, h, r, velo* (dx, dy, dz, dw, dh, dl, dr, dv*) that can be used
:param anchors: (N, 7+n) to transform the `src_boxes` into the `target_boxes`.
:return:
Args:
src_boxes (torch.Tensor): source boxes, e.g., object proposals.
dst_boxes (torch.Tensor): target of the transformation, e.g.,
ground-truth boxes.
Returns:
torch.Tensor: Box transformation deltas
""" """
box_ndim = anchors.shape[-1] box_ndim = src_boxes.shape[-1]
cas, cgs, cts = [], [], [] cas, cgs, cts = [], [], []
if box_ndim > 7: if box_ndim > 7:
xa, ya, za, wa, la, ha, ra, *cas = torch.split(anchors, 1, dim=-1) xa, ya, za, wa, la, ha, ra, *cas = torch.split(
xg, yg, zg, wg, lg, hg, rg, *cgs = torch.split(boxes, 1, dim=-1) src_boxes, 1, dim=-1)
xg, yg, zg, wg, lg, hg, rg, *cgs = torch.split(
dst_boxes, 1, dim=-1)
cts = [g - a for g, a in zip(cgs, cas)] cts = [g - a for g, a in zip(cgs, cas)]
else: else:
xa, ya, za, wa, la, ha, ra = torch.split(anchors, 1, dim=-1) xa, ya, za, wa, la, ha, ra = torch.split(src_boxes, 1, dim=-1)
xg, yg, zg, wg, lg, hg, rg = torch.split(boxes, 1, dim=-1) xg, yg, zg, wg, lg, hg, rg = torch.split(dst_boxes, 1, dim=-1)
za = za + ha / 2 za = za + ha / 2
zg = zg + hg / 2 zg = zg + hg / 2
diagonal = torch.sqrt(la**2 + wa**2) diagonal = torch.sqrt(la**2 + wa**2)
...@@ -40,21 +49,25 @@ class DeltaXYZWLHRBBoxCoder(BaseBBoxCoder): ...@@ -40,21 +49,25 @@ class DeltaXYZWLHRBBoxCoder(BaseBBoxCoder):
return torch.cat([xt, yt, zt, wt, lt, ht, rt, *cts], dim=-1) return torch.cat([xt, yt, zt, wt, lt, ht, rt, *cts], dim=-1)
@staticmethod @staticmethod
def decode(anchors, box_encodings): def decode(anchors, deltas):
""" """Apply transformation `deltas` (dx, dy, dz, dw, dh, dl, dr, dv*) to `boxes`.
:param box_encodings: (N, 7 + n) x, y, z, w, l, h, r
:param anchors: (N, 7) Args:
:return: anchors (torch.Tensor): Parameters of anchors with shape (N, 7).
deltas (torch.Tensor): Encoded boxes with shape
(N, 7+n) [x, y, z, w, l, h, r, velo*].
Returns:
torch.Tensor: Decoded boxes.
""" """
cas, cts = [], [] cas, cts = [], []
box_ndim = anchors.shape[-1] box_ndim = anchors.shape[-1]
if box_ndim > 7: if box_ndim > 7:
xa, ya, za, wa, la, ha, ra, *cas = torch.split(anchors, 1, dim=-1) xa, ya, za, wa, la, ha, ra, *cas = torch.split(anchors, 1, dim=-1)
xt, yt, zt, wt, lt, ht, rt, *cts = torch.split( xt, yt, zt, wt, lt, ht, rt, *cts = torch.split(deltas, 1, dim=-1)
box_encodings, 1, dim=-1)
else: else:
xa, ya, za, wa, la, ha, ra = torch.split(anchors, 1, dim=-1) xa, ya, za, wa, la, ha, ra = torch.split(anchors, 1, dim=-1)
xt, yt, zt, wt, lt, ht, rt = torch.split(box_encodings, 1, dim=-1) xt, yt, zt, wt, lt, ht, rt = torch.split(deltas, 1, dim=-1)
za = za + ha / 2 za = za + ha / 2
diagonal = torch.sqrt(la**2 + wa**2) diagonal = torch.sqrt(la**2 + wa**2)
......
...@@ -28,9 +28,8 @@ class PartialBinBasedBBoxCoder(BaseBBoxCoder): ...@@ -28,9 +28,8 @@ class PartialBinBasedBBoxCoder(BaseBBoxCoder):
"""Encode ground truth to prediction targets. """Encode ground truth to prediction targets.
Args: Args:
gt_bboxes_3d (:obj:BaseInstance3DBoxes): gt bboxes with gt_bboxes_3d (BaseInstance3DBoxes): gt bboxes with shape (n, 7).
shape (n, 7). gt_labels_3d (torch.Tensor): gt classes.
gt_labels_3d (Tensor): gt classes.
Returns: Returns:
tuple: Targets of center, size and direction. tuple: Targets of center, size and direction.
...@@ -67,7 +66,7 @@ class PartialBinBasedBBoxCoder(BaseBBoxCoder): ...@@ -67,7 +66,7 @@ class PartialBinBasedBBoxCoder(BaseBBoxCoder):
- size_res: predicted bbox size residual. - size_res: predicted bbox size residual.
Returns: Returns:
Tensor: decoded bbox3d with shape (batch, n, 7) torch.Tensor: decoded bbox3d with shape (batch, n, 7)
""" """
center = bbox_out['center'] center = bbox_out['center']
batch_size, num_proposal = center.shape[:2] batch_size, num_proposal = center.shape[:2]
...@@ -99,8 +98,8 @@ class PartialBinBasedBBoxCoder(BaseBBoxCoder): ...@@ -99,8 +98,8 @@ class PartialBinBasedBBoxCoder(BaseBBoxCoder):
"""Split predicted features to specific parts. """Split predicted features to specific parts.
Args: Args:
preds (Tensor): predicted features to split. preds (torch.Tensor): predicted features to split.
base_xyz (Tensor): coordinates of points. base_xyz (torch.Tensor): coordinates of points.
Returns: Returns:
dict: split results. dict: split results.
...@@ -161,8 +160,8 @@ class PartialBinBasedBBoxCoder(BaseBBoxCoder): ...@@ -161,8 +160,8 @@ class PartialBinBasedBBoxCoder(BaseBBoxCoder):
regression number from class center angle to current angle. regression number from class center angle to current angle.
Args: Args:
angle (Tensor): Angle is from 0-2pi (or -pi~pi), class center at angle (torch.Tensor): Angle is from 0-2pi (or -pi~pi),
0, 1*(2pi/N), 2*(2pi/N) ... (N-1)*(2pi/N) class center at 0, 1*(2pi/N), 2*(2pi/N) ... (N-1)*(2pi/N).
Returns: Returns:
tuple: Encoded discrete class and residual. tuple: Encoded discrete class and residual.
...@@ -179,12 +178,12 @@ class PartialBinBasedBBoxCoder(BaseBBoxCoder): ...@@ -179,12 +178,12 @@ class PartialBinBasedBBoxCoder(BaseBBoxCoder):
"""Inverse function to angle2class """Inverse function to angle2class
Args: Args:
angle_cls (Tensor): Angle class to decode. angle_cls (torch.Tensor): Angle class to decode.
angle_res (Tensor): Angle residual to decode. angle_res (torch.Tensor): Angle residual to decode.
limit_period (bool): Whether to limit angle to [-pi, pi]. limit_period (bool): Whether to limit angle to [-pi, pi].
Returns: Returns:
Tensor: angle decoded from angle_cls and angle_res. torch.Tensor: angle decoded from angle_cls and angle_res.
""" """
angle_per_class = 2 * np.pi / float(self.num_dir_bins) angle_per_class = 2 * np.pi / float(self.num_dir_bins)
angle_center = angle_cls.float() * angle_per_class angle_center = angle_cls.float() * angle_per_class
......
...@@ -46,13 +46,14 @@ def bbox_overlaps_nearest_3d(bboxes1, bboxes2, mode='iou', is_aligned=False): ...@@ -46,13 +46,14 @@ def bbox_overlaps_nearest_3d(bboxes1, bboxes2, mode='iou', is_aligned=False):
"""Calculate nearest 3D IoU """Calculate nearest 3D IoU
Args: Args:
bboxes1: Tensor, shape (N, 7+N) [x, y, z, h, w, l, ry, v] bboxes1 (torch.Tensor): shape (N, 7+N) [x, y, z, h, w, l, ry, v].
bboxes2: Tensor, shape (M, 7+N) [x, y, z, h, w, l, ry, v] bboxes2 (torch.Tensor): shape (M, 7+N) [x, y, z, h, w, l, ry, v].
mode: mode (str): "iou" (intersection over union) or iof mode (str): "iou" (intersection over union) or iof
(intersection over foreground). (intersection over foreground).
Return: Return:
iou: (M, N) not support aligned mode currently torch.Tensor: Bbox overlaps results of bboxes1 and bboxes2
with shape (M, N).(not support aligned mode currently).
""" """
assert bboxes1.size(-1) >= 7 assert bboxes1.size(-1) >= 7
assert bboxes2.size(-1) >= 7 assert bboxes2.size(-1) >= 7
...@@ -74,14 +75,15 @@ def bbox_overlaps_3d(bboxes1, bboxes2, mode='iou', coordinate='camera'): ...@@ -74,14 +75,15 @@ def bbox_overlaps_3d(bboxes1, bboxes2, mode='iou', coordinate='camera'):
"""Calculate 3D IoU using cuda implementation """Calculate 3D IoU using cuda implementation
Args: Args:
bboxes1: Tensor, shape (N, 7) [x, y, z, h, w, l, ry] bboxes1 (torch.Tensor): shape (N, 7) [x, y, z, h, w, l, ry].
bboxes2: Tensor, shape (M, 7) [x, y, z, h, w, l, ry] bboxes2 (torch.Tensor): shape (M, 7) [x, y, z, h, w, l, ry].
mode: mode (str): "iou" (intersection over union) or mode (str): "iou" (intersection over union) or
iof (intersection over foreground). iof (intersection over foreground).
coordinate (str): 'camera' or 'lidar' coordinate system coordinate (str): 'camera' or 'lidar' coordinate system.
Return: Return:
iou: (M, N) not support aligned mode currently torch.Tensor: Bbox overlaps results of bboxes1 and bboxes2
with shape (M, N).(not support aligned mode currently).
""" """
assert bboxes1.size(-1) == bboxes2.size(-1) == 7 assert bboxes1.size(-1) == bboxes2.size(-1) == 7
assert coordinate in ['camera', 'lidar'] assert coordinate in ['camera', 'lidar']
......
...@@ -6,7 +6,7 @@ from . import RandomSampler, SamplingResult ...@@ -6,7 +6,7 @@ from . import RandomSampler, SamplingResult
@BBOX_SAMPLERS.register_module() @BBOX_SAMPLERS.register_module()
class IoUNegPiecewiseSampler(RandomSampler): class IoUNegPiecewiseSampler(RandomSampler):
"""IoU Piece-wise Sampling """IoU Piece-wise Sampling.
Sampling negtive proposals according to a list of IoU thresholds. Sampling negtive proposals according to a list of IoU thresholds.
The negtive proposals are divided into several pieces according The negtive proposals are divided into several pieces according
......
...@@ -247,7 +247,7 @@ class BaseInstance3DBoxes(object): ...@@ -247,7 +247,7 @@ class BaseInstance3DBoxes(object):
"""Scale the box with horizontal and vertical scaling factors """Scale the box with horizontal and vertical scaling factors
Args: Args:
scale_factors (float): scale factors to scale the boxes. scale_factors (float): Scale factors to scale the boxes.
""" """
self.tensor[:, :6] *= scale_factor self.tensor[:, :6] *= scale_factor
self.tensor[:, 7:] *= scale_factor self.tensor[:, 7:] *= scale_factor
...@@ -256,8 +256,8 @@ class BaseInstance3DBoxes(object): ...@@ -256,8 +256,8 @@ class BaseInstance3DBoxes(object):
"""Limit the yaw to a given period and offset """Limit the yaw to a given period and offset
Args: Args:
offset (float): the offset of the yaw offset (float): The offset of the yaw.
period (float): the expected period period (float): The expected period.
""" """
self.tensor[:, 6] = limit_period(self.tensor[:, 6], offset, period) self.tensor[:, 6] = limit_period(self.tensor[:, 6], offset, period)
...@@ -268,10 +268,10 @@ class BaseInstance3DBoxes(object): ...@@ -268,10 +268,10 @@ class BaseInstance3DBoxes(object):
if either of its side is no larger than threshold. if either of its side is no larger than threshold.
Args: Args:
threshold (float): the threshold of minimal sizes threshold (float): The threshold of minimal sizes.
Returns: Returns:
torch.Tensor: a binary vector which represents whether each torch.Tensor: A binary vector which represents whether each
box is empty (False) or non-empty (True). box is empty (False) or non-empty (True).
""" """
box = self.tensor box = self.tensor
...@@ -321,11 +321,11 @@ class BaseInstance3DBoxes(object): ...@@ -321,11 +321,11 @@ class BaseInstance3DBoxes(object):
def cat(cls, boxes_list): def cat(cls, boxes_list):
"""Concatenates a list of Boxes into a single Boxes """Concatenates a list of Boxes into a single Boxes
Arguments: Args:
boxes_list (list[Boxes]) boxes_list (list[Boxes]): List of boxes.
Returns: Returns:
Boxes: the concatenated Boxes Boxes: The concatenated Boxes.
""" """
assert isinstance(boxes_list, (list, tuple)) assert isinstance(boxes_list, (list, tuple))
if len(boxes_list) == 0: if len(boxes_list) == 0:
...@@ -365,7 +365,7 @@ class BaseInstance3DBoxes(object): ...@@ -365,7 +365,7 @@ class BaseInstance3DBoxes(object):
"""Yield a box as a Tensor of shape (4,) at a time. """Yield a box as a Tensor of shape (4,) at a time.
Returns: Returns:
torch.Tensor: a box of shape (4,). torch.Tensor: A box of shape (4,).
""" """
yield from self.tensor yield from self.tensor
...@@ -378,12 +378,12 @@ class BaseInstance3DBoxes(object): ...@@ -378,12 +378,12 @@ class BaseInstance3DBoxes(object):
boxes2, boxes1 and boxes2 should be in the same type. boxes2, boxes1 and boxes2 should be in the same type.
Args: Args:
boxes1 (:obj:BaseInstanceBoxes): boxes 1 contain N boxes boxes1 (:obj:BaseInstanceBoxes): Boxes 1 contain N boxes.
boxes2 (:obj:BaseInstanceBoxes): boxes 2 contain M boxes boxes2 (:obj:BaseInstanceBoxes): Boxes 2 contain M boxes.
mode (str, optional): mode of iou calculation. Defaults to 'iou'. mode (str, optional): Mode of iou calculation. Defaults to 'iou'.
Returns: Returns:
torch.Tensor: Calculated iou of boxes torch.Tensor: Calculated iou of boxes.
""" """
assert isinstance(boxes1, BaseInstance3DBoxes) assert isinstance(boxes1, BaseInstance3DBoxes)
assert isinstance(boxes2, BaseInstance3DBoxes) assert isinstance(boxes2, BaseInstance3DBoxes)
...@@ -410,12 +410,12 @@ class BaseInstance3DBoxes(object): ...@@ -410,12 +410,12 @@ class BaseInstance3DBoxes(object):
boxes1 and boxes2 are not necessarily to be in the same type. boxes1 and boxes2 are not necessarily to be in the same type.
Args: Args:
boxes1 (:obj:BaseInstanceBoxes): boxes 1 contain N boxes boxes1 (:obj:BaseInstanceBoxes): Boxes 1 contain N boxes.
boxes2 (:obj:BaseInstanceBoxes): boxes 2 contain M boxes boxes2 (:obj:BaseInstanceBoxes): Boxes 2 contain M boxes.
mode (str, optional): mode of iou calculation. Defaults to 'iou'. mode (str, optional): Mode of iou calculation. Defaults to 'iou'.
Returns: Returns:
torch.Tensor: Calculated iou of boxes torch.Tensor: Calculated iou of boxes.
""" """
assert isinstance(boxes1, BaseInstance3DBoxes) assert isinstance(boxes1, BaseInstance3DBoxes)
assert isinstance(boxes2, BaseInstance3DBoxes) assert isinstance(boxes2, BaseInstance3DBoxes)
......
...@@ -62,19 +62,19 @@ class Box3DMode(IntEnum): ...@@ -62,19 +62,19 @@ class Box3DMode(IntEnum):
"""Convert boxes from `src` mode to `dst` mode. """Convert boxes from `src` mode to `dst` mode.
Args: Args:
box (tuple | list | np.ndarray | box (tuple | list | np.dnarray |
torch.Tensor | BaseInstance3DBoxes): torch.Tensor | BaseInstance3DBoxes):
can be a k-tuple, k-list or an Nxk array/tensor, where k = 7 Can be a k-tuple, k-list or an Nxk array/tensor, where k = 7.
src (BoxMode): the src Box mode src (BoxMode): The src Box mode.
dst (BoxMode): the target Box mode dst (BoxMode): The target Box mode.
rt_mat (np.ndarray | torch.Tensor): The rotation and translation rt_mat (np.dnarray | torch.Tensor): The rotation and translation
matrix between different coordinates. Defaults to None. matrix between different coordinates. Defaults to None.
The conversion from `src` coordinates to `dst` coordinates The conversion from `src` coordinates to `dst` coordinates
usually comes along the change of sensors, e.g., from camera usually comes along the change of sensors, e.g., from camera
to LiDAR. This requires a transformation matrix. to LiDAR. This requires a transformation matrix.
Returns: Returns:
(tuple | list | np.ndarray | torch.Tensor | BaseInstance3DBoxes): (tuple | list | np.dnarray | torch.Tensor | BaseInstance3DBoxes):
The converted box of the same type. The converted box of the same type.
""" """
if src == dst: if src == dst:
......
...@@ -6,7 +6,7 @@ from .utils import limit_period, rotation_3d_in_axis ...@@ -6,7 +6,7 @@ from .utils import limit_period, rotation_3d_in_axis
class CameraInstance3DBoxes(BaseInstance3DBoxes): class CameraInstance3DBoxes(BaseInstance3DBoxes):
"""3D boxes of instances in CAM coordinates """3D boxes of instances in CAM coordinates.
Coordinates in camera: Coordinates in camera:
.. code-block:: none .. code-block:: none
...@@ -26,10 +26,10 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes): ...@@ -26,10 +26,10 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes):
the positive direction of x to the positive direction of z. the positive direction of x to the positive direction of z.
Attributes: Attributes:
tensor (torch.Tensor): float matrix of N x box_dim. tensor (torch.Tensor): Float matrix of N x box_dim.
box_dim (int): integer indicates the dimension of a box box_dim (int): Integer indicates the dimension of a box
Each row is (x, y, z, x_size, y_size, z_size, yaw, ...). Each row is (x, y, z, x_size, y_size, z_size, yaw, ...).
with_yaw (bool): if True, the value of yaw will be set to 0 as minmax with_yaw (bool): If True, the value of yaw will be set to 0 as minmax
boxes. boxes.
""" """
...@@ -38,7 +38,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes): ...@@ -38,7 +38,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes):
"""Obtain the height of all the boxes. """Obtain the height of all the boxes.
Returns: Returns:
torch.Tensor: a vector with height of each box. torch.Tensor: A vector with height of each box.
""" """
return self.tensor[:, 4] return self.tensor[:, 4]
...@@ -47,7 +47,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes): ...@@ -47,7 +47,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes):
"""Obtain the top height of all the boxes. """Obtain the top height of all the boxes.
Returns: Returns:
torch.Tensor: a vector with the top height of each box. torch.Tensor: A vector with the top height of each box.
""" """
# the positive direction is down rather than up # the positive direction is down rather than up
return self.bottom_height - self.height return self.bottom_height - self.height
...@@ -57,7 +57,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes): ...@@ -57,7 +57,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes):
"""Obtain the bottom's height of all the boxes. """Obtain the bottom's height of all the boxes.
Returns: Returns:
torch.Tensor: a vector with bottom's height of each box. torch.Tensor: A vector with bottom's height of each box.
""" """
return self.tensor[:, 1] return self.tensor[:, 1]
...@@ -66,7 +66,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes): ...@@ -66,7 +66,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes):
"""Calculate the gravity center of all the boxes. """Calculate the gravity center of all the boxes.
Returns: Returns:
torch.Tensor: a tensor with center of each box. torch.Tensor: A tensor with center of each box.
""" """
bottom_center = self.bottom_center bottom_center = self.bottom_center
gravity_center = torch.zeros_like(bottom_center) gravity_center = torch.zeros_like(bottom_center)
...@@ -99,7 +99,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes): ...@@ -99,7 +99,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes):
down y down y
Returns: Returns:
torch.Tensor: corners of each box with size (N, 8, 3) torch.Tensor: Corners of each box with size (N, 8, 3)
""" """
# TODO: rotation_3d_in_axis function do not support # TODO: rotation_3d_in_axis function do not support
# empty tensor currently. # empty tensor currently.
...@@ -124,7 +124,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes): ...@@ -124,7 +124,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes):
"""Calculate the 2D bounding boxes in BEV with rotation """Calculate the 2D bounding boxes in BEV with rotation
Returns: Returns:
torch.Tensor: a nx5 tensor of 2D BEV box of each box. torch.Tensor: A nx5 tensor of 2D BEV box of each box.
The box is in XYWHR format. The box is in XYWHR format.
""" """
return self.tensor[:, [0, 2, 3, 5, 6]] return self.tensor[:, [0, 2, 3, 5, 6]]
...@@ -134,7 +134,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes): ...@@ -134,7 +134,7 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes):
"""Calculate the 2D bounding boxes in BEV without rotation """Calculate the 2D bounding boxes in BEV without rotation
Returns: Returns:
torch.Tensor: a tensor of 2D BEV box of each box. torch.Tensor: A tensor of 2D BEV box of each box.
""" """
# Obtain BEV boxes with rotation in XZWHR format # Obtain BEV boxes with rotation in XZWHR format
bev_rotated_boxes = self.bev bev_rotated_boxes = self.bev
...@@ -221,8 +221,8 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes): ...@@ -221,8 +221,8 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes):
"""Check whether the boxes are in the given range """Check whether the boxes are in the given range
Args: Args:
box_range (list | torch.Tensor): the range of box box_range (list | torch.Tensor): The range of box
(x_min, z_min, x_max, z_max) (x_min, z_min, x_max, z_max).
Note: Note:
In the original implementation of SECOND, checking whether In the original implementation of SECOND, checking whether
...@@ -249,12 +249,12 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes): ...@@ -249,12 +249,12 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes):
boxes2, boxes1 and boxes2 should be in the same type. boxes2, boxes1 and boxes2 should be in the same type.
Args: Args:
boxes1 (:obj:BaseInstanceBoxes): boxes 1 contain N boxes boxes1 (:obj:BaseInstanceBoxes): Boxes 1 contain N boxes.
boxes2 (:obj:BaseInstanceBoxes): boxes 2 contain M boxes boxes2 (:obj:BaseInstanceBoxes): Boxes 2 contain M boxes.
mode (str, optional): mode of iou calculation. Defaults to 'iou'. mode (str, optional): Mode of iou calculation. Defaults to 'iou'.
Returns: Returns:
torch.Tensor: Calculated iou of boxes torch.Tensor: Calculated iou of boxes.
""" """
assert isinstance(boxes1, BaseInstance3DBoxes) assert isinstance(boxes1, BaseInstance3DBoxes)
assert isinstance(boxes2, BaseInstance3DBoxes) assert isinstance(boxes2, BaseInstance3DBoxes)
...@@ -278,8 +278,8 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes): ...@@ -278,8 +278,8 @@ class CameraInstance3DBoxes(BaseInstance3DBoxes):
"""Convert self to `dst` mode. """Convert self to `dst` mode.
Args: Args:
dst (BoxMode): the target Box mode dst (BoxMode): The target Box mode.
rt_mat (np.ndarray | torch.Tensor): The rotation and translation rt_mat (np.dnarray | torch.Tensor): The rotation and translation
matrix between different coordinates. Defaults to None. matrix between different coordinates. Defaults to None.
The conversion from `src` coordinates to `dst` coordinates The conversion from `src` coordinates to `dst` coordinates
usually comes along the change of sensors, e.g., from camera usually comes along the change of sensors, e.g., from camera
......
...@@ -7,7 +7,7 @@ from .utils import limit_period, rotation_3d_in_axis ...@@ -7,7 +7,7 @@ from .utils import limit_period, rotation_3d_in_axis
class DepthInstance3DBoxes(BaseInstance3DBoxes): class DepthInstance3DBoxes(BaseInstance3DBoxes):
"""3D boxes of instances in Depth coordinates """3D boxes of instances in Depth coordinates.
Coordinates in Depth: Coordinates in Depth:
.. code-block:: none .. code-block:: none
...@@ -23,11 +23,11 @@ class DepthInstance3DBoxes(BaseInstance3DBoxes): ...@@ -23,11 +23,11 @@ class DepthInstance3DBoxes(BaseInstance3DBoxes):
The yaw is 0 at the positive direction of x axis, and increases from The yaw is 0 at the positive direction of x axis, and increases from
the positive direction of x to the positive direction of y. the positive direction of x to the positive direction of y.
Attributes: Args:
tensor (torch.Tensor): float matrix of N x box_dim. tensor (Tensor): Float matrix of N x box_dim.
box_dim (int): integer indicates the dimension of a box box_dim (int): Integer indicates the dimension of a box
Each row is (x, y, z, x_size, y_size, z_size, yaw, ...). Each row is (x, y, z, x_size, y_size, z_size, yaw, ...).
with_yaw (bool): if True, the value of yaw will be set to 0 as minmax with_yaw (bool): If True, the value of yaw will be set to 0 as minmax
boxes. boxes.
""" """
...@@ -89,17 +89,17 @@ class DepthInstance3DBoxes(BaseInstance3DBoxes): ...@@ -89,17 +89,17 @@ class DepthInstance3DBoxes(BaseInstance3DBoxes):
@property @property
def bev(self): def bev(self):
"""Calculate the 2D bounding boxes in BEV with rotation """Calculate the 2D bounding boxes in BEV with rotation.
Returns: Returns:
torch.Tensor: a nx5 tensor of 2D BEV box of each box. torch.Tensor: A nx5 tensor of 2D BEV box of each box.
The box is in XYWHR format The box is in XYWHR format.
""" """
return self.tensor[:, [0, 1, 3, 4, 6]] return self.tensor[:, [0, 1, 3, 4, 6]]
@property @property
def nearest_bev(self): def nearest_bev(self):
"""Calculate the 2D bounding boxes in BEV without rotation """Calculate the 2D bounding boxes in BEV without rotation.
Returns: Returns:
torch.Tensor: a tensor of 2D BEV box of each box. torch.Tensor: a tensor of 2D BEV box of each box.
...@@ -196,11 +196,11 @@ class DepthInstance3DBoxes(BaseInstance3DBoxes): ...@@ -196,11 +196,11 @@ class DepthInstance3DBoxes(BaseInstance3DBoxes):
return points return points
def in_range_bev(self, box_range): def in_range_bev(self, box_range):
"""Check whether the boxes are in the given range """Check whether the boxes are in the given range.
Args: Args:
box_range (list | torch.Tensor): the range of box box_range (list | torch.Tensor): The range of box
(x_min, y_min, x_max, y_max) (x_min, y_min, x_max, y_max).
Note: Note:
In the original implementation of SECOND, checking whether In the original implementation of SECOND, checking whether
...@@ -222,7 +222,7 @@ class DepthInstance3DBoxes(BaseInstance3DBoxes): ...@@ -222,7 +222,7 @@ class DepthInstance3DBoxes(BaseInstance3DBoxes):
"""Convert self to `dst` mode. """Convert self to `dst` mode.
Args: Args:
dst (BoxMode): the target Box mode dst (BoxMode): The target Box mode.
rt_mat (np.ndarray | torch.Tensor): The rotation and translation rt_mat (np.ndarray | torch.Tensor): The rotation and translation
matrix between different coordinates. Defaults to None. matrix between different coordinates. Defaults to None.
The conversion from `src` coordinates to `dst` coordinates The conversion from `src` coordinates to `dst` coordinates
...@@ -238,7 +238,7 @@ class DepthInstance3DBoxes(BaseInstance3DBoxes): ...@@ -238,7 +238,7 @@ class DepthInstance3DBoxes(BaseInstance3DBoxes):
box=self, src=Box3DMode.DEPTH, dst=dst, rt_mat=rt_mat) box=self, src=Box3DMode.DEPTH, dst=dst, rt_mat=rt_mat)
def points_in_boxes(self, points): def points_in_boxes(self, points):
"""Find points that are in boxes (CUDA) """Find points that are in boxes (CUDA).
Args: Args:
points (torch.Tensor): [1, M, 3] or [M, 3], [x, y, z] points (torch.Tensor): [1, M, 3] or [M, 3], [x, y, z]
......
...@@ -24,10 +24,10 @@ class LiDARInstance3DBoxes(BaseInstance3DBoxes): ...@@ -24,10 +24,10 @@ class LiDARInstance3DBoxes(BaseInstance3DBoxes):
the negative direction of y to the positive direction of x. the negative direction of y to the positive direction of x.
Attributes: Attributes:
tensor (torch.Tensor): float matrix of N x box_dim. tensor (torch.Tensor): Float matrix of N x box_dim.
box_dim (int): integer indicates the dimension of a box box_dim (int): Integer indicates the dimension of a box
Each row is (x, y, z, x_size, y_size, z_size, yaw, ...). Each row is (x, y, z, x_size, y_size, z_size, yaw, ...).
with_yaw (bool): if True, the value of yaw will be set to 0 as minmax with_yaw (bool): If True, the value of yaw will be set to 0 as minmax
boxes. boxes.
""" """
...@@ -36,7 +36,7 @@ class LiDARInstance3DBoxes(BaseInstance3DBoxes): ...@@ -36,7 +36,7 @@ class LiDARInstance3DBoxes(BaseInstance3DBoxes):
"""Calculate the gravity center of all the boxes. """Calculate the gravity center of all the boxes.
Returns: Returns:
torch.Tensor: a tensor with center of each box. torch.Tensor: A tensor with center of each box.
""" """
bottom_center = self.bottom_center bottom_center = self.bottom_center
gravity_center = torch.zeros_like(bottom_center) gravity_center = torch.zeros_like(bottom_center)
...@@ -92,7 +92,7 @@ class LiDARInstance3DBoxes(BaseInstance3DBoxes): ...@@ -92,7 +92,7 @@ class LiDARInstance3DBoxes(BaseInstance3DBoxes):
"""Calculate the 2D bounding boxes in BEV with rotation """Calculate the 2D bounding boxes in BEV with rotation
Returns: Returns:
torch.Tensor: a nx5 tensor of 2D BEV box of each box. torch.Tensor: A nx5 tensor of 2D BEV box of each box.
The box is in XYWHR format The box is in XYWHR format
""" """
return self.tensor[:, [0, 1, 3, 4, 6]] return self.tensor[:, [0, 1, 3, 4, 6]]
...@@ -102,7 +102,7 @@ class LiDARInstance3DBoxes(BaseInstance3DBoxes): ...@@ -102,7 +102,7 @@ class LiDARInstance3DBoxes(BaseInstance3DBoxes):
"""Calculate the 2D bounding boxes in BEV without rotation """Calculate the 2D bounding boxes in BEV without rotation
Returns: Returns:
torch.Tensor: a tensor of 2D BEV box of each box. torch.Tensor: A tensor of 2D BEV box of each box.
""" """
# Obtain BEV boxes with rotation in XYWHR format # Obtain BEV boxes with rotation in XYWHR format
bev_rotated_boxes = self.bev bev_rotated_boxes = self.bev
......
...@@ -6,7 +6,7 @@ def limit_period(val, offset=0.5, period=np.pi): ...@@ -6,7 +6,7 @@ def limit_period(val, offset=0.5, period=np.pi):
"""Limit the value into a period for periodic function. """Limit the value into a period for periodic function.
Args: Args:
val (torch.Tensor): The value to be converted val (torch.Tensor): The value to be converted.
offset (float, optional): Offset to set the value range. offset (float, optional): Offset to set the value range.
Defaults to 0.5. Defaults to 0.5.
period ([type], optional): Period of the value. Defaults to np.pi. period ([type], optional): Period of the value. Defaults to np.pi.
......
...@@ -14,10 +14,17 @@ def bbox3d_mapping_back(bboxes, scale_factor, flip_horizontal, flip_vertical): ...@@ -14,10 +14,17 @@ def bbox3d_mapping_back(bboxes, scale_factor, flip_horizontal, flip_vertical):
def transform_lidar_to_cam(boxes_lidar): def transform_lidar_to_cam(boxes_lidar):
""" """Transform boxes from lidar coords to cam coords.
Only transform format, not exactly in camera coords Only transform format, not exactly in camera coords.
:param boxes_lidar: (N, 3 or 7) [x, y, z, w, l, h, ry] in LiDAR coords
:return: boxes_cam: (N, 3 or 7) [x, y, z, h, w, l, ry] in camera coords Args:
boxes_lidar (torch.Tensor): (N, 3 or 7) [x, y, z, w, l, h, ry]
in LiDAR coords.
boxes_cam (torch.Tensor): (N, 3 or 7) [x, y, z, h, w, l, ry]
in camera coords.
Returns:
torch.Tensor: Boxes in camera coords.
""" """
# boxes_cam = boxes_lidar.new_tensor(boxes_lidar.data) # boxes_cam = boxes_lidar.new_tensor(boxes_lidar.data)
boxes_cam = boxes_lidar.clone().detach() boxes_cam = boxes_lidar.clone().detach()
...@@ -30,10 +37,15 @@ def transform_lidar_to_cam(boxes_lidar): ...@@ -30,10 +37,15 @@ def transform_lidar_to_cam(boxes_lidar):
def boxes3d_to_bev_torch(boxes3d): def boxes3d_to_bev_torch(boxes3d):
""" """Transform 3d boxes to bev in camera coords.
:param boxes3d: (N, 7) [x, y, z, h, w, l, ry] in camera coords
:return: Args:
boxes_bev: (N, 5) [x1, y1, x2, y2, ry] boxes3d (torch.Tensor): 3d boxes in camera coords
with the shape of [N, 7] (x, y, z, h, w, l, ry).
Returns:
torch.Tensor: Bev boxes with the shape of [N, 5]
(x1, y1, x2, y2, ry).
""" """
boxes_bev = boxes3d.new(torch.Size((boxes3d.shape[0], 5))) boxes_bev = boxes3d.new(torch.Size((boxes3d.shape[0], 5)))
...@@ -46,10 +58,13 @@ def boxes3d_to_bev_torch(boxes3d): ...@@ -46,10 +58,13 @@ def boxes3d_to_bev_torch(boxes3d):
def boxes3d_to_bev_torch_lidar(boxes3d): def boxes3d_to_bev_torch_lidar(boxes3d):
""" """Transform 3d boxes to bev in lidar coords.
:param boxes3d: (N, 7) [x, y, z, w, l, h, ry] in LiDAR coords
:return: Args:
boxes_bev: (N, 5) [x1, y1, x2, y2, ry] boxes3d (torch.Tensor): 3d boxes in lidar coords
with the shape of [N, 7] (x, y, z, h, w, l, ry).
Returns: Bev boxes with the shape of [N, 5] (x1, y1, x2, y2, ry).
""" """
boxes_bev = boxes3d.new(torch.Size((boxes3d.shape[0], 5))) boxes_bev = boxes3d.new(torch.Size((boxes3d.shape[0], 5)))
...@@ -65,11 +80,11 @@ def bbox3d2roi(bbox_list): ...@@ -65,11 +80,11 @@ def bbox3d2roi(bbox_list):
"""Convert a list of bboxes to roi format. """Convert a list of bboxes to roi format.
Args: Args:
bbox_list (list[Tensor]): a list of bboxes corresponding to a batch bbox_list (list[torch.Tensor]): a list of bboxes
of images. corresponding to a batch of images.
Returns: Returns:
Tensor: shape (n, c), [batch_ind, x, y ...] torch.Tensor: shape (n, c), [batch_ind, x, y ...].
""" """
rois_list = [] rois_list = []
for img_id, bboxes in enumerate(bbox_list): for img_id, bboxes in enumerate(bbox_list):
...@@ -87,12 +102,12 @@ def bbox3d2result(bboxes, scores, labels): ...@@ -87,12 +102,12 @@ def bbox3d2result(bboxes, scores, labels):
"""Convert detection results to a list of numpy arrays. """Convert detection results to a list of numpy arrays.
Args: Args:
bboxes (Tensor): shape (n, 5) bboxes (torch.Tensor): shape (n, 5)
labels (Tensor): shape (n, ) labels (torch.Tensor): shape (n, )
scores (Tensor): shape (n, ) scores (torch.Tensor): shape (n, )
Returns: Returns:
dict(Tensor): bbox results in cpu mode dict(torch.Tensor): Bbox results in cpu mode.
""" """
return dict( return dict(
boxes_3d=bboxes.to('cpu'), boxes_3d=bboxes.to('cpu'),
...@@ -106,8 +121,8 @@ def upright_depth_to_lidar_torch(points=None, ...@@ -106,8 +121,8 @@ def upright_depth_to_lidar_torch(points=None,
"""Convert points and boxes in upright depth coordinate to lidar. """Convert points and boxes in upright depth coordinate to lidar.
Args: Args:
points (None | Tensor): points in upright depth coordinate. points (None | torch.Tensor): points in upright depth coordinate.
bboxes (None | Tensor): bboxes in upright depth coordinate. bboxes (None | torch.Tensor): bboxes in upright depth coordinate.
to_bottom_center (bool): covert bboxes to bottom center. to_bottom_center (bool): covert bboxes to bottom center.
Returns: Returns:
...@@ -136,10 +151,11 @@ def box3d_to_corner3d_upright_depth(boxes3d): ...@@ -136,10 +151,11 @@ def box3d_to_corner3d_upright_depth(boxes3d):
"""Convert box3d to corner3d in upright depth coordinate """Convert box3d to corner3d in upright depth coordinate
Args: Args:
boxes3d (Tensor): boxes with shape [n,7] in upright depth coordinate boxes3d (torch.Tensor): boxes with shape [n,7] in
upright depth coordinate.
Returns: Returns:
Tensor: boxes with [n, 8, 3] in upright depth coordinate torch.Tensor: boxes with [n, 8, 3] in upright depth coordinate
""" """
boxes_num = boxes3d.shape[0] boxes_num = boxes3d.shape[0]
ry = boxes3d[:, 6:7] ry = boxes3d[:, 6:7]
......
...@@ -8,14 +8,14 @@ def average_precision(recalls, precisions, mode='area'): ...@@ -8,14 +8,14 @@ def average_precision(recalls, precisions, mode='area'):
"""Calculate average precision (for single or multiple scales). """Calculate average precision (for single or multiple scales).
Args: Args:
recalls (ndarray): shape (num_scales, num_dets) or (num_dets, ) recalls (np.ndarray): shape (num_scales, num_dets) or (num_dets, )
precisions (ndarray): shape (num_scales, num_dets) or (num_dets, ) precisions (np.ndarray): shape (num_scales, num_dets) or (num_dets, )
mode (str): 'area' or '11points', 'area' means calculating the area mode (str): 'area' or '11points', 'area' means calculating the area
under precision-recall curve, '11points' means calculating under precision-recall curve, '11points' means calculating
the average precision of recalls at [0, 0.1, ..., 1] the average precision of recalls at [0, 0.1, ..., 1]
Returns: Returns:
float or ndarray: calculated average precision float or np.ndarray: calculated average precision
""" """
if recalls.ndim == 1: if recalls.ndim == 1:
recalls = recalls[np.newaxis, :] recalls = recalls[np.newaxis, :]
...@@ -60,8 +60,8 @@ def eval_det_cls(pred, gt, iou_thr=None): ...@@ -60,8 +60,8 @@ def eval_det_cls(pred, gt, iou_thr=None):
iou_thr (list[float]): a list, iou threshold. iou_thr (list[float]): a list, iou threshold.
Return: Return:
ndarray: numpy array of length nd. np.ndarray: numpy array of length nd.
ndarray: numpy array of length nd. np.ndarray: numpy array of length nd.
float: scalar, average precision. float: scalar, average precision.
""" """
...@@ -204,7 +204,7 @@ def indoor_eval(gt_annos, ...@@ -204,7 +204,7 @@ def indoor_eval(gt_annos,
logger=None, logger=None,
box_type_3d=None, box_type_3d=None,
box_mode_3d=None): box_mode_3d=None):
"""Scannet Evaluation. """Indoor Evaluation.
Evaluate the result of the detection. Evaluate the result of the detection.
...@@ -212,10 +212,9 @@ def indoor_eval(gt_annos, ...@@ -212,10 +212,9 @@ def indoor_eval(gt_annos,
gt_annos (list[dict]): GT annotations. gt_annos (list[dict]): GT annotations.
dt_annos (list[dict]): Detection annotations. the dict dt_annos (list[dict]): Detection annotations. the dict
includes the following keys includes the following keys
- labels_3d (Tensor): Labels of boxes. - labels_3d (torch.Tensor): Labels of boxes.
- boxes_3d (:obj:BaseInstance3DBoxes): 3d bboxes in - boxes_3d (BaseInstance3DBoxes): 3d bboxes in Depth coordinate.
Depth coordinate. - scores_3d (torch.Tensor): Scores of boxes.
- scores_3d (Tensor): Scores of boxes.
metric (list[float]): AP IoU thresholds. metric (list[float]): AP IoU thresholds.
label2cat (dict): {label: cat}. label2cat (dict): {label: cat}.
logger (logging.Logger | str | None): The way to print the mAP logger (logging.Logger | str | None): The way to print the mAP
......
...@@ -340,13 +340,14 @@ def fused_compute_statistics(overlaps, ...@@ -340,13 +340,14 @@ def fused_compute_statistics(overlaps,
def calculate_iou_partly(gt_annos, dt_annos, metric, num_parts=50): def calculate_iou_partly(gt_annos, dt_annos, metric, num_parts=50):
"""fast iou algorithm. this function can be used independently to """Fast iou algorithm. this function can be used independently to
do result analysis. Must be used in CAMERA coordinate system. do result analysis. Must be used in CAMERA coordinate system.
Args: Args:
gt_annos: dict, must from get_label_annos() in kitti_common.py gt_annos (dict): Must from get_label_annos() in kitti_common.py.
dt_annos: dict, must from get_label_annos() in kitti_common.py dt_annos (dict): Must from get_label_annos() in kitti_common.py.
metric: eval type. 0: bbox, 1: bev, 2: 3d metric (int): Eval type. 0: bbox, 1: bev, 2: 3d.
num_parts: int. a parameter for fast calculate algorithm num_parts (int): A parameter for fast calculate algorithm.
""" """
assert len(gt_annos) == len(dt_annos) assert len(gt_annos) == len(dt_annos)
total_dt_num = np.stack([len(a['name']) for a in dt_annos], 0) total_dt_num = np.stack([len(a['name']) for a in dt_annos], 0)
...@@ -456,17 +457,19 @@ def eval_class(gt_annos, ...@@ -456,17 +457,19 @@ def eval_class(gt_annos,
compute_aos=False, compute_aos=False,
num_parts=200): num_parts=200):
"""Kitti eval. support 2d/bev/3d/aos eval. support 0.5:0.05:0.95 coco AP. """Kitti eval. support 2d/bev/3d/aos eval. support 0.5:0.05:0.95 coco AP.
Args: Args:
gt_annos: dict, must from get_label_annos() in kitti_common.py gt_annos (dict): Must from get_label_annos() in kitti_common.py.
dt_annos: dict, must from get_label_annos() in kitti_common.py dt_annos (dict): Must from get_label_annos() in kitti_common.py.
current_classes: list of int, 0: car, 1: pedestrian, 2: cyclist current_classes (list[int]): 0: car, 1: pedestrian, 2: cyclist.
difficultys: list of int. eval difficulty, 0: easy, 1: normal, 2: hard difficultys (list[int]): Eval difficulty, 0: easy, 1: normal, 2: hard
metric: eval type. 0: bbox, 1: bev, 2: 3d metric (int): Eval type. 0: bbox, 1: bev, 2: 3d
min_overlaps: float, min overlap. format: [num_overlap, metric, class]. min_overlaps (float): Min overlap. format:
num_parts: int. a parameter for fast calculate algorithm [num_overlap, metric, class].
num_parts (int): A parameter for fast calculate algorithm
Returns: Returns:
dict of recall, precision and aos dict: recall, precision and aos
""" """
assert len(gt_annos) == len(dt_annos) assert len(gt_annos) == len(dt_annos)
num_examples = len(gt_annos) num_examples = len(gt_annos)
......
...@@ -304,19 +304,19 @@ def rotate_iou_kernel_eval(N, ...@@ -304,19 +304,19 @@ def rotate_iou_kernel_eval(N,
def rotate_iou_gpu_eval(boxes, query_boxes, criterion=-1, device_id=0): def rotate_iou_gpu_eval(boxes, query_boxes, criterion=-1, device_id=0):
"""rotated box iou running in gpu. 500x faster than cpu version """Rotated box iou running in gpu. 500x faster than cpu version
(take 5ms in one example with numba.cuda code). (take 5ms in one example with numba.cuda code).
convert from [this project]( convert from [this project](
https://github.com/hongzhenwang/RRPN-revise/tree/master/lib/rotation). https://github.com/hongzhenwang/RRPN-revise/tree/master/lib/rotation).
Args: Args:
boxes (float tensor: [N, 5]): rbboxes. format: centers, dims, boxes (torch.Tensor): rbboxes. format: centers, dims,
angles(clockwise when positive) angles(clockwise when positive) with the shape of [N, 5].
query_boxes (float tensor: [K, 5]): [description] query_boxes (float tensor: [K, 5]): [description]
device_id (int, optional): Defaults to 0. [description] device_id (int, optional): Defaults to 0. [description]
Returns: Returns:
[type]: [description] np.ndarray: IoU results.
""" """
boxes = boxes.astype(np.float32) boxes = boxes.astype(np.float32)
query_boxes = query_boxes.astype(np.float32) query_boxes = query_boxes.astype(np.float32)
......
...@@ -70,13 +70,13 @@ def aligned_3d_nms(boxes, scores, classes, thresh): ...@@ -70,13 +70,13 @@ def aligned_3d_nms(boxes, scores, classes, thresh):
"""3d nms for aligned boxes. """3d nms for aligned boxes.
Args: Args:
boxes (Tensor): Aligned box with shape [n, 6]. boxes (torch.Tensor): Aligned box with shape [n, 6].
scores (Tensor): Scores of each box. scores (torch.Tensor): Scores of each box.
classes (Tensor): Class of each box. classes (torch.Tensor): Class of each box.
thresh (float): Iou threshold for nms. thresh (float): Iou threshold for nms.
Returns: Returns:
Tensor: Indices of selected boxes. torch.Tensor: Indices of selected boxes.
""" """
x1 = boxes[:, 0] x1 = boxes[:, 0]
y1 = boxes[:, 1] y1 = boxes[:, 1]
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment