"tasks/vision/classification/classification.py" did not exist on "f5eac3d19b89991d2e2c88f50efeb0fe5cc69a45"
Commit c2fe651f authored by zhangshilong's avatar zhangshilong Committed by ChaimZhu
Browse files

refactor directory

parent bc5806ba
# dataset settings # dataset settings
# TODO refactor S3DISDataset
dataset_type = 'S3DISDataset' dataset_type = 'S3DISDataset'
data_root = './data/s3dis/' data_root = './data/s3dis/'
class_names = ('table', 'chair', 'sofa', 'bookcase', 'board') class_names = ('table', 'chair', 'sofa', 'bookcase', 'board')
......
...@@ -116,7 +116,7 @@ model = dict( ...@@ -116,7 +116,7 @@ model = dict(
[0.50867593, 0.50656086, 0.30136237], [0.50867593, 0.50656086, 0.30136237],
[1.1511526, 1.0546296, 0.49706793], [1.1511526, 1.0546296, 0.49706793],
[0.47535285, 0.49249494, 0.5802117]]), # Mean sizes for each class, the order is consistent with class_names. [0.47535285, 0.49249494, 0.5802117]]), # Mean sizes for each class, the order is consistent with class_names.
vote_moudule_cfg=dict( # Config of vote module branch, refer to mmdet3d.models.model_utils for more details vote_moudule_cfg=dict( # Config of vote module branch, refer to mmdet3d.models.layers for more details
in_channels=256, # Input channels for vote_module in_channels=256, # Input channels for vote_module
vote_per_seed=1, # Number of votes to generate for each seed vote_per_seed=1, # Number of votes to generate for each seed
gt_per_seed=3, # Number of gts for each seed gt_per_seed=3, # Number of gts for each seed
...@@ -186,77 +186,77 @@ class_names = ('cabinet', 'bed', 'chair', 'sofa', 'table', 'door', 'window', ...@@ -186,77 +186,77 @@ class_names = ('cabinet', 'bed', 'chair', 'sofa', 'table', 'door', 'window',
'bookshelf', 'picture', 'counter', 'desk', 'curtain', 'bookshelf', 'picture', 'counter', 'desk', 'curtain',
'refrigerator', 'showercurtrain', 'toilet', 'sink', 'bathtub', 'refrigerator', 'showercurtrain', 'toilet', 'sink', 'bathtub',
'garbagebin') # Names of classes 'garbagebin') # Names of classes
train_pipeline = [ # Training pipeline, refer to mmdet3d.datasets.pipelines for more details train_pipeline = [ # Training pipeline, refer to mmdet3d.datasets.transforms for more details
dict( dict(
type='LoadPointsFromFile', # First pipeline to load points, refer to mmdet3d.datasets.pipelines.indoor_loading for more details type='LoadPointsFromFile', # First pipeline to load points, refer to mmdet3d.datasets.transforms.indoor_loading for more details
shift_height=True, # Whether to use shifted height shift_height=True, # Whether to use shifted height
load_dim=6, # The dimension of the loaded points load_dim=6, # The dimension of the loaded points
use_dim=[0, 1, 2]), # Which dimensions of the points to be used use_dim=[0, 1, 2]), # Which dimensions of the points to be used
dict( dict(
type='LoadAnnotations3D', # Second pipeline to load annotations, refer to mmdet3d.datasets.pipelines.indoor_loading for more details type='LoadAnnotations3D', # Second pipeline to load annotations, refer to mmdet3d.datasets.transforms.indoor_loading for more details
with_bbox_3d=True, # Whether to load 3D boxes with_bbox_3d=True, # Whether to load 3D boxes
with_label_3d=True, # Whether to load 3D labels corresponding to each 3D box with_label_3d=True, # Whether to load 3D labels corresponding to each 3D box
with_mask_3d=True, # Whether to load 3D instance masks with_mask_3d=True, # Whether to load 3D instance masks
with_seg_3d=True), # Whether to load 3D semantic masks with_seg_3d=True), # Whether to load 3D semantic masks
dict( dict(
type='PointSegClassMapping', # Declare valid categories, refer to mmdet3d.datasets.pipelines.point_seg_class_mapping for more details type='PointSegClassMapping', # Declare valid categories, refer to mmdet3d.datasets.transforms.point_seg_class_mapping for more details
valid_cat_ids=(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 24, 28, 33, 34, valid_cat_ids=(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 24, 28, 33, 34,
36, 39), # all valid categories ids 36, 39), # all valid categories ids
max_cat_id=40), # max possible category id in input segmentation mask max_cat_id=40), # max possible category id in input segmentation mask
dict(type='PointSample', # Sample points, refer to mmdet3d.datasets.pipelines.transforms_3d for more details dict(type='PointSample', # Sample points, refer to mmdet3d.datasets.transforms.transforms_3d for more details
num_points=40000), # Number of points to be sampled num_points=40000), # Number of points to be sampled
dict(type='IndoorFlipData', # Augmentation pipeline that flip points and 3d boxes dict(type='IndoorFlipData', # Augmentation pipeline that flip points and 3d boxes
flip_ratio_yz=0.5, # Probability of being flipped along yz plane flip_ratio_yz=0.5, # Probability of being flipped along yz plane
flip_ratio_xz=0.5), # Probability of being flipped along xz plane flip_ratio_xz=0.5), # Probability of being flipped along xz plane
dict( dict(
type='IndoorGlobalRotScale', # Augmentation pipeline that rotate and scale points and 3d boxes, refer to mmdet3d.datasets.pipelines.indoor_augment for more details type='IndoorGlobalRotScale', # Augmentation pipeline that rotate and scale points and 3d boxes, refer to mmdet3d.datasets.transforms.indoor_augment for more details
shift_height=True, # Whether the loaded points use `shift_height` attribute shift_height=True, # Whether the loaded points use `shift_height` attribute
rot_range=[-0.027777777777777776, 0.027777777777777776], # Range of rotation rot_range=[-0.027777777777777776, 0.027777777777777776], # Range of rotation
scale_range=None), # Range of scale scale_range=None), # Range of scale
dict( dict(
type='DefaultFormatBundle3D', # Default format bundle to gather data in the pipeline, refer to mmdet3d.datasets.pipelines.formatting for more details type='DefaultFormatBundle3D', # Default format bundle to gather data in the pipeline, refer to mmdet3d.datasets.transforms.formatting for more details
class_names=('cabinet', 'bed', 'chair', 'sofa', 'table', 'door', class_names=('cabinet', 'bed', 'chair', 'sofa', 'table', 'door',
'window', 'bookshelf', 'picture', 'counter', 'desk', 'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet', 'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'garbagebin')), 'sink', 'bathtub', 'garbagebin')),
dict( dict(
type='Collect3D', # Pipeline that decides which keys in the data should be passed to the detector, refer to mmdet3d.datasets.pipelines.formatting for more details type='Collect3D', # Pipeline that decides which keys in the data should be passed to the detector, refer to mmdet3d.datasets.transforms.formatting for more details
keys=[ keys=[
'points', 'gt_bboxes_3d', 'gt_labels_3d', 'pts_semantic_mask', 'points', 'gt_bboxes_3d', 'gt_labels_3d', 'pts_semantic_mask',
'pts_instance_mask' 'pts_instance_mask'
]) ])
] ]
test_pipeline = [ # Testing pipeline, refer to mmdet3d.datasets.pipelines for more details test_pipeline = [ # Testing pipeline, refer to mmdet3d.datasets.transforms for more details
dict( dict(
type='LoadPointsFromFile', # First pipeline to load points, refer to mmdet3d.datasets.pipelines.indoor_loading for more details type='LoadPointsFromFile', # First pipeline to load points, refer to mmdet3d.datasets.transforms.indoor_loading for more details
shift_height=True, # Whether to use shifted height shift_height=True, # Whether to use shifted height
load_dim=6, # The dimension of the loaded points load_dim=6, # The dimension of the loaded points
use_dim=[0, 1, 2]), # Which dimensions of the points to be used use_dim=[0, 1, 2]), # Which dimensions of the points to be used
dict(type='PointSample', # Sample points, refer to mmdet3d.datasets.pipelines.transforms_3d for more details dict(type='PointSample', # Sample points, refer to mmdet3d.datasets.transforms.transforms_3d for more details
num_points=40000), # Number of points to be sampled num_points=40000), # Number of points to be sampled
dict( dict(
type='DefaultFormatBundle3D', # Default format bundle to gather data in the pipeline, refer to mmdet3d.datasets.pipelines.formatting for more details type='DefaultFormatBundle3D', # Default format bundle to gather data in the pipeline, refer to mmdet3d.datasets.transforms.formatting for more details
class_names=('cabinet', 'bed', 'chair', 'sofa', 'table', 'door', class_names=('cabinet', 'bed', 'chair', 'sofa', 'table', 'door',
'window', 'bookshelf', 'picture', 'counter', 'desk', 'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet', 'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'garbagebin')), 'sink', 'bathtub', 'garbagebin')),
dict(type='Collect3D', # Pipeline that decides which keys in the data should be passed to the detector, refer to mmdet3d.datasets.pipelines.formatting for more details dict(type='Collect3D', # Pipeline that decides which keys in the data should be passed to the detector, refer to mmdet3d.datasets.transforms.formatting for more details
keys=['points']) keys=['points'])
] ]
eval_pipeline = [ # Pipeline used for evaluation or visualization, refer to mmdet3d.datasets.pipelines for more details eval_pipeline = [ # Pipeline used for evaluation or visualization, refer to mmdet3d.datasets.transforms for more details
dict( dict(
type='LoadPointsFromFile', # First pipeline to load points, refer to mmdet3d.datasets.pipelines.indoor_loading for more details type='LoadPointsFromFile', # First pipeline to load points, refer to mmdet3d.datasets.transforms.indoor_loading for more details
shift_height=True, # Whether to use shifted height shift_height=True, # Whether to use shifted height
load_dim=6, # The dimension of the loaded points load_dim=6, # The dimension of the loaded points
use_dim=[0, 1, 2]), # Which dimensions of the points to be used use_dim=[0, 1, 2]), # Which dimensions of the points to be used
dict( dict(
type='DefaultFormatBundle3D', # Default format bundle to gather data in the pipeline, refer to mmdet3d.datasets.pipelines.formatting for more details type='DefaultFormatBundle3D', # Default format bundle to gather data in the pipeline, refer to mmdet3d.datasets.transforms.formatting for more details
class_names=('cabinet', 'bed', 'chair', 'sofa', 'table', 'door', class_names=('cabinet', 'bed', 'chair', 'sofa', 'table', 'door',
'window', 'bookshelf', 'picture', 'counter', 'desk', 'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet', 'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'garbagebin')), 'sink', 'bathtub', 'garbagebin')),
with_label=False), with_label=False),
dict(type='Collect3D', # Pipeline that decides which keys in the data should be passed to the detector, refer to mmdet3d.datasets.pipelines.formatting for more details dict(type='Collect3D', # Pipeline that decides which keys in the data should be passed to the detector, refer to mmdet3d.datasets.transforms.formatting for more details
keys=['points']) keys=['points'])
] ]
data = dict( data = dict(
......
...@@ -117,7 +117,7 @@ model = dict( ...@@ -117,7 +117,7 @@ model = dict(
[0.50867593, 0.50656086, 0.30136237], [0.50867593, 0.50656086, 0.30136237],
[1.1511526, 1.0546296, 0.49706793], [1.1511526, 1.0546296, 0.49706793],
[0.47535285, 0.49249494, 0.5802117]]), # 每一类的平均尺寸,其顺序与类名顺序相同 [0.47535285, 0.49249494, 0.5802117]]), # 每一类的平均尺寸,其顺序与类名顺序相同
vote_moudule_cfg=dict( # 投票 (vote) 模块的配置,更多细节请参考 mmdet3d.models.model_utils vote_moudule_cfg=dict( # 投票 (vote) 模块的配置,更多细节请参考 mmdet3d.models.layers
in_channels=256, # 投票模块的输入通道数 in_channels=256, # 投票模块的输入通道数
vote_per_seed=1, # 对于每个种子点生成的投票数 vote_per_seed=1, # 对于每个种子点生成的投票数
gt_per_seed=3, # 每个种子点的真实标签个数 gt_per_seed=3, # 每个种子点的真实标签个数
...@@ -187,77 +187,77 @@ class_names = ('cabinet', 'bed', 'chair', 'sofa', 'table', 'door', 'window', ...@@ -187,77 +187,77 @@ class_names = ('cabinet', 'bed', 'chair', 'sofa', 'table', 'door', 'window',
'bookshelf', 'picture', 'counter', 'desk', 'curtain', 'bookshelf', 'picture', 'counter', 'desk', 'curtain',
'refrigerator', 'showercurtrain', 'toilet', 'sink', 'bathtub', 'refrigerator', 'showercurtrain', 'toilet', 'sink', 'bathtub',
'garbagebin') # 类的名称 'garbagebin') # 类的名称
train_pipeline = [ # 训练流水线,更多细节请参考 mmdet3d.datasets.pipelines train_pipeline = [ # 训练流水线,更多细节请参考 mmdet3d.datasets.transforms
dict( dict(
type='LoadPointsFromFile', # 第一个流程,用于读取点,更多细节请参考 mmdet3d.datasets.pipelines.indoor_loading type='LoadPointsFromFile', # 第一个流程,用于读取点,更多细节请参考 mmdet3d.datasets.transforms.indoor_loading
shift_height=True, # 是否使用变换高度 shift_height=True, # 是否使用变换高度
load_dim=6, # 读取的点的维度 load_dim=6, # 读取的点的维度
use_dim=[0, 1, 2]), # 使用所读取点的哪些维度 use_dim=[0, 1, 2]), # 使用所读取点的哪些维度
dict( dict(
type='LoadAnnotations3D', # 第二个流程,用于读取标注,更多细节请参考 mmdet3d.datasets.pipelines.indoor_loading type='LoadAnnotations3D', # 第二个流程,用于读取标注,更多细节请参考 mmdet3d.datasets.transforms.indoor_loading
with_bbox_3d=True, # 是否读取 3D 框 with_bbox_3d=True, # 是否读取 3D 框
with_label_3d=True, # 是否读取 3D 框对应的类别标签 with_label_3d=True, # 是否读取 3D 框对应的类别标签
with_mask_3d=True, # 是否读取 3D 实例分割掩码 with_mask_3d=True, # 是否读取 3D 实例分割掩码
with_seg_3d=True), # 是否读取 3D 语义分割掩码 with_seg_3d=True), # 是否读取 3D 语义分割掩码
dict( dict(
type='PointSegClassMapping', # 选取有效的类别,更多细节请参考 mmdet3d.datasets.pipelines.point_seg_class_mapping type='PointSegClassMapping', # 选取有效的类别,更多细节请参考 mmdet3d.datasets.transforms.point_seg_class_mapping
valid_cat_ids=(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 24, 28, 33, 34, valid_cat_ids=(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 24, 28, 33, 34,
36, 39), # 所有有效类别的编号 36, 39), # 所有有效类别的编号
max_cat_id=40), # 输入语义分割掩码中可能存在的最大类别编号 max_cat_id=40), # 输入语义分割掩码中可能存在的最大类别编号
dict(type='PointSample', # 室内点采样,更多细节请参考 mmdet3d.datasets.pipelines.indoor_sample dict(type='PointSample', # 室内点采样,更多细节请参考 mmdet3d.datasets.transforms.indoor_sample
num_points=40000), # 采样的点的数量 num_points=40000), # 采样的点的数量
dict(type='IndoorFlipData', # 数据增广流程,随机翻转点和 3D 框 dict(type='IndoorFlipData', # 数据增广流程,随机翻转点和 3D 框
flip_ratio_yz=0.5, # 沿着 yz 平面被翻转的概率 flip_ratio_yz=0.5, # 沿着 yz 平面被翻转的概率
flip_ratio_xz=0.5), # 沿着 xz 平面被翻转的概率 flip_ratio_xz=0.5), # 沿着 xz 平面被翻转的概率
dict( dict(
type='IndoorGlobalRotScale', # 数据增广流程,旋转并放缩点和 3D 框,更多细节请参考 mmdet3d.datasets.pipelines.indoor_augment type='IndoorGlobalRotScale', # 数据增广流程,旋转并放缩点和 3D 框,更多细节请参考 mmdet3d.datasets.transforms.indoor_augment
shift_height=True, # 读取的点是否有高度这一属性 shift_height=True, # 读取的点是否有高度这一属性
rot_range=[-0.027777777777777776, 0.027777777777777776], # 旋转角范围 rot_range=[-0.027777777777777776, 0.027777777777777776], # 旋转角范围
scale_range=None), # 缩放尺寸范围 scale_range=None), # 缩放尺寸范围
dict( dict(
type='DefaultFormatBundle3D', # 默认格式打包以收集读取的所有数据,更多细节请参考 mmdet3d.datasets.pipelines.formatting type='DefaultFormatBundle3D', # 默认格式打包以收集读取的所有数据,更多细节请参考 mmdet3d.datasets.transforms.formatting
class_names=('cabinet', 'bed', 'chair', 'sofa', 'table', 'door', class_names=('cabinet', 'bed', 'chair', 'sofa', 'table', 'door',
'window', 'bookshelf', 'picture', 'counter', 'desk', 'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet', 'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'garbagebin')), 'sink', 'bathtub', 'garbagebin')),
dict( dict(
type='Collect3D', # 最后一个流程,决定哪些键值对应的数据会被输入给检测器,更多细节请参考 mmdet3d.datasets.pipelines.formatting type='Collect3D', # 最后一个流程,决定哪些键值对应的数据会被输入给检测器,更多细节请参考 mmdet3d.datasets.transforms.formatting
keys=[ keys=[
'points', 'gt_bboxes_3d', 'gt_labels_3d', 'pts_semantic_mask', 'points', 'gt_bboxes_3d', 'gt_labels_3d', 'pts_semantic_mask',
'pts_instance_mask' 'pts_instance_mask'
]) ])
] ]
test_pipeline = [ # 测试流水线,更多细节请参考 mmdet3d.datasets.pipelines test_pipeline = [ # 测试流水线,更多细节请参考 mmdet3d.datasets.transforms
dict( dict(
type='LoadPointsFromFile', # 第一个流程,用于读取点,更多细节请参考 mmdet3d.datasets.pipelines.indoor_loading type='LoadPointsFromFile', # 第一个流程,用于读取点,更多细节请参考 mmdet3d.datasets.transforms.indoor_loading
shift_height=True, # 是否使用变换高度 shift_height=True, # 是否使用变换高度
load_dim=6, # 读取的点的维度 load_dim=6, # 读取的点的维度
use_dim=[0, 1, 2]), # 使用所读取点的哪些维度 use_dim=[0, 1, 2]), # 使用所读取点的哪些维度
dict(type='PointSample', # 室内点采样,更多细节请参考 mmdet3d.datasets.pipelines.indoor_sample dict(type='PointSample', # 室内点采样,更多细节请参考 mmdet3d.datasets.transforms.indoor_sample
num_points=40000), # 采样的点的数量 num_points=40000), # 采样的点的数量
dict( dict(
type='DefaultFormatBundle3D', # 默认格式打包以收集读取的所有数据,更多细节请参考 mmdet3d.datasets.pipelines.formatting type='DefaultFormatBundle3D', # 默认格式打包以收集读取的所有数据,更多细节请参考 mmdet3d.datasets.transforms.formatting
class_names=('cabinet', 'bed', 'chair', 'sofa', 'table', 'door', class_names=('cabinet', 'bed', 'chair', 'sofa', 'table', 'door',
'window', 'bookshelf', 'picture', 'counter', 'desk', 'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet', 'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'garbagebin')), 'sink', 'bathtub', 'garbagebin')),
dict(type='Collect3D', # 最后一个流程,决定哪些键值对应的数据会被输入给检测器,更多细节请参考 mmdet3d.datasets.pipelines.formatting dict(type='Collect3D', # 最后一个流程,决定哪些键值对应的数据会被输入给检测器,更多细节请参考 mmdet3d.datasets.transforms.formatting
keys=['points']) keys=['points'])
] ]
eval_pipeline = [ # 模型验证或可视化所使用的流水线,更多细节请参考 mmdet3d.datasets.pipelines eval_pipeline = [ # 模型验证或可视化所使用的流水线,更多细节请参考 mmdet3d.datasets.transforms
dict( dict(
type='LoadPointsFromFile', # 第一个流程,用于读取点,更多细节请参考 mmdet3d.datasets.pipelines.indoor_loading type='LoadPointsFromFile', # 第一个流程,用于读取点,更多细节请参考 mmdet3d.datasets.transforms.indoor_loading
shift_height=True, # 是否使用变换高度 shift_height=True, # 是否使用变换高度
load_dim=6, # 读取的点的维度 load_dim=6, # 读取的点的维度
use_dim=[0, 1, 2]), # 使用所读取点的哪些维度 use_dim=[0, 1, 2]), # 使用所读取点的哪些维度
dict( dict(
type='DefaultFormatBundle3D', # 默认格式打包以收集读取的所有数据,更多细节请参考 mmdet3d.datasets.pipelines.formatting type='DefaultFormatBundle3D', # 默认格式打包以收集读取的所有数据,更多细节请参考 mmdet3d.datasets.transforms.formatting
class_names=('cabinet', 'bed', 'chair', 'sofa', 'table', 'door', class_names=('cabinet', 'bed', 'chair', 'sofa', 'table', 'door',
'window', 'bookshelf', 'picture', 'counter', 'desk', 'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet', 'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'garbagebin')), 'sink', 'bathtub', 'garbagebin')),
with_label=False), with_label=False),
dict(type='Collect3D', # 最后一个流程,决定哪些键值对应的数据会被输入给检测器,更多细节请参考 mmdet3d.datasets.pipelines.formatting dict(type='Collect3D', # 最后一个流程,决定哪些键值对应的数据会被输入给检测器,更多细节请参考 mmdet3d.datasets.transforms.formatting
keys=['points']) keys=['points'])
] ]
data = dict( data = dict(
......
...@@ -12,9 +12,9 @@ import torch.nn as nn ...@@ -12,9 +12,9 @@ import torch.nn as nn
from mmengine.dataset import Compose from mmengine.dataset import Compose
from mmengine.runner import load_checkpoint from mmengine.runner import load_checkpoint
from mmdet3d.core import Box3DMode, Det3DDataSample, SampleList from mmdet3d.registry import MODELS
from mmdet3d.core.bbox import get_box_type from mmdet3d.structures import Box3DMode, Det3DDataSample, get_box_type
from mmdet3d.models import build_model from mmdet3d.structures.det3d_data_sample import SampleList
def convert_SyncBN(config): def convert_SyncBN(config):
...@@ -55,7 +55,7 @@ def init_model(config, checkpoint=None, device='cuda:0'): ...@@ -55,7 +55,7 @@ def init_model(config, checkpoint=None, device='cuda:0'):
config.model.pretrained = None config.model.pretrained = None
convert_SyncBN(config.model) convert_SyncBN(config.model)
config.model.train_cfg = None config.model.train_cfg = None
model = build_model(config.model) model = MODELS.build(config.model)
if checkpoint is not None: if checkpoint is not None:
checkpoint = load_checkpoint(model, checkpoint, map_location='cpu') checkpoint = load_checkpoint(model, checkpoint, map_location='cpu')
if 'CLASSES' in checkpoint['meta']: if 'CLASSES' in checkpoint['meta']:
......
# Copyright (c) OpenMMLab. All rights reserved.
from .anchor import * # noqa: F401, F403
from .bbox import * # noqa: F401, F403
from .data_structures import * # noqa: F401, F403
from .evaluation import * # noqa: F401, F403
from .points import * # noqa: F401, F403
from .post_processing import * # noqa: F401, F403
from .utils import * # noqa: F401, F403
from .visualization import * # noqa: F401, F403
from .voxel import * # noqa: F401, F403
# Copyright (c) OpenMMLab. All rights reserved.
from .assigners import AssignResult, BaseAssigner, Max3DIoUAssigner
# from .bbox_target import bbox_target
from .builder import build_assigner, build_bbox_coder, build_sampler
from .coders import DeltaXYZWLHRBBoxCoder
from .iou_calculators import (AxisAlignedBboxOverlaps3D, BboxOverlaps3D,
BboxOverlapsNearest3D,
axis_aligned_bbox_overlaps_3d, bbox_overlaps_3d,
bbox_overlaps_nearest_3d)
from .samplers import (BaseSampler, CombinedSampler,
InstanceBalancedPosSampler, IoUBalancedNegSampler,
PseudoSampler, RandomSampler, SamplingResult)
from .structures import (BaseInstance3DBoxes, Box3DMode, CameraInstance3DBoxes,
Coord3DMode, DepthInstance3DBoxes,
LiDARInstance3DBoxes, get_box_type, limit_period,
mono_cam_box2vis, points_cam2img, points_img2cam,
xywhr2xyxyr)
from .transforms import bbox3d2result, bbox3d2roi, bbox3d_mapping_back
__all__ = [
'BaseSampler', 'AssignResult', 'BaseAssigner', 'Max3DIoUAssigner',
'PseudoSampler', 'RandomSampler', 'InstanceBalancedPosSampler',
'IoUBalancedNegSampler', 'CombinedSampler', 'SamplingResult',
'DeltaXYZWLHRBBoxCoder', 'BboxOverlapsNearest3D', 'BboxOverlaps3D',
'bbox_overlaps_nearest_3d', 'bbox_overlaps_3d',
'AxisAlignedBboxOverlaps3D', 'axis_aligned_bbox_overlaps_3d', 'Box3DMode',
'LiDARInstance3DBoxes', 'CameraInstance3DBoxes', 'bbox3d2roi',
'bbox3d2result', 'DepthInstance3DBoxes', 'BaseInstance3DBoxes',
'bbox3d_mapping_back', 'xywhr2xyxyr', 'limit_period', 'points_cam2img',
'points_img2cam', 'get_box_type', 'Coord3DMode', 'mono_cam_box2vis',
'build_assigner', 'build_bbox_coder', 'build_sampler'
]
# Copyright (c) OpenMMLab. All rights reserved.
from .iou3d_calculator import (AxisAlignedBboxOverlaps3D, BboxOverlaps3D,
BboxOverlapsNearest3D,
axis_aligned_bbox_overlaps_3d, bbox_overlaps_3d,
bbox_overlaps_nearest_3d)
__all__ = [
'BboxOverlapsNearest3D', 'BboxOverlaps3D', 'bbox_overlaps_nearest_3d',
'bbox_overlaps_3d', 'AxisAlignedBboxOverlaps3D',
'axis_aligned_bbox_overlaps_3d'
]
# Copyright (c) OpenMMLab. All rights reserved.
from .det3d_data_sample import Det3DDataSample
from .point_data import PointData
__all__ = ['Det3DDataSample', 'PointData']
# Copyright (c) OpenMMLab. All rights reserved.
from .indoor_eval import indoor_eval
from .instance_seg_eval import instance_seg_eval
from .kitti_utils import kitti_eval, kitti_eval_coco_style
from .lyft_eval import lyft_eval
from .seg_eval import seg_eval
__all__ = [
'kitti_eval_coco_style', 'kitti_eval', 'indoor_eval', 'lyft_eval',
'seg_eval', 'instance_seg_eval'
]
# Copyright (c) OpenMMLab. All rights reserved.
from mmdet.core.post_processing import (merge_aug_bboxes, merge_aug_masks,
merge_aug_proposals, merge_aug_scores,
multiclass_nms)
from .box3d_nms import (aligned_3d_nms, box3d_multiclass_nms, circle_nms,
nms_bev, nms_normal_bev)
from .merge_augs import merge_aug_bboxes_3d
__all__ = [
'multiclass_nms', 'merge_aug_proposals', 'merge_aug_bboxes',
'merge_aug_scores', 'merge_aug_masks', 'box3d_multiclass_nms',
'aligned_3d_nms', 'merge_aug_bboxes_3d', 'circle_nms', 'nms_bev',
'nms_normal_bev'
]
# Copyright (c) OpenMMLab. All rights reserved.
from .array_converter import ArrayConverter, array_converter
from .gaussian import (draw_heatmap_gaussian, ellip_gaussian2D, gaussian_2d,
gaussian_radius, get_ellip_gaussian_2D)
from .misc import add_prefix
from .typing import (ConfigType, ForwardResults, InstanceList, MultiConfig,
OptConfigType, OptInstanceList, OptMultiConfig,
OptSampleList, OptSamplingResultList, SampleList,
SamplingResultList)
__all__ = [
'gaussian_2d', 'gaussian_radius', 'draw_heatmap_gaussian',
'ArrayConverter', 'array_converter', 'ellip_gaussian2D',
'get_ellip_gaussian_2D', 'ConfigType', 'OptConfigType', 'MultiConfig',
'OptMultiConfig', 'InstanceList', 'OptInstanceList', 'SampleList',
'OptSampleList', 'SamplingResultList', 'ForwardResults',
'OptSamplingResultList', 'add_prefix'
]
...@@ -4,34 +4,32 @@ from .convert_utils import get_2d_boxes ...@@ -4,34 +4,32 @@ from .convert_utils import get_2d_boxes
from .dataset_wrappers import CBGSDataset from .dataset_wrappers import CBGSDataset
from .det3d_dataset import Det3DDataset from .det3d_dataset import Det3DDataset
from .kitti_dataset import KittiDataset from .kitti_dataset import KittiDataset
from .kitti_mono_dataset import KittiMonoDataset
from .lyft_dataset import LyftDataset from .lyft_dataset import LyftDataset
from .nuscenes_dataset import NuScenesDataset from .nuscenes_dataset import NuScenesDataset
from .nuscenes_mono_dataset import NuScenesMonoDataset # yapf: enable
from .s3dis_dataset import S3DISDataset, S3DISSegDataset
from .scannet_dataset import (ScanNetDataset, ScanNetInstanceSegDataset,
ScanNetSegDataset)
from .seg3d_dataset import Seg3DDataset
from .semantickitti_dataset import SemanticKITTIDataset
from .sunrgbd_dataset import SUNRGBDDataset
# yapf: disable # yapf: disable
from .pipelines import (AffineResize, BackgroundPointsFilter, GlobalAlignment, from .transforms import (AffineResize, BackgroundPointsFilter, GlobalAlignment,
GlobalRotScaleTrans, IndoorPatchPointSample, GlobalRotScaleTrans, IndoorPatchPointSample,
IndoorPointSample, LoadAnnotations3D, IndoorPointSample, LoadAnnotations3D,
LoadPointsFromDict, LoadPointsFromFile, LoadPointsFromDict, LoadPointsFromFile,
LoadPointsFromMultiSweeps, NormalizePointsColor, LoadPointsFromMultiSweeps, NormalizePointsColor,
ObjectNameFilter, ObjectNoise, ObjectRangeFilter, ObjectNameFilter, ObjectNoise, ObjectRangeFilter,
ObjectSample, PointSample, PointShuffle, ObjectSample, PointSample, PointShuffle,
PointsRangeFilter, RandomDropPointsColor, RandomFlip3D, PointsRangeFilter, RandomDropPointsColor,
RandomJitterPoints, RandomShiftScale, RandomFlip3D, RandomJitterPoints, RandomShiftScale,
VoxelBasedPointSampler) VoxelBasedPointSampler)
# yapf: enable
from .s3dis_dataset import S3DISDataset, S3DISSegDataset
from .scannet_dataset import (ScanNetDataset, ScanNetInstanceSegDataset,
ScanNetSegDataset)
from .seg3d_dataset import Seg3DDataset
from .semantickitti_dataset import SemanticKITTIDataset
from .sunrgbd_dataset import SUNRGBDDataset
from .utils import get_loading_pipeline from .utils import get_loading_pipeline
from .waymo_dataset import WaymoDataset from .waymo_dataset import WaymoDataset
__all__ = [ __all__ = [
'KittiDataset', 'KittiMonoDataset', 'DATASETS', 'CBGSDataset', 'KittiDataset', 'DATASETS', 'CBGSDataset',
'build_dataset', 'NuScenesDataset', 'NuScenesMonoDataset', 'LyftDataset', 'build_dataset', 'NuScenesDataset', 'LyftDataset',
'ObjectSample', 'RandomFlip3D', 'ObjectNoise', 'GlobalRotScaleTrans', 'ObjectSample', 'RandomFlip3D', 'ObjectNoise', 'GlobalRotScaleTrans',
'PointShuffle', 'ObjectRangeFilter', 'PointsRangeFilter', 'PointShuffle', 'ObjectRangeFilter', 'PointsRangeFilter',
'LoadPointsFromFile', 'S3DISSegDataset', 'S3DISDataset', 'LoadPointsFromFile', 'S3DISSegDataset', 'S3DISDataset',
......
...@@ -18,9 +18,9 @@ PIPELINES = TRANSFORMS ...@@ -18,9 +18,9 @@ PIPELINES = TRANSFORMS
def build_dataset(cfg, default_args=None): def build_dataset(cfg, default_args=None):
from mmengine import ClassBalancedDataset, ConcatDataset, RepeatDataset
from mmdet3d.datasets.dataset_wrappers import CBGSDataset from mmdet3d.datasets.dataset_wrappers import CBGSDataset
from mmdet.datasets.dataset_wrappers import (ClassBalancedDataset,
ConcatDataset, RepeatDataset)
if isinstance(cfg, (list, tuple)): if isinstance(cfg, (list, tuple)):
dataset = ConcatDataset([build_dataset(c, default_args) for c in cfg]) dataset = ConcatDataset([build_dataset(c, default_args) for c in cfg])
elif cfg['type'] == 'ConcatDataset': elif cfg['type'] == 'ConcatDataset':
......
...@@ -7,7 +7,7 @@ from nuscenes.utils.geometry_utils import view_points ...@@ -7,7 +7,7 @@ from nuscenes.utils.geometry_utils import view_points
from pyquaternion import Quaternion from pyquaternion import Quaternion
from shapely.geometry import MultiPoint, box from shapely.geometry import MultiPoint, box
from mmdet3d.core.bbox import points_cam2img from mmdet3d.structures import points_cam2img
nus_categories = ('car', 'truck', 'trailer', 'bus', 'construction_vehicle', nus_categories = ('car', 'truck', 'trailer', 'bus', 'construction_vehicle',
'bicycle', 'motorcycle', 'pedestrian', 'traffic_cone', 'bicycle', 'motorcycle', 'pedestrian', 'traffic_cone',
......
...@@ -8,7 +8,7 @@ import numpy as np ...@@ -8,7 +8,7 @@ import numpy as np
from mmengine.dataset import BaseDataset from mmengine.dataset import BaseDataset
from mmdet3d.datasets import DATASETS from mmdet3d.datasets import DATASETS
from ..core.bbox import get_box_type from mmdet3d.structures import get_box_type
@DATASETS.register_module() @DATASETS.register_module()
...@@ -139,7 +139,10 @@ class Det3DDataset(BaseDataset): ...@@ -139,7 +139,10 @@ class Det3DDataset(BaseDataset):
img_filtered_annotations = {} img_filtered_annotations = {}
filter_mask = ann_info['gt_labels_3d'] > -1 filter_mask = ann_info['gt_labels_3d'] > -1
for key in ann_info.keys(): for key in ann_info.keys():
if key != 'instances':
img_filtered_annotations[key] = (ann_info[key][filter_mask]) img_filtered_annotations[key] = (ann_info[key][filter_mask])
else:
img_filtered_annotations[key] = ann_info[key]
return img_filtered_annotations return img_filtered_annotations
def get_ann_info(self, index: int) -> dict: def get_ann_info(self, index: int) -> dict:
...@@ -180,7 +183,7 @@ class Det3DDataset(BaseDataset): ...@@ -180,7 +183,7 @@ class Det3DDataset(BaseDataset):
# add s or gt prefix for most keys after concat # add s or gt prefix for most keys after concat
# we only process 3d annotations here, the corresponding # we only process 3d annotations here, the corresponding
# 2d annotation process is in the `LoadAnnotations3D` # 2d annotation process is in the `LoadAnnotations3D`
# in `pipelines` # in `transforms`
name_mapping = { name_mapping = {
'bbox_label_3d': 'gt_labels_3d', 'bbox_label_3d': 'gt_labels_3d',
'bbox_3d': 'gt_bboxes_3d', 'bbox_3d': 'gt_bboxes_3d',
...@@ -197,16 +200,15 @@ class Det3DDataset(BaseDataset): ...@@ -197,16 +200,15 @@ class Det3DDataset(BaseDataset):
keys = list(instances[0].keys()) keys = list(instances[0].keys())
ann_info = dict() ann_info = dict()
for ann_name in keys: for ann_name in keys:
if ann_name in name_mapping:
temp_anns = [item[ann_name] for item in instances] temp_anns = [item[ann_name] for item in instances]
# map the original dataset label to training label # map the original dataset label to training label
if 'label' in ann_name: if 'label' in ann_name:
temp_anns = [ temp_anns = [
self.label_mapping[item] for item in temp_anns self.label_mapping[item] for item in temp_anns
] ]
temp_anns = np.array(temp_anns) if ann_name in name_mapping:
ann_name = name_mapping[ann_name] ann_name = name_mapping[ann_name]
temp_anns = np.array(temp_anns)
ann_info[ann_name] = temp_anns ann_info[ann_name] = temp_anns
ann_info['instances'] = info['instances'] ann_info['instances'] = info['instances']
return ann_info return ann_info
......
...@@ -213,7 +213,7 @@ class Kitti2DDataset(Det3DDataset): ...@@ -213,7 +213,7 @@ class Kitti2DDataset(Det3DDataset):
Returns: Returns:
list[dict]: A list of dictionaries with the kitti 2D format. list[dict]: A list of dictionaries with the kitti 2D format.
""" """
from mmdet3d.core.bbox.transforms import bbox2result_kitti2d from mmdet3d.structures.ops.transforms import bbox2result_kitti2d
sample_idx = [info['image']['image_idx'] for info in self.data_infos] sample_idx = [info['image']['image_idx'] for info in self.data_infos]
result_files = bbox2result_kitti2d(outputs, self.CLASSES, sample_idx, result_files = bbox2result_kitti2d(outputs, self.CLASSES, sample_idx,
out) out)
...@@ -231,7 +231,7 @@ class Kitti2DDataset(Det3DDataset): ...@@ -231,7 +231,7 @@ class Kitti2DDataset(Det3DDataset):
tuple (str, dict): Average precision results in str format tuple (str, dict): Average precision results in str format
and average precision results in dict format. and average precision results in dict format.
""" """
from mmdet3d.core.evaluation import kitti_eval from mmdet3d.evaluation import kitti_eval
eval_types = ['bbox'] if not eval_types else eval_types eval_types = ['bbox'] if not eval_types else eval_types
assert eval_types in ('bbox', ['bbox' assert eval_types in ('bbox', ['bbox'
]), 'KITTI data set only evaluate bbox' ]), 'KITTI data set only evaluate bbox'
......
...@@ -4,7 +4,7 @@ from typing import Callable, List, Optional, Union ...@@ -4,7 +4,7 @@ from typing import Callable, List, Optional, Union
import numpy as np import numpy as np
from mmdet3d.datasets import DATASETS from mmdet3d.datasets import DATASETS
from ..core.bbox import CameraInstance3DBoxes from mmdet3d.structures import CameraInstance3DBoxes
from .det3d_dataset import Det3DDataset from .det3d_dataset import Det3DDataset
...@@ -119,7 +119,7 @@ class KittiDataset(Det3DDataset): ...@@ -119,7 +119,7 @@ class KittiDataset(Det3DDataset):
Returns: Returns:
dict: annotation information consists of the following keys: dict: annotation information consists of the following keys:
- bboxes_3d (:obj:`LiDARInstance3DBoxes`): - gt_bboxes_3d (:obj:`LiDARInstance3DBoxes`):
3D ground truth bboxes. 3D ground truth bboxes.
- bbox_labels_3d (np.ndarray): Labels of ground truths. - bbox_labels_3d (np.ndarray): Labels of ground truths.
- gt_bboxes (np.ndarray): 2D ground truth bboxes. - gt_bboxes (np.ndarray): 2D ground truth bboxes.
......
# Copyright (c) OpenMMLab. All rights reserved.
import copy
import tempfile
from os import path as osp
import mmcv
import numpy as np
import torch
from mmcv.utils import print_log
from mmdet3d.registry import DATASETS
from ..core.bbox import Box3DMode, CameraInstance3DBoxes, points_cam2img
from .nuscenes_mono_dataset import NuScenesMonoDataset
@DATASETS.register_module()
class KittiMonoDataset(NuScenesMonoDataset):
"""Monocular 3D detection on KITTI Dataset.
Args:
data_root (str): Path of dataset root.
info_file (str): Path of info file.
load_interval (int, optional): Interval of loading the dataset. It is
used to uniformly sample the dataset. Defaults to 1.
with_velocity (bool, optional): Whether include velocity prediction
into the experiments. Defaults to False.
eval_version (str, optional): Configuration version of evaluation.
Defaults to None.
version (str, optional): Dataset version. Defaults to None.
kwargs (dict): Other arguments are the same of NuScenesMonoDataset.
"""
CLASSES = ('Pedestrian', 'Cyclist', 'Car')
def __init__(self,
data_root,
info_file,
load_interval=1,
with_velocity=False,
eval_version=None,
version=None,
**kwargs):
super().__init__(
data_root=data_root,
load_interval=load_interval,
with_velocity=with_velocity,
eval_version=eval_version,
version=version,
**kwargs)
self.anno_infos = mmcv.load(info_file)
self.bbox_code_size = 7
def _parse_ann_info(self, img_info, ann_info):
"""Parse bbox and mask annotation.
Args:
ann_info (list[dict]): Annotation info of an image.
with_mask (bool): Whether to parse mask annotations.
Returns:
dict: A dict containing the following keys: bboxes, bboxes_ignore,
labels, masks, seg_map. "masks" are raw annotations and not
decoded into binary masks.
"""
gt_bboxes = []
gt_labels = []
gt_bboxes_ignore = []
gt_masks_ann = []
gt_bboxes_cam3d = []
centers2d = []
depths = []
for i, ann in enumerate(ann_info):
if ann.get('ignore', False):
continue
x1, y1, w, h = ann['bbox']
inter_w = max(0, min(x1 + w, img_info['width']) - max(x1, 0))
inter_h = max(0, min(y1 + h, img_info['height']) - max(y1, 0))
if inter_w * inter_h == 0:
continue
if ann['area'] <= 0 or w < 1 or h < 1:
continue
if ann['category_id'] not in self.cat_ids:
continue
bbox = [x1, y1, x1 + w, y1 + h]
if ann.get('iscrowd', False):
gt_bboxes_ignore.append(bbox)
else:
gt_bboxes.append(bbox)
gt_labels.append(self.cat2label[ann['category_id']])
gt_masks_ann.append(ann.get('segmentation', None))
# 3D annotations in camera coordinates
bbox_cam3d = np.array(ann['bbox_cam3d']).reshape(-1, )
gt_bboxes_cam3d.append(bbox_cam3d)
# 2.5D annotations in camera coordinates
center2d = ann['center2d'][:2]
depth = ann['center2d'][2]
centers2d.append(center2d)
depths.append(depth)
if gt_bboxes:
gt_bboxes = np.array(gt_bboxes, dtype=np.float32)
gt_labels = np.array(gt_labels, dtype=np.int64)
else:
gt_bboxes = np.zeros((0, 4), dtype=np.float32)
gt_labels = np.array([], dtype=np.int64)
if gt_bboxes_cam3d:
gt_bboxes_cam3d = np.array(gt_bboxes_cam3d, dtype=np.float32)
centers2d = np.array(centers2d, dtype=np.float32)
depths = np.array(depths, dtype=np.float32)
else:
gt_bboxes_cam3d = np.zeros((0, self.bbox_code_size),
dtype=np.float32)
centers2d = np.zeros((0, 2), dtype=np.float32)
depths = np.zeros((0), dtype=np.float32)
gt_bboxes_cam3d = CameraInstance3DBoxes(
gt_bboxes_cam3d,
box_dim=gt_bboxes_cam3d.shape[-1],
origin=(0.5, 0.5, 0.5))
gt_labels_3d = copy.deepcopy(gt_labels)
if gt_bboxes_ignore:
gt_bboxes_ignore = np.array(gt_bboxes_ignore, dtype=np.float32)
else:
gt_bboxes_ignore = np.zeros((0, 4), dtype=np.float32)
seg_map = img_info['filename'].replace('jpg', 'png')
ann = dict(
bboxes=gt_bboxes,
labels=gt_labels,
gt_bboxes_3d=gt_bboxes_cam3d,
gt_labels_3d=gt_labels_3d,
centers2d=centers2d,
depths=depths,
bboxes_ignore=gt_bboxes_ignore,
masks=gt_masks_ann,
seg_map=seg_map)
return ann
def format_results(self,
outputs,
pklfile_prefix=None,
submission_prefix=None):
"""Format the results to pkl file.
Args:
outputs (list[dict]): Testing results of the dataset.
pklfile_prefix (str): The prefix of pkl files. It includes
the file path and the prefix of filename, e.g., "a/b/prefix".
If not specified, a temp file will be created. Default: None.
submission_prefix (str): The prefix of submitted files. It
includes the file path and the prefix of filename, e.g.,
"a/b/prefix". If not specified, a temp file will be created.
Default: None.
Returns:
tuple: (result_files, tmp_dir), result_files is a dict containing
the json filepaths, tmp_dir is the temporal directory created
for saving json files when jsonfile_prefix is not specified.
"""
if pklfile_prefix is None:
tmp_dir = tempfile.TemporaryDirectory()
pklfile_prefix = osp.join(tmp_dir.name, 'results')
else:
tmp_dir = None
if not isinstance(outputs[0], dict):
result_files = self.bbox2result_kitti2d(outputs, self.CLASSES,
pklfile_prefix,
submission_prefix)
elif 'pts_bbox' in outputs[0] or 'img_bbox' in outputs[0] or \
'img_bbox2d' in outputs[0]:
result_files = dict()
for name in outputs[0]:
results_ = [out[name] for out in outputs]
pklfile_prefix_ = pklfile_prefix + name
if submission_prefix is not None:
submission_prefix_ = submission_prefix + name
else:
submission_prefix_ = None
if '2d' in name:
result_files_ = self.bbox2result_kitti2d(
results_, self.CLASSES, pklfile_prefix_,
submission_prefix_)
else:
result_files_ = self.bbox2result_kitti(
results_, self.CLASSES, pklfile_prefix_,
submission_prefix_)
result_files[name] = result_files_
else:
result_files = self.bbox2result_kitti(outputs, self.CLASSES,
pklfile_prefix,
submission_prefix)
return result_files, tmp_dir
def evaluate(self,
results,
metric=None,
logger=None,
pklfile_prefix=None,
submission_prefix=None,
show=False,
out_dir=None,
pipeline=None):
"""Evaluation in KITTI protocol.
Args:
results (list[dict]): Testing results of the dataset.
metric (str | list[str], optional): Metrics to be evaluated.
Defaults to None.
logger (logging.Logger | str, optional): Logger used for printing
related information during evaluation. Default: None.
pklfile_prefix (str, optional): The prefix of pkl files, including
the file path and the prefix of filename, e.g., "a/b/prefix".
If not specified, a temp file will be created. Default: None.
submission_prefix (str, optional): The prefix of submission data.
If not specified, the submission data will not be generated.
show (bool, optional): Whether to visualize.
Default: False.
out_dir (str, optional): Path to save the visualization results.
Default: None.
pipeline (list[dict], optional): raw data loading for showing.
Default: None.
Returns:
dict[str, float]: Results of each evaluation metric.
"""
result_files, tmp_dir = self.format_results(results, pklfile_prefix)
from mmdet3d.core.evaluation import kitti_eval
gt_annos = [info['annos'] for info in self.anno_infos]
if isinstance(result_files, dict):
ap_dict = dict()
for name, result_files_ in result_files.items():
eval_types = ['bbox', 'bev', '3d']
if '2d' in name:
eval_types = ['bbox']
ap_result_str, ap_dict_ = kitti_eval(
gt_annos,
result_files_,
self.CLASSES,
eval_types=eval_types)
for ap_type, ap in ap_dict_.items():
ap_dict[f'{name}/{ap_type}'] = float('{:.4f}'.format(ap))
print_log(
f'Results of {name}:\n' + ap_result_str, logger=logger)
else:
if metric == 'img_bbox2d':
ap_result_str, ap_dict = kitti_eval(
gt_annos, result_files, self.CLASSES, eval_types=['bbox'])
else:
ap_result_str, ap_dict = kitti_eval(gt_annos, result_files,
self.CLASSES)
print_log('\n' + ap_result_str, logger=logger)
if tmp_dir is not None:
tmp_dir.cleanup()
if show or out_dir:
self.show(results, out_dir, show=show, pipeline=pipeline)
return ap_dict
def bbox2result_kitti(self,
net_outputs,
class_names,
pklfile_prefix=None,
submission_prefix=None):
"""Convert 3D detection results to kitti format for evaluation and test
submission.
Args:
net_outputs (list[np.ndarray]): List of array storing the
inferenced bounding boxes and scores.
class_names (list[String]): A list of class names.
pklfile_prefix (str): The prefix of pkl file.
submission_prefix (str): The prefix of submission file.
Returns:
list[dict]: A list of dictionaries with the kitti format.
"""
assert len(net_outputs) == len(self.anno_infos)
if submission_prefix is not None:
mmcv.mkdir_or_exist(submission_prefix)
det_annos = []
print('\nConverting prediction to KITTI format')
for idx, pred_dicts in enumerate(
mmcv.track_iter_progress(net_outputs)):
annos = []
info = self.anno_infos[idx]
sample_idx = info['image']['image_idx']
image_shape = info['image']['image_shape'][:2]
box_dict = self.convert_valid_bboxes(pred_dicts, info)
anno = {
'name': [],
'truncated': [],
'occluded': [],
'alpha': [],
'bbox': [],
'dimensions': [],
'location': [],
'rotation_y': [],
'score': []
}
if len(box_dict['bbox']) > 0:
box_2d_preds = box_dict['bbox']
box_preds = box_dict['box3d_camera']
scores = box_dict['scores']
box_preds_lidar = box_dict['box3d_lidar']
label_preds = box_dict['label_preds']
for box, box_lidar, bbox, score, label in zip(
box_preds, box_preds_lidar, box_2d_preds, scores,
label_preds):
bbox[2:] = np.minimum(bbox[2:], image_shape[::-1])
bbox[:2] = np.maximum(bbox[:2], [0, 0])
anno['name'].append(class_names[int(label)])
anno['truncated'].append(0.0)
anno['occluded'].append(0)
anno['alpha'].append(-np.arctan2(box[0], box[2]) + box[6])
anno['bbox'].append(bbox)
anno['dimensions'].append(box[3:6])
anno['location'].append(box[:3])
anno['rotation_y'].append(box[6])
anno['score'].append(score)
anno = {k: np.stack(v) for k, v in anno.items()}
annos.append(anno)
else:
anno = {
'name': np.array([]),
'truncated': np.array([]),
'occluded': np.array([]),
'alpha': np.array([]),
'bbox': np.zeros([0, 4]),
'dimensions': np.zeros([0, 3]),
'location': np.zeros([0, 3]),
'rotation_y': np.array([]),
'score': np.array([]),
}
annos.append(anno)
if submission_prefix is not None:
curr_file = f'{submission_prefix}/{sample_idx:06d}.txt'
with open(curr_file, 'w') as f:
bbox = anno['bbox']
loc = anno['location']
dims = anno['dimensions'] # lhw -> hwl
for idx in range(len(bbox)):
print(
'{} -1 -1 {:.4f} {:.4f} {:.4f} {:.4f} '
'{:.4f} {:.4f} {:.4f} '
'{:.4f} {:.4f} {:.4f} {:.4f} {:.4f} {:.4f}'.format(
anno['name'][idx], anno['alpha'][idx],
bbox[idx][0], bbox[idx][1], bbox[idx][2],
bbox[idx][3], dims[idx][1], dims[idx][2],
dims[idx][0], loc[idx][0], loc[idx][1],
loc[idx][2], anno['rotation_y'][idx],
anno['score'][idx]),
file=f)
annos[-1]['sample_idx'] = np.array(
[sample_idx] * len(annos[-1]['score']), dtype=np.int64)
det_annos += annos
if pklfile_prefix is not None:
if not pklfile_prefix.endswith(('.pkl', '.pickle')):
out = f'{pklfile_prefix}.pkl'
mmcv.dump(det_annos, out)
print('Result is saved to %s' % out)
return det_annos
def bbox2result_kitti2d(self,
net_outputs,
class_names,
pklfile_prefix=None,
submission_prefix=None):
"""Convert 2D detection results to kitti format for evaluation and test
submission.
Args:
net_outputs (list[np.ndarray]): List of array storing the
inferenced bounding boxes and scores.
class_names (list[String]): A list of class names.
pklfile_prefix (str): The prefix of pkl file.
submission_prefix (str): The prefix of submission file.
Returns:
list[dict]: A list of dictionaries have the kitti format
"""
assert len(net_outputs) == len(self.anno_infos)
det_annos = []
print('\nConverting prediction to KITTI format')
for i, bboxes_per_sample in enumerate(
mmcv.track_iter_progress(net_outputs)):
annos = []
anno = dict(
name=[],
truncated=[],
occluded=[],
alpha=[],
bbox=[],
dimensions=[],
location=[],
rotation_y=[],
score=[])
sample_idx = self.anno_infos[i]['image']['image_idx']
num_example = 0
for label in range(len(bboxes_per_sample)):
bbox = bboxes_per_sample[label]
for i in range(bbox.shape[0]):
anno['name'].append(class_names[int(label)])
anno['truncated'].append(0.0)
anno['occluded'].append(0)
anno['alpha'].append(-10)
anno['bbox'].append(bbox[i, :4])
# set dimensions (height, width, length) to zero
anno['dimensions'].append(
np.zeros(shape=[3], dtype=np.float32))
# set the 3D translation to (-1000, -1000, -1000)
anno['location'].append(
np.ones(shape=[3], dtype=np.float32) * (-1000.0))
anno['rotation_y'].append(0.0)
anno['score'].append(bbox[i, 4])
num_example += 1
if num_example == 0:
annos.append(
dict(
name=np.array([]),
truncated=np.array([]),
occluded=np.array([]),
alpha=np.array([]),
bbox=np.zeros([0, 4]),
dimensions=np.zeros([0, 3]),
location=np.zeros([0, 3]),
rotation_y=np.array([]),
score=np.array([]),
))
else:
anno = {k: np.stack(v) for k, v in anno.items()}
annos.append(anno)
annos[-1]['sample_idx'] = np.array(
[sample_idx] * num_example, dtype=np.int64)
det_annos += annos
if pklfile_prefix is not None:
if not pklfile_prefix.endswith(('.pkl', '.pickle')):
out = f'{pklfile_prefix}.pkl'
mmcv.dump(det_annos, out)
print('Result is saved to %s' % out)
if submission_prefix is not None:
# save file in submission format
mmcv.mkdir_or_exist(submission_prefix)
print(f'Saving KITTI submission to {submission_prefix}')
for i, anno in enumerate(det_annos):
sample_idx = self.anno_infos[i]['image']['image_idx']
cur_det_file = f'{submission_prefix}/{sample_idx:06d}.txt'
with open(cur_det_file, 'w') as f:
bbox = anno['bbox']
loc = anno['location']
dims = anno['dimensions'][::-1] # lhw -> hwl
for idx in range(len(bbox)):
print(
'{} -1 -1 {:4f} {:4f} {:4f} {:4f} {:4f} {:4f} '
'{:4f} {:4f} {:4f} {:4f} {:4f} {:4f} {:4f}'.format(
anno['name'][idx],
anno['alpha'][idx],
*bbox[idx], # 4 float
*dims[idx], # 3 float
*loc[idx], # 3 float
anno['rotation_y'][idx],
anno['score'][idx]),
file=f,
)
print(f'Result is saved to {submission_prefix}')
return det_annos
def convert_valid_bboxes(self, box_dict, info):
"""Convert the predicted boxes into valid ones.
Args:
box_dict (dict): Box dictionaries to be converted.
- boxes_3d (:obj:`CameraInstance3DBoxes`): 3D bounding boxes.
- scores_3d (torch.Tensor): Scores of boxes.
- labels_3d (torch.Tensor): Class labels of boxes.
info (dict): Data info.
Returns:
dict: Valid predicted boxes.
- bbox (np.ndarray): 2D bounding boxes.
- box3d_camera (np.ndarray): 3D bounding boxes in
camera coordinate.
- scores (np.ndarray): Scores of boxes.
- label_preds (np.ndarray): Class label predictions.
- sample_idx (int): Sample index.
"""
box_preds = box_dict['boxes_3d']
scores = box_dict['scores_3d']
labels = box_dict['labels_3d']
sample_idx = info['image']['image_idx']
if len(box_preds) == 0:
return dict(
bbox=np.zeros([0, 4]),
box3d_camera=np.zeros([0, 7]),
scores=np.zeros([0]),
label_preds=np.zeros([0, 4]),
sample_idx=sample_idx)
rect = info['calib']['R0_rect'].astype(np.float32)
Trv2c = info['calib']['Tr_velo_to_cam'].astype(np.float32)
P2 = info['calib']['P2'].astype(np.float32)
img_shape = info['image']['image_shape']
P2 = box_preds.tensor.new_tensor(P2)
box_preds_camera = box_preds
box_preds_lidar = box_preds.convert_to(Box3DMode.LIDAR,
np.linalg.inv(rect @ Trv2c))
box_corners = box_preds_camera.corners
box_corners_in_image = points_cam2img(box_corners, P2)
# box_corners_in_image: [N, 8, 2]
minxy = torch.min(box_corners_in_image, dim=1)[0]
maxxy = torch.max(box_corners_in_image, dim=1)[0]
box_2d_preds = torch.cat([minxy, maxxy], dim=1)
# Post-processing
# check box_preds_camera
image_shape = box_preds.tensor.new_tensor(img_shape)
valid_cam_inds = ((box_2d_preds[:, 0] < image_shape[1]) &
(box_2d_preds[:, 1] < image_shape[0]) &
(box_2d_preds[:, 2] > 0) & (box_2d_preds[:, 3] > 0))
# check box_preds
valid_inds = valid_cam_inds
if valid_inds.sum() > 0:
return dict(
bbox=box_2d_preds[valid_inds, :].numpy(),
box3d_camera=box_preds_camera[valid_inds].tensor.numpy(),
box3d_lidar=box_preds_lidar[valid_inds].tensor.numpy(),
scores=scores[valid_inds].numpy(),
label_preds=labels[valid_inds].numpy(),
sample_idx=sample_idx)
else:
return dict(
bbox=np.zeros([0, 4]),
box3d_camera=np.zeros([0, 7]),
box3d_lidar=np.zeros([0, 7]),
scores=np.zeros([0]),
label_preds=np.zeros([0, 4]),
sample_idx=sample_idx)
...@@ -4,7 +4,7 @@ from typing import Dict, List ...@@ -4,7 +4,7 @@ from typing import Dict, List
import numpy as np import numpy as np
from mmdet3d.registry import DATASETS from mmdet3d.registry import DATASETS
from ..core.bbox import LiDARInstance3DBoxes from mmdet3d.structures import LiDARInstance3DBoxes
from .det3d_dataset import Det3DDataset from .det3d_dataset import Det3DDataset
......
...@@ -4,9 +4,9 @@ from typing import Dict, List ...@@ -4,9 +4,9 @@ from typing import Dict, List
import numpy as np import numpy as np
from mmdet3d.core.bbox.structures.cam_box3d import CameraInstance3DBoxes
from mmdet3d.registry import DATASETS from mmdet3d.registry import DATASETS
from ..core.bbox import LiDARInstance3DBoxes from mmdet3d.structures import LiDARInstance3DBoxes
from mmdet3d.structures.bbox_3d.cam_box3d import CameraInstance3DBoxes
from .det3d_dataset import Det3DDataset from .det3d_dataset import Det3DDataset
......
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