├── strix ├── models │ ├── README.md │ ├── cnn │ │ ├── __init__.py │ │ ├── engines │ │ │ ├── __init__.py │ │ │ └── gan_engines.py │ │ ├── nets │ │ │ └── multihead_net.py │ │ └── losses │ │ │ └── __init__.py │ ├── rcnn │ │ ├── modeling │ │ │ ├── __init__.py │ │ │ ├── roi_heads │ │ │ │ ├── __init__.py │ │ │ │ ├── box_head │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── roi_box_predictors.py │ │ │ │ ├── mask_head │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── roi_mask_predictors.py │ │ │ │ │ └── roi_mask_feature_extractors.py │ │ │ │ └── keypoint_head │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── roi_keypoint_predictors.py │ │ │ │ │ ├── roi_keypoint_feature_extractors.py │ │ │ │ │ └── keypoint_head.py │ │ │ ├── rpn │ │ │ │ ├── fcos │ │ │ │ │ └── __init__.py │ │ │ │ ├── retinanet │ │ │ │ │ └── __init__.py │ │ │ │ ├── __init__.py │ │ │ │ └── utils.py │ │ │ ├── detector │ │ │ │ ├── __init__.py │ │ │ │ ├── detectors.py │ │ │ │ └── generalized_rcnn.py │ │ │ ├── backbone │ │ │ │ └── __init__.py │ │ │ ├── registry.py │ │ │ ├── utils.py │ │ │ └── balanced_positive_negative_sampler.py │ │ ├── utils │ │ │ ├── __init__.py │ │ │ ├── README.md │ │ │ ├── miscellaneous.py │ │ │ ├── collect_env.py │ │ │ ├── cv2_util.py │ │ │ ├── logger.py │ │ │ ├── imports.py │ │ │ ├── timer.py │ │ │ ├── env.py │ │ │ ├── registry.py │ │ │ └── metric_logger.py │ │ ├── structures │ │ │ ├── __init__.py │ │ │ └── image_list.py │ │ ├── engine │ │ │ └── __init__.py │ │ ├── config │ │ │ └── __init__.py │ │ ├── data │ │ │ ├── __init__.py │ │ │ ├── datasets │ │ │ │ ├── __init__.py │ │ │ │ ├── evaluation │ │ │ │ │ ├── voc │ │ │ │ │ │ └── __init__.py │ │ │ │ │ ├── coco │ │ │ │ │ │ └── __init__.py │ │ │ │ │ └── __init__.py │ │ │ │ ├── concat_dataset.py │ │ │ │ └── list_dataset.py │ │ │ ├── transforms │ │ │ │ ├── __init__.py │ │ │ │ ├── build.py │ │ │ │ └── transforms.py │ │ │ ├── samplers │ │ │ │ ├── __init__.py │ │ │ │ ├── iteration_based_batch_sampler.py │ │ │ │ └── distributed.py │ │ │ └── collate_batch.py │ │ ├── solver │ │ │ ├── __init__.py │ │ │ ├── build.py │ │ │ └── lr_scheduler.py │ │ ├── layers │ │ │ ├── nms.py │ │ │ ├── scale.py │ │ │ ├── smooth_l1_loss.py │ │ │ ├── __init__.py │ │ │ ├── batch_norm.py │ │ │ ├── _utils.py │ │ │ ├── iou_loss.py │ │ │ ├── roi_pool.py │ │ │ ├── roi_align.py │ │ │ └── sigmoid_focal_loss.py │ │ ├── csrc │ │ │ ├── cpu │ │ │ │ ├── vision.h │ │ │ │ └── nms_cpu.cpp │ │ │ ├── vision.cpp │ │ │ ├── nms.h │ │ │ ├── SigmoidFocalLoss.h │ │ │ ├── ROIPool.h │ │ │ ├── ROIAlign.h │ │ │ └── cuda │ │ │ │ └── vision.h │ │ └── __init__.py │ └── transformer │ │ ├── __init__.py │ │ └── transformer_nets.py ├── tests │ ├── __init__.py │ ├── conftest.py │ ├── test_dataset_from_cfg │ ├── test_ContrastiveLoss │ ├── test_classification_datasets.py │ ├── test_output_onehot_transform │ ├── test_siamesedataset │ ├── test_click_numeric_choice.py │ ├── test_basicclassificationdataset.py │ ├── test_TensoboardDumper │ └── test_click_remeber_last.py ├── __init__.py ├── data_io │ ├── base_dataset │ │ ├── __init__.py │ │ ├── utils.py │ │ ├── selflearning_dataset.py │ │ ├── classification_dataset.py │ │ └── segmentation_dataset.py │ └── __init__.py ├── misc │ ├── configs │ │ ├── rpn_R_50_C4_1x.yaml │ │ ├── e2e_faster_rcnn_R_50_C4_1x.yaml │ │ ├── pascal_voc │ │ │ ├── e2e_faster_rcnn_R_50_C4_1x_1_gpu_voc.yaml │ │ │ ├── e2e_faster_rcnn_R_50_C4_1x_4_gpu_voc.yaml │ │ │ └── e2e_mask_rcnn_R_50_FPN_1x_cocostyle.yaml │ │ ├── e2e_mask_rcnn_R_50_C4_1x.yaml │ │ ├── quick_schedules │ │ │ ├── rpn_R_50_C4_quick.yaml │ │ │ ├── e2e_faster_rcnn_R_50_C4_quick.yaml │ │ │ ├── e2e_mask_rcnn_R_50_C4_quick.yaml │ │ │ ├── rpn_R_50_FPN_quick.yaml │ │ │ ├── e2e_faster_rcnn_R_50_FPN_quick.yaml │ │ │ ├── e2e_faster_rcnn_X_101_32x8d_FPN_quick.yaml │ │ │ ├── e2e_mask_rcnn_R_50_FPN_quick.yaml │ │ │ ├── e2e_keypoint_rcnn_R_50_FPN_quick.yaml │ │ │ └── e2e_mask_rcnn_X_101_32x8d_FPN_quick.yaml │ │ ├── rpn_R_101_FPN_1x.yaml │ │ ├── rpn_R_50_FPN_1x.yaml │ │ ├── fcos │ │ │ ├── fcos_R_50_FPN_1x.yaml │ │ │ ├── fcos_R_101_FPN_2x.yaml │ │ │ ├── fcos_R_50_FPN_1x_center.yaml │ │ │ ├── fcos_R_50_FPN_1x_center_giou.yaml │ │ │ ├── fcos_bn_bs16_MNV2_FPN_1x.yaml │ │ │ ├── fcos_X_101_32x8d_FPN_2x.yaml │ │ │ ├── fcos_X_101_64x4d_FPN_2x.yaml │ │ │ ├── fcos_syncbn_bs32_MNV2_FPN_1x.yaml │ │ │ ├── fcos_syncbn_bs32_c128_MNV2_FPN_1x.yaml │ │ │ ├── fcos_syncbn_bs32_c128_ms_MNV2_FPN_1x.yaml │ │ │ └── fcos_syncbn_bs64_c128_ms_MNV2_FPN_1x.yaml │ │ ├── rpn_X_101_32x8d_FPN_1x.yaml │ │ ├── gn_baselines │ │ │ ├── README.md │ │ │ ├── e2e_faster_rcnn_R_50_FPN_1x_gn.yaml │ │ │ ├── scratch_e2e_faster_rcnn_R_50_FPN_3x_gn.yaml │ │ │ ├── e2e_faster_rcnn_R_50_FPN_Xconv1fc_1x_gn.yaml │ │ │ ├── scratch_e2e_faster_rcnn_R_50_FPN_Xconv1fc_3x_gn.yaml │ │ │ ├── e2e_mask_rcnn_R_50_FPN_1x_gn.yaml │ │ │ ├── scratch_e2e_mask_rcnn_R_50_FPN_3x_gn.yaml │ │ │ ├── e2e_mask_rcnn_R_50_FPN_Xconv1fc_1x_gn.yaml │ │ │ └── scratch_e2e_mask_rcnn_R_50_FPN_Xconv1fc_3x_gn.yaml │ │ ├── e2e_faster_rcnn_R_101_FPN_1x.yaml │ │ ├── e2e_faster_rcnn_R_50_FPN_1x.yaml │ │ ├── cityscapes │ │ │ ├── e2e_faster_rcnn_R_50_FPN_1x_cocostyle.yaml │ │ │ └── e2e_mask_rcnn_R_50_FPN_1x_cocostyle.yaml │ │ ├── e2e_faster_rcnn_X_101_32x8d_FPN_1x.yaml │ │ ├── e2e_faster_rcnn_fbnet.yaml │ │ ├── e2e_faster_rcnn_fbnet_600.yaml │ │ ├── e2e_faster_rcnn_fbnet_chamv1a_600.yaml │ │ ├── e2e_mask_rcnn_R_50_FPN_1x.yaml │ │ ├── e2e_mask_rcnn_R_101_FPN_1x.yaml │ │ ├── retinanet │ │ │ ├── retinanet_R-50-FPN_1x_quick.yaml │ │ │ ├── retinanet_R-50-FPN_1x.yaml │ │ │ ├── retinanet_R-101-FPN_1x.yaml │ │ │ ├── retinanet_R-50-FPN_P5_1x.yaml │ │ │ ├── retinanet_R-101-FPN_P5_1x.yaml │ │ │ └── retinanet_X_101_32x8d_FPN_1x.yaml │ │ ├── e2e_mask_rcnn_X_101_32x8d_FPN_1x.yaml │ │ ├── e2e_keypoint_rcnn_R_50_FPN_1x.yaml │ │ ├── e2e_mask_rcnn_fbnet.yaml │ │ ├── e2e_mask_rcnn_fbnet_600.yaml │ │ ├── e2e_mask_rcnn_fbnet_xirb16d_dsmask.yaml │ │ └── e2e_mask_rcnn_fbnet_xirb16d_dsmask_600.yaml │ └── nni_template_config.yml ├── utilities │ ├── imports.py │ ├── transforms.py │ ├── oyaml.py │ └── enum.py ├── configures │ ├── __init__.py │ └── config.py └── main.py ├── .gitattributes ├── MANIFEST.in ├── docs ├── source │ ├── About Strix │ ├── Datasets │ │ ├── advanced.rst │ │ ├── how.rst │ │ └── what.rst │ ├── Commands │ │ ├── strix-train.rst │ │ ├── strix-check-data.rst │ │ ├── strix-nni-search.rst │ │ ├── strix-test-from-cfg.rst │ │ ├── strix-train-and-test.rst │ │ ├── strix-gradcam-from-cfg.rst │ │ └── strix-train-cfg.rst │ ├── Networks │ │ └── how.rst │ └── _static │ │ ├── icon.png │ │ ├── logo.png │ │ ├── banner.png │ │ ├── disentangle.png │ │ └── usage-example.png ├── requirements.txt ├── Makefile └── make.bat ├── images ├── logo.png ├── banner.png ├── Custom-Data.png ├── datalist-demo.png ├── disentangle.png ├── disentangle1.png ├── disentangle2.png ├── usage-example.png └── Design-Concept.png ├── .gitmodules ├── .readthedocs.yml ├── install.md ├── .gitignore └── setup.cfg /strix/models/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /strix/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /strix/models/cnn/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /strix/models/rcnn/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /strix/models/transformer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /strix/models/rcnn/structures/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/roi_heads/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/rpn/fcos/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | strix/_version.py export-subst 2 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/rpn/retinanet/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/roi_heads/box_head/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/roi_heads/mask_head/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/roi_heads/keypoint_head/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include versioneer.py 2 | include strix/_version.py 3 | -------------------------------------------------------------------------------- /docs/source/About Strix: -------------------------------------------------------------------------------- 1 | About Strix 2 | ======== 3 | ​ 4 | 这是我的公开日记 -------------------------------------------------------------------------------- /docs/source/Datasets/advanced.rst: -------------------------------------------------------------------------------- 1 | Advanced tips 2 | =============== -------------------------------------------------------------------------------- /docs/source/Commands/strix-train.rst: -------------------------------------------------------------------------------- 1 | strix-train 2 | ===================== -------------------------------------------------------------------------------- /docs/source/Datasets/how.rst: -------------------------------------------------------------------------------- 1 | Make your `Dataset` 2 | =================== -------------------------------------------------------------------------------- /docs/source/Networks/how.rst: -------------------------------------------------------------------------------- 1 | Make your `Network` 2 | =================== -------------------------------------------------------------------------------- /docs/source/Commands/strix-check-data.rst: -------------------------------------------------------------------------------- 1 | strix-check-data 2 | ================ -------------------------------------------------------------------------------- /docs/source/Commands/strix-nni-search.rst: -------------------------------------------------------------------------------- 1 | strix-nni-search 2 | ================ -------------------------------------------------------------------------------- /docs/source/Commands/strix-test-from-cfg.rst: -------------------------------------------------------------------------------- 1 | strix-test-from-cfg 2 | ==================== -------------------------------------------------------------------------------- /docs/source/Datasets/what.rst: -------------------------------------------------------------------------------- 1 | What is Strix's `Dataset`? 2 | =========================== -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/images/logo.png -------------------------------------------------------------------------------- /docs/source/Commands/strix-train-and-test.rst: -------------------------------------------------------------------------------- 1 | strix-train-and-test 2 | ==================== -------------------------------------------------------------------------------- /images/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/images/banner.png -------------------------------------------------------------------------------- /docs/source/Commands/strix-gradcam-from-cfg.rst: -------------------------------------------------------------------------------- 1 | strix-gradcam-from-cfg 2 | ======================= -------------------------------------------------------------------------------- /docs/source/Commands/strix-train-cfg.rst: -------------------------------------------------------------------------------- 1 | strix-train-from-cfg 2 | ============================= -------------------------------------------------------------------------------- /images/Custom-Data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/images/Custom-Data.png -------------------------------------------------------------------------------- /images/datalist-demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/images/datalist-demo.png -------------------------------------------------------------------------------- /images/disentangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/images/disentangle.png -------------------------------------------------------------------------------- /images/disentangle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/images/disentangle1.png -------------------------------------------------------------------------------- /images/disentangle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/images/disentangle2.png -------------------------------------------------------------------------------- /images/usage-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/images/usage-example.png -------------------------------------------------------------------------------- /images/Design-Concept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/images/Design-Concept.png -------------------------------------------------------------------------------- /docs/source/_static/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/docs/source/_static/icon.png -------------------------------------------------------------------------------- /docs/source/_static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/docs/source/_static/logo.png -------------------------------------------------------------------------------- /strix/models/rcnn/engine/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "MONAI_EX"] 2 | path = MONAI_EX 3 | url = https://github.com/Project-Strix/MONAI_EX.git 4 | -------------------------------------------------------------------------------- /docs/source/_static/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/docs/source/_static/banner.png -------------------------------------------------------------------------------- /docs/source/_static/disentangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/docs/source/_static/disentangle.png -------------------------------------------------------------------------------- /docs/source/_static/usage-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Project-Strix/Strix/HEAD/docs/source/_static/usage-example.png -------------------------------------------------------------------------------- /strix/models/rcnn/config/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from .defaults import _C as cfg 3 | -------------------------------------------------------------------------------- /strix/models/rcnn/data/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from .build import make_data_loader 3 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/rpn/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | # from .rpn import build_rpn 3 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/detector/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from .detectors import build_detection_model 3 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/backbone/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from .backbone import build_backbone 3 | from . import fbnet 4 | -------------------------------------------------------------------------------- /strix/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from click.testing import CliRunner 4 | 5 | 6 | @pytest.fixture(scope="function") 7 | def runner(request): 8 | return CliRunner() 9 | -------------------------------------------------------------------------------- /strix/models/rcnn/utils/README.md: -------------------------------------------------------------------------------- 1 | # Utility functions 2 | 3 | This folder contain utility functions that are not used in the 4 | core library, but are useful for building models or training 5 | code using the config system. 6 | -------------------------------------------------------------------------------- /strix/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | PY_REQUIRED_MAJOR = 3 5 | PY_REQUIRED_MINOR = 7 6 | 7 | from . import _version 8 | __version__ = _version.get_versions()['version'] 9 | 10 | __basedir__ = os.path.dirname(__file__) -------------------------------------------------------------------------------- /strix/models/rcnn/solver/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from .build import make_optimizer 3 | from .build import make_lr_scheduler 4 | from .lr_scheduler import WarmupMultiStepLR 5 | -------------------------------------------------------------------------------- /strix/tests/test_dataset_from_cfg: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from strix.data_io.generate_dataset import test_dataset_from_config 3 | 4 | 5 | fname = Path("/homes/clwang/test_config.yaml") 6 | test_dataset_from_config(fname, 'train', None) 7 | -------------------------------------------------------------------------------- /strix/models/rcnn/layers/nms.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | # from ._utils import _C 3 | from strix.models.rcnn import _C 4 | 5 | nms = _C.nms 6 | # nms.__doc__ = """ 7 | # This function performs Non-maximum suppresion""" 8 | -------------------------------------------------------------------------------- /strix/models/rcnn/data/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from .coco import COCODataset 3 | from .voc import PascalVOCDataset 4 | from .concat_dataset import ConcatDataset 5 | 6 | __all__ = ["COCODataset", "ConcatDataset", "PascalVOCDataset"] 7 | -------------------------------------------------------------------------------- /strix/models/rcnn/utils/miscellaneous.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import errno 3 | import os 4 | 5 | 6 | def mkdir(path): 7 | try: 8 | os.makedirs(path) 9 | except OSError as e: 10 | if e.errno != errno.EEXIST: 11 | raise 12 | -------------------------------------------------------------------------------- /strix/models/rcnn/data/transforms/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from .transforms import Compose 3 | from .transforms import Resize 4 | from .transforms import RandomHorizontalFlip 5 | from .transforms import ToTensor 6 | from .transforms import Normalize 7 | 8 | from .build import build_transforms 9 | -------------------------------------------------------------------------------- /strix/models/rcnn/layers/scale.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | 4 | 5 | class Scale(nn.Module): 6 | def __init__(self, init_value=1.0): 7 | super(Scale, self).__init__() 8 | self.scale = nn.Parameter(torch.FloatTensor([init_value])) 9 | 10 | def forward(self, input): 11 | return input * self.scale 12 | -------------------------------------------------------------------------------- /strix/tests/test_ContrastiveLoss: -------------------------------------------------------------------------------- 1 | import torch 2 | from strix.models.cnn.losses import ContrastiveLoss 3 | 4 | 5 | loss = ContrastiveLoss() 6 | output1 = torch.randn(5, 128) 7 | output2 = torch.randn(5, 128) 8 | target1 = torch.Tensor([1, 1, 1, 0, 0]) 9 | target2 = torch.Tensor([1, 1, 0, 1, 0]) 10 | 11 | loss(output1, output2, target1, target2) 12 | -------------------------------------------------------------------------------- /strix/data_io/base_dataset/__init__.py: -------------------------------------------------------------------------------- 1 | from strix.data_io.base_dataset.classification_dataset import BasicClassificationDataset 2 | from strix.data_io.base_dataset.segmentation_dataset import BasicSegmentationDataset 3 | from strix.data_io.base_dataset.selflearning_dataset import BasicSelflearningDataset 4 | from strix.data_io.base_dataset.siamese_dataset import BasicSiameseDataset -------------------------------------------------------------------------------- /strix/tests/test_classification_datasets.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from strix.data_io import CLASSIFICATION_DATASETS 3 | 4 | def test_classification_dataset(): 5 | dummy_cls_dataset = lambda file_list, phase, opts: [1,2,3] 6 | CLASSIFICATION_DATASETS.register('2D', 'dummy', '', '', dummy_cls_dataset) 7 | 8 | assert 'dummy' in CLASSIFICATION_DATASETS['2D'].keys() 9 | -------------------------------------------------------------------------------- /strix/tests/test_output_onehot_transform: -------------------------------------------------------------------------------- 1 | import torch 2 | from strix.models.cnn.utils import output_onehot_transform 3 | 4 | output = {} 5 | output["pred"] = torch.rand([5,2]) 6 | output["label"] = torch.rand([5]) 7 | 8 | pred, label = output_onehot_transform(output, n_classes=2) 9 | print(output['pred'].shape, output['label'].shape) 10 | print(pred.shape, label.shape) -------------------------------------------------------------------------------- /strix/models/rcnn/data/samplers/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from .distributed import DistributedSampler 3 | from .grouped_batch_sampler import GroupedBatchSampler 4 | from .iteration_based_batch_sampler import IterationBasedBatchSampler 5 | 6 | __all__ = ["DistributedSampler", "GroupedBatchSampler", "IterationBasedBatchSampler"] 7 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/detector/detectors.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from .generalized_rcnn import GeneralizedRCNN 3 | 4 | 5 | _DETECTION_META_ARCHITECTURES = {"GeneralizedRCNN": GeneralizedRCNN} 6 | 7 | 8 | def build_detection_model(cfg): 9 | meta_arch = _DETECTION_META_ARCHITECTURES[cfg.MODEL.META_ARCHITECTURE] 10 | return meta_arch(cfg) 11 | -------------------------------------------------------------------------------- /strix/models/rcnn/utils/collect_env.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import PIL 3 | 4 | from torch.utils.collect_env import get_pretty_env_info 5 | 6 | 7 | def get_pil_version(): 8 | return "\n Pillow ({})".format(PIL.__version__) 9 | 10 | 11 | def collect_env_info(): 12 | env_str = get_pretty_env_info() 13 | env_str += get_pil_version() 14 | return env_str 15 | -------------------------------------------------------------------------------- /strix/misc/configs/rpn_R_50_C4_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | RPN_ONLY: True 5 | RPN: 6 | PRE_NMS_TOP_N_TEST: 12000 7 | POST_NMS_TOP_N_TEST: 2000 8 | DATASETS: 9 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 10 | TEST: ("coco_2014_minival",) 11 | SOLVER: 12 | BASE_LR: 0.02 13 | WEIGHT_DECAY: 0.0001 14 | STEPS: (60000, 80000) 15 | MAX_ITER: 90000 16 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/registry.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | 3 | from strix.models.rcnn.utils.registry import Registry 4 | 5 | BACKBONES = Registry() 6 | RPN_HEADS = Registry() 7 | ROI_BOX_FEATURE_EXTRACTORS = Registry() 8 | ROI_BOX_PREDICTOR = Registry() 9 | ROI_KEYPOINT_FEATURE_EXTRACTORS = Registry() 10 | ROI_KEYPOINT_PREDICTOR = Registry() 11 | ROI_MASK_FEATURE_EXTRACTORS = Registry() 12 | ROI_MASK_PREDICTOR = Registry() 13 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_faster_rcnn_R_50_C4_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | RPN: 5 | PRE_NMS_TOP_N_TEST: 6000 6 | POST_NMS_TOP_N_TEST: 1000 7 | DATASETS: 8 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 9 | TEST: ("coco_2014_minival",) 10 | SOLVER: 11 | BASE_LR: 0.01 12 | WEIGHT_DECAY: 0.0001 13 | STEPS: (120000, 160000) 14 | MAX_ITER: 180000 15 | IMS_PER_BATCH: 8 16 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/utils.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | """ 3 | Miscellaneous utility functions 4 | """ 5 | 6 | import torch 7 | 8 | 9 | def cat(tensors, dim=0): 10 | """ 11 | Efficient version of torch.cat that avoids a copy if there is only a single element in a list 12 | """ 13 | assert isinstance(tensors, (list, tuple)) 14 | if len(tensors) == 1: 15 | return tensors[0] 16 | return torch.cat(tensors, dim) 17 | -------------------------------------------------------------------------------- /strix/models/cnn/engines/__init__.py: -------------------------------------------------------------------------------- 1 | from strix.utilities.registry import Registry 2 | 3 | TRAIN_ENGINES = Registry() 4 | TEST_ENGINES = Registry() 5 | ENSEMBLE_TEST_ENGINES = Registry() 6 | 7 | from strix.models.cnn.engines.segmentation_engines import * 8 | from strix.models.cnn.engines.classification_engines import * 9 | from strix.models.cnn.engines.selflearning_engines import * 10 | from strix.models.cnn.engines.multitask_engines import * 11 | from strix.models.cnn.engines.siamese_engines import * 12 | -------------------------------------------------------------------------------- /strix/tests/test_siamesedataset: -------------------------------------------------------------------------------- 1 | from monai_ex import data 2 | from strix.data_io import SIAMESE_DATASETS 3 | from monai_ex.data import DataLoader 4 | from utils_cw import get_items_from_file 5 | 6 | 7 | dataset = SIAMESE_DATASETS['2D']['jsph_mvi']( 8 | files_list=get_items_from_file("/homes/clwang/Data/jsph_lung/MVI/data_crops/datalist-train.json"), 9 | phase='valid', opts={}) 10 | loader = DataLoader(dataset=dataset, batch_size=5) 11 | 12 | for d in loader: 13 | print(type(d), len(d)) 14 | print(type(d[0]), len(d[0])) 15 | -------------------------------------------------------------------------------- /strix/models/rcnn/layers/smooth_l1_loss.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import torch 3 | 4 | 5 | # TODO maybe push this to nn? 6 | def smooth_l1_loss(input, target, beta=1. / 9, size_average=True): 7 | """ 8 | very similar to the smooth_l1_loss from pytorch, but with 9 | the extra beta parameter 10 | """ 11 | n = torch.abs(input - target) 12 | cond = n < beta 13 | loss = torch.where(cond, 0.5 * n ** 2 / beta, n - 0.5 * beta) 14 | if size_average: 15 | return loss.mean() 16 | return loss.sum() 17 | -------------------------------------------------------------------------------- /strix/utilities/imports.py: -------------------------------------------------------------------------------- 1 | import importlib 2 | import importlib.util 3 | import sys 4 | 5 | # from https://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa 6 | def import_file(module_name, file_path, make_importable=False): 7 | spec = importlib.util.spec_from_file_location(module_name, file_path) 8 | module = importlib.util.module_from_spec(spec) 9 | spec.loader.exec_module(module) 10 | if make_importable: 11 | sys.modules[module_name] = module 12 | return module -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | torch>=1.6 2 | pytorch-ignite==0.4.8 3 | numpy>=1.17 4 | itk>=5.2 5 | nibabel 6 | parameterized 7 | scikit-image>=0.14.2 8 | tensorboard 9 | commonmark==0.9.1 10 | recommonmark==0.6.0 11 | Sphinx 12 | pydata-sphinx-theme 13 | sphinxcontrib-applehelp 14 | sphinxcontrib-devhelp 15 | sphinxcontrib-htmlhelp 16 | sphinxcontrib-jsmath 17 | sphinxcontrib-qthelp 18 | sphinxcontrib-serializinghtml 19 | sphinx-autodoc-typehints==1.11.1 20 | sphinx-markdown-tables 21 | pandas 22 | tensorboardX 23 | imagecodecs; platform_system == "Linux" 24 | tifffile; platform_system == "Linux" 25 | pyyaml -------------------------------------------------------------------------------- /strix/misc/configs/pascal_voc/e2e_faster_rcnn_R_50_C4_1x_1_gpu_voc.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | RPN: 5 | PRE_NMS_TOP_N_TEST: 6000 6 | POST_NMS_TOP_N_TEST: 300 7 | ANCHOR_SIZES: (128, 256, 512) 8 | ROI_BOX_HEAD: 9 | NUM_CLASSES: 21 10 | DATASETS: 11 | TRAIN: ("voc_2007_train", "voc_2007_val") 12 | TEST: ("voc_2007_test",) 13 | SOLVER: 14 | BASE_LR: 0.001 15 | WEIGHT_DECAY: 0.0001 16 | STEPS: (50000, ) 17 | MAX_ITER: 70000 18 | IMS_PER_BATCH: 1 19 | TEST: 20 | IMS_PER_BATCH: 1 21 | -------------------------------------------------------------------------------- /strix/misc/configs/pascal_voc/e2e_faster_rcnn_R_50_C4_1x_4_gpu_voc.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | RPN: 5 | PRE_NMS_TOP_N_TEST: 6000 6 | POST_NMS_TOP_N_TEST: 300 7 | ANCHOR_SIZES: (128, 256, 512) 8 | ROI_BOX_HEAD: 9 | NUM_CLASSES: 21 10 | DATASETS: 11 | TRAIN: ("voc_2007_train", "voc_2007_val") 12 | TEST: ("voc_2007_test",) 13 | SOLVER: 14 | BASE_LR: 0.004 15 | WEIGHT_DECAY: 0.0001 16 | STEPS: (12500, ) 17 | MAX_ITER: 17500 18 | IMS_PER_BATCH: 4 19 | TEST: 20 | IMS_PER_BATCH: 4 21 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_mask_rcnn_R_50_C4_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | RPN: 5 | PRE_NMS_TOP_N_TEST: 6000 6 | POST_NMS_TOP_N_TEST: 1000 7 | ROI_MASK_HEAD: 8 | PREDICTOR: "MaskRCNNC4Predictor" 9 | SHARE_BOX_FEATURE_EXTRACTOR: True 10 | MASK_ON: True 11 | DATASETS: 12 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 13 | TEST: ("coco_2014_minival",) 14 | SOLVER: 15 | BASE_LR: 0.01 16 | WEIGHT_DECAY: 0.0001 17 | STEPS: (120000, 160000) 18 | MAX_ITER: 180000 19 | IMS_PER_BATCH: 8 20 | -------------------------------------------------------------------------------- /strix/models/rcnn/data/datasets/evaluation/voc/__init__.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from .voc_eval import do_voc_evaluation 4 | 5 | 6 | def voc_evaluation(dataset, predictions, output_folder, box_only, **_): 7 | logger = logging.getLogger("strix.models.rcnn.inference") 8 | if box_only: 9 | logger.warning("voc evaluation doesn't support box_only, ignored.") 10 | logger.info("performing voc evaluation, ignored iou_types.") 11 | return do_voc_evaluation( 12 | dataset=dataset, 13 | predictions=predictions, 14 | output_folder=output_folder, 15 | logger=logger, 16 | ) 17 | -------------------------------------------------------------------------------- /strix/misc/configs/quick_schedules/rpn_R_50_C4_quick.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | RPN_ONLY: True 5 | RPN: 6 | PRE_NMS_TOP_N_TEST: 12000 7 | POST_NMS_TOP_N_TEST: 2000 8 | DATASETS: 9 | TRAIN: ("coco_2014_minival",) 10 | TEST: ("coco_2014_minival",) 11 | INPUT: 12 | MIN_SIZE_TRAIN: (600,) 13 | MAX_SIZE_TRAIN: 1000 14 | MIN_SIZE_TEST: 800 15 | MAX_SIZE_TEST: 1000 16 | SOLVER: 17 | BASE_LR: 0.005 18 | WEIGHT_DECAY: 0.0001 19 | STEPS: (1500,) 20 | MAX_ITER: 2000 21 | IMS_PER_BATCH: 4 22 | TEST: 23 | IMS_PER_BATCH: 2 24 | -------------------------------------------------------------------------------- /strix/models/rcnn/data/datasets/evaluation/coco/__init__.py: -------------------------------------------------------------------------------- 1 | from .coco_eval import do_coco_evaluation 2 | 3 | 4 | def coco_evaluation( 5 | dataset, 6 | predictions, 7 | output_folder, 8 | box_only, 9 | iou_types, 10 | expected_results, 11 | expected_results_sigma_tol, 12 | ): 13 | return do_coco_evaluation( 14 | dataset=dataset, 15 | predictions=predictions, 16 | box_only=box_only, 17 | output_folder=output_folder, 18 | iou_types=iou_types, 19 | expected_results=expected_results, 20 | expected_results_sigma_tol=expected_results_sigma_tol, 21 | ) 22 | -------------------------------------------------------------------------------- /strix/misc/configs/quick_schedules/e2e_faster_rcnn_R_50_C4_quick.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | RPN: 5 | PRE_NMS_TOP_N_TEST: 6000 6 | POST_NMS_TOP_N_TEST: 1000 7 | ROI_HEADS: 8 | BATCH_SIZE_PER_IMAGE: 256 9 | DATASETS: 10 | TRAIN: ("coco_2014_minival",) 11 | TEST: ("coco_2014_minival",) 12 | INPUT: 13 | MIN_SIZE_TRAIN: (600,) 14 | MAX_SIZE_TRAIN: 1000 15 | MIN_SIZE_TEST: 800 16 | MAX_SIZE_TEST: 1000 17 | SOLVER: 18 | BASE_LR: 0.005 19 | WEIGHT_DECAY: 0.0001 20 | STEPS: (1500,) 21 | MAX_ITER: 2000 22 | IMS_PER_BATCH: 2 23 | TEST: 24 | IMS_PER_BATCH: 2 25 | -------------------------------------------------------------------------------- /strix/models/rcnn/csrc/cpu/vision.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | #pragma once 3 | #include 4 | 5 | 6 | at::Tensor ROIAlign_forward_cpu(const at::Tensor& input, 7 | const at::Tensor& rois, 8 | const float spatial_scale, 9 | const int pooled_height, 10 | const int pooled_width, 11 | const int sampling_ratio); 12 | 13 | 14 | at::Tensor nms_cpu(const at::Tensor& dets, 15 | const at::Tensor& scores, 16 | const float threshold); 17 | -------------------------------------------------------------------------------- /strix/misc/configs/rpn_R_101_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-101" 4 | RPN_ONLY: True 5 | BACKBONE: 6 | CONV_BODY: "R-101-FPN" 7 | RESNETS: 8 | BACKBONE_OUT_CHANNELS: 256 9 | RPN: 10 | USE_FPN: True 11 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 2000 14 | FPN_POST_NMS_TOP_N_TEST: 2000 15 | DATASETS: 16 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 17 | TEST: ("coco_2014_minival",) 18 | DATALOADER: 19 | SIZE_DIVISIBILITY: 32 20 | SOLVER: 21 | BASE_LR: 0.02 22 | WEIGHT_DECAY: 0.0001 23 | STEPS: (60000, 80000) 24 | MAX_ITER: 90000 25 | -------------------------------------------------------------------------------- /strix/misc/configs/rpn_R_50_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | RPN_ONLY: True 5 | BACKBONE: 6 | CONV_BODY: "R-50-FPN" 7 | RESNETS: 8 | BACKBONE_OUT_CHANNELS: 256 9 | RPN: 10 | USE_FPN: True 11 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 2000 14 | FPN_POST_NMS_TOP_N_TEST: 2000 15 | DATASETS: 16 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 17 | TEST: ("coco_2014_minival",) 18 | DATALOADER: 19 | SIZE_DIVISIBILITY: 32 20 | SOLVER: 21 | BASE_LR: 0.02 22 | WEIGHT_DECAY: 0.0001 23 | STEPS: (60000, 80000) 24 | MAX_ITER: 90000 25 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Build documentation in the docs/ directory with Sphinx 9 | sphinx: 10 | configuration: docs/source/conf.py 11 | 12 | # Build documentation with MkDocs 13 | #mkdocs: 14 | # configuration: mkdocs.yml 15 | 16 | # Optionally build your docs in additional formats such as PDF and ePub 17 | # formats: all 18 | 19 | # Optionally set the version of Python and requirements required to build your docs 20 | python: 21 | version: 3.7 22 | install: 23 | - requirements: docs/requirements.txt 24 | # system_packages: true 25 | 26 | 27 | build: 28 | image: stable -------------------------------------------------------------------------------- /strix/models/rcnn/utils/cv2_util.py: -------------------------------------------------------------------------------- 1 | """ 2 | Module for cv2 utility functions and maintaining version compatibility 3 | between 3.x and 4.x 4 | """ 5 | import cv2 6 | 7 | 8 | def findContours(*args, **kwargs): 9 | """ 10 | Wraps cv2.findContours to maintain compatiblity between versions 11 | 3 and 4 12 | 13 | Returns: 14 | contours, hierarchy 15 | """ 16 | if cv2.__version__.startswith('4'): 17 | contours, hierarchy = cv2.findContours(*args, **kwargs) 18 | elif cv2.__version__.startswith('3'): 19 | _, contours, hierarchy = cv2.findContours(*args, **kwargs) 20 | else: 21 | raise AssertionError( 22 | 'cv2 must be either version 3 or 4 to call this method') 23 | 24 | return contours, hierarchy 25 | -------------------------------------------------------------------------------- /strix/models/rcnn/data/collate_batch.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from strix.models.rcnn.structures.image_list import to_image_list 3 | 4 | 5 | class BatchCollator(object): 6 | """ 7 | From a list of samples from the dataset, 8 | returns the batched images and targets. 9 | This should be passed to the DataLoader 10 | """ 11 | 12 | def __init__(self, size_divisible=0): 13 | self.size_divisible = size_divisible 14 | 15 | def __call__(self, batch): 16 | transposed_batch = list(zip(*batch)) 17 | images = to_image_list(transposed_batch[0], self.size_divisible) 18 | targets = transposed_batch[1] 19 | img_ids = transposed_batch[2] 20 | return images, targets, img_ids 21 | -------------------------------------------------------------------------------- /strix/misc/configs/quick_schedules/e2e_mask_rcnn_R_50_C4_quick.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | RPN: 5 | PRE_NMS_TOP_N_TEST: 6000 6 | POST_NMS_TOP_N_TEST: 1000 7 | ROI_HEADS: 8 | BATCH_SIZE_PER_IMAGE: 256 9 | ROI_MASK_HEAD: 10 | PREDICTOR: "MaskRCNNC4Predictor" 11 | SHARE_BOX_FEATURE_EXTRACTOR: True 12 | MASK_ON: True 13 | DATASETS: 14 | TRAIN: ("coco_2014_minival",) 15 | TEST: ("coco_2014_minival",) 16 | INPUT: 17 | MIN_SIZE_TRAIN: (600,) 18 | MAX_SIZE_TRAIN: 1000 19 | MIN_SIZE_TEST: 800 20 | MAX_SIZE_TEST: 1000 21 | SOLVER: 22 | BASE_LR: 0.005 23 | WEIGHT_DECAY: 0.0001 24 | STEPS: (1500,) 25 | MAX_ITER: 2000 26 | IMS_PER_BATCH: 4 27 | TEST: 28 | IMS_PER_BATCH: 2 29 | -------------------------------------------------------------------------------- /strix/models/rcnn/csrc/vision.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | #include "nms.h" 3 | #include "ROIAlign.h" 4 | #include "ROIPool.h" 5 | #include "SigmoidFocalLoss.h" 6 | 7 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 8 | m.def("nms", &nms, "non-maximum suppression"); 9 | m.def("roi_align_forward", &ROIAlign_forward, "ROIAlign_forward"); 10 | m.def("roi_align_backward", &ROIAlign_backward, "ROIAlign_backward"); 11 | m.def("roi_pool_forward", &ROIPool_forward, "ROIPool_forward"); 12 | m.def("roi_pool_backward", &ROIPool_backward, "ROIPool_backward"); 13 | m.def("sigmoid_focalloss_forward", &SigmoidFocalLoss_forward, "SigmoidFocalLoss_forward"); 14 | m.def("sigmoid_focalloss_backward", &SigmoidFocalLoss_backward, "SigmoidFocalLoss_backward"); 15 | } 16 | -------------------------------------------------------------------------------- /strix/misc/configs/fcos/fcos_R_50_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "pretrain_models/R-50.pkl" 4 | RPN_ONLY: True 5 | FCOS_ON: True 6 | BACKBONE: 7 | CONV_BODY: "R-50-FPN-RETINANET" 8 | RESNETS: 9 | BACKBONE_OUT_CHANNELS: 256 10 | RETINANET: 11 | USE_C5: False # FCOS uses P5 instead of C5 12 | FCOS: 13 | CENTER_SAMPLE: False 14 | DATASETS: 15 | TRAIN: ("coco_2017_train", ) 16 | TEST: ("coco_2017_val", ) 17 | INPUT: 18 | MIN_SIZE_TRAIN: (800,) 19 | MAX_SIZE_TRAIN: 1333 20 | MIN_SIZE_TEST: 800 21 | MAX_SIZE_TEST: 1333 22 | DATALOADER: 23 | SIZE_DIVISIBILITY: 32 24 | SOLVER: 25 | BASE_LR: 0.01 26 | WEIGHT_DECAY: 0.0001 27 | STEPS: (60000, 80000) 28 | MAX_ITER: 90000 29 | IMS_PER_BATCH: 16 30 | WARMUP_METHOD: "constant" 31 | -------------------------------------------------------------------------------- /strix/misc/configs/rpn_X_101_32x8d_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/FAIR/20171220/X-101-32x8d" 4 | RPN_ONLY: True 5 | BACKBONE: 6 | CONV_BODY: "R-101-FPN" 7 | RESNETS: 8 | BACKBONE_OUT_CHANNELS: 256 9 | STRIDE_IN_1X1: False 10 | NUM_GROUPS: 32 11 | WIDTH_PER_GROUP: 8 12 | RPN: 13 | USE_FPN: True 14 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 15 | PRE_NMS_TOP_N_TEST: 1000 16 | POST_NMS_TOP_N_TEST: 2000 17 | FPN_POST_NMS_TOP_N_TEST: 2000 18 | DATASETS: 19 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 20 | TEST: ("coco_2014_minival",) 21 | DATALOADER: 22 | SIZE_DIVISIBILITY: 32 23 | SOLVER: 24 | BASE_LR: 0.02 25 | WEIGHT_DECAY: 0.0001 26 | STEPS: (60000, 80000) 27 | MAX_ITER: 90000 28 | -------------------------------------------------------------------------------- /strix/misc/configs/fcos/fcos_R_101_FPN_2x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-101" 4 | RPN_ONLY: True 5 | FCOS_ON: True 6 | BACKBONE: 7 | CONV_BODY: "R-101-FPN-RETINANET" 8 | RESNETS: 9 | BACKBONE_OUT_CHANNELS: 256 10 | RETINANET: 11 | USE_C5: False # FCOS uses P5 instead of C5 12 | DATASETS: 13 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 14 | TEST: ("coco_2014_minival",) 15 | INPUT: 16 | MIN_SIZE_RANGE_TRAIN: (640, 800) 17 | MAX_SIZE_TRAIN: 1333 18 | MIN_SIZE_TEST: 800 19 | MAX_SIZE_TEST: 1333 20 | DATALOADER: 21 | SIZE_DIVISIBILITY: 32 22 | SOLVER: 23 | BASE_LR: 0.01 24 | WEIGHT_DECAY: 0.0001 25 | STEPS: (120000, 160000) 26 | MAX_ITER: 180000 27 | IMS_PER_BATCH: 16 28 | WARMUP_METHOD: "constant" -------------------------------------------------------------------------------- /strix/misc/configs/fcos/fcos_R_50_FPN_1x_center.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "pretrain_models/R-50.pkl" 4 | RPN_ONLY: True 5 | FCOS_ON: True 6 | BACKBONE: 7 | CONV_BODY: "R-50-FPN-RETINANET" 8 | RESNETS: 9 | BACKBONE_OUT_CHANNELS: 256 10 | RETINANET: 11 | USE_C5: False # FCOS uses P5 instead of C5 12 | FCOS: 13 | CENTER_SAMPLE: True 14 | POS_RADIUS: 1.5 15 | DATASETS: 16 | TRAIN: ("coco_2017_train", ) 17 | TEST: ("coco_2017_val", ) 18 | INPUT: 19 | MIN_SIZE_TRAIN: (800,) 20 | MAX_SIZE_TRAIN: 1333 21 | MIN_SIZE_TEST: 800 22 | MAX_SIZE_TEST: 1333 23 | DATALOADER: 24 | SIZE_DIVISIBILITY: 32 25 | SOLVER: 26 | BASE_LR: 0.01 27 | WEIGHT_DECAY: 0.0001 28 | STEPS: (60000, 80000) 29 | MAX_ITER: 90000 30 | IMS_PER_BATCH: 16 31 | WARMUP_METHOD: "constant" 32 | -------------------------------------------------------------------------------- /strix/misc/nni_template_config.yml: -------------------------------------------------------------------------------- 1 | authorName: default 2 | experimentName: select_hyparam_catheter 3 | trialConcurrency: 1 4 | maxExecDuration: 30h 5 | maxTrialNum: 200 6 | #choice: local, remote, pai 7 | trainingServicePlatform: local 8 | searchSpacePath: search_space.json 9 | #choice: true, false 10 | useAnnotation: false 11 | # localConfig: 12 | # gpuIndices: None 13 | tuner: 14 | builtinTunerName: TPE 15 | classArgs: 16 | optimize_mode: maximize 17 | parallel_optimize: True 18 | constant_liar_type: min 19 | assessor: 20 | builtinAssessorName: Curvefitting 21 | classArgs: 22 | epoch_num: 100 23 | start_step: 20 24 | threshold: 0.95 25 | gap: 1 26 | trial: 27 | command: python main.py train-fcfg --config "/homes/yliu/Code/strix/param.list" 28 | codeDir: . 29 | gpuNum: 0 30 | -------------------------------------------------------------------------------- /strix/utilities/transforms.py: -------------------------------------------------------------------------------- 1 | from typing import Sequence, Callable 2 | from monai.transforms import apply_transform 3 | 4 | def decollate_transform_adaptor(transfrom_fn: Callable): 5 | """Adaptor for transforms to handle decollated data. 6 | Making sure input data is a decollated sequence type. 7 | 8 | Args: 9 | transfrom_fn (Callable): target transform fn to be adapted. 10 | """ 11 | def _inner(input_data: Sequence): 12 | if isinstance(input_data, Sequence): 13 | return [apply_transform(transfrom_fn, data) for data in input_data] 14 | else: 15 | # if isinstance(input_data, dict) and 'pred' in input_data: 16 | # print(type(input_data.get('pred')), input_data.get('pred')) 17 | return apply_transform(transfrom_fn, input_data) 18 | return _inner 19 | -------------------------------------------------------------------------------- /strix/models/rcnn/csrc/nms.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | #pragma once 3 | #include "cpu/vision.h" 4 | 5 | #ifdef WITH_CUDA 6 | #include "cuda/vision.h" 7 | #endif 8 | 9 | 10 | at::Tensor nms(const at::Tensor& dets, 11 | const at::Tensor& scores, 12 | const float threshold) { 13 | 14 | if (dets.type().is_cuda()) { 15 | #ifdef WITH_CUDA 16 | // TODO raise error if not compiled with CUDA 17 | if (dets.numel() == 0) 18 | return at::empty({0}, dets.options().dtype(at::kLong).device(at::kCPU)); 19 | auto b = at::cat({dets, scores.unsqueeze(1)}, 1); 20 | return nms_cuda(b, threshold); 21 | #else 22 | AT_ERROR("Not compiled with GPU support"); 23 | #endif 24 | } 25 | 26 | at::Tensor result = nms_cpu(dets, scores, threshold); 27 | return result; 28 | } 29 | -------------------------------------------------------------------------------- /strix/misc/configs/fcos/fcos_R_50_FPN_1x_center_giou.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "pretrain_models/R-50.pkl" 4 | RPN_ONLY: True 5 | FCOS_ON: True 6 | BACKBONE: 7 | CONV_BODY: "R-50-FPN-RETINANET" 8 | RESNETS: 9 | BACKBONE_OUT_CHANNELS: 256 10 | RETINANET: 11 | USE_C5: False # FCOS uses P5 instead of C5 12 | FCOS: 13 | CENTER_SAMPLE: True 14 | POS_RADIUS: 1.5 15 | LOC_LOSS_TYPE: "giou" 16 | DATASETS: 17 | TRAIN: ("coco_2017_train", ) 18 | TEST: ("coco_2017_val", ) 19 | INPUT: 20 | MIN_SIZE_TRAIN: (800,) 21 | MAX_SIZE_TRAIN: 1333 22 | MIN_SIZE_TEST: 800 23 | MAX_SIZE_TEST: 1333 24 | DATALOADER: 25 | SIZE_DIVISIBILITY: 32 26 | SOLVER: 27 | BASE_LR: 0.01 28 | WEIGHT_DECAY: 0.0001 29 | STEPS: (60000, 80000) 30 | MAX_ITER: 90000 31 | IMS_PER_BATCH: 16 32 | WARMUP_METHOD: "constant" 33 | -------------------------------------------------------------------------------- /strix/misc/configs/quick_schedules/rpn_R_50_FPN_quick.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | RPN_ONLY: True 5 | BACKBONE: 6 | CONV_BODY: "R-50-FPN" 7 | RESNETS: 8 | BACKBONE_OUT_CHANNELS: 256 9 | RPN: 10 | USE_FPN: True 11 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 2000 14 | FPN_POST_NMS_TOP_N_TEST: 2000 15 | DATASETS: 16 | TRAIN: ("coco_2014_minival",) 17 | TEST: ("coco_2014_minival",) 18 | INPUT: 19 | MIN_SIZE_TRAIN: (600,) 20 | MAX_SIZE_TRAIN: 1000 21 | MIN_SIZE_TEST: 800 22 | MAX_SIZE_TEST: 1000 23 | DATALOADER: 24 | SIZE_DIVISIBILITY: 32 25 | SOLVER: 26 | BASE_LR: 0.005 27 | WEIGHT_DECAY: 0.0001 28 | STEPS: (1500,) 29 | MAX_ITER: 2000 30 | IMS_PER_BATCH: 4 31 | TEST: 32 | IMS_PER_BATCH: 2 33 | -------------------------------------------------------------------------------- /strix/misc/configs/gn_baselines/README.md: -------------------------------------------------------------------------------- 1 | ### Group Normalization 2 | 1 [Group Normalization](https://arxiv.org/abs/1803.08494) 3 | 2 [Rethinking ImageNet Pre-training](https://arxiv.org/abs/1811.08883) 4 | 3 [official code](https://github.com/facebookresearch/Detectron/blob/master/projects/GN/README.md) 5 | 6 | 7 | ### Performance 8 | | case | Type | lr schd | im/gpu | bbox AP | mask AP | 9 | |----------------------------|:------------:|:---------:|:-------:|:-------:|:-------:| 10 | | R-50-FPN, GN (paper) | finetune | 2x | 2 | 40.3 | 35.7 | 11 | | R-50-FPN, GN (implement) | finetune | 2x | 2 | 40.2 | 36.0 | 12 | | R-50-FPN, GN (paper) | from scratch | 3x | 2 | 39.5 | 35.2 | 13 | | R-50-FPN, GN (implement) | from scratch | 3x | 2 | 38.9 | 35.1 | 14 | -------------------------------------------------------------------------------- /strix/models/rcnn/data/datasets/concat_dataset.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import bisect 3 | 4 | from torch.utils.data.dataset import ConcatDataset as _ConcatDataset 5 | 6 | 7 | class ConcatDataset(_ConcatDataset): 8 | """ 9 | Same as torch.utils.data.dataset.ConcatDataset, but exposes an extra 10 | method for querying the sizes of the image 11 | """ 12 | 13 | def get_idxs(self, idx): 14 | dataset_idx = bisect.bisect_right(self.cumulative_sizes, idx) 15 | if dataset_idx == 0: 16 | sample_idx = idx 17 | else: 18 | sample_idx = idx - self.cumulative_sizes[dataset_idx - 1] 19 | return dataset_idx, sample_idx 20 | 21 | def get_img_info(self, idx): 22 | dataset_idx, sample_idx = self.get_idxs(idx) 23 | return self.datasets[dataset_idx].get_img_info(sample_idx) 24 | -------------------------------------------------------------------------------- /strix/models/rcnn/layers/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import torch 3 | 4 | from .batch_norm import FrozenBatchNorm2d 5 | from .misc import Conv2d 6 | from .misc import ConvTranspose2d 7 | from .misc import BatchNorm2d 8 | from .misc import interpolate 9 | from .nms import nms 10 | from .roi_align import ROIAlign 11 | from .roi_align import roi_align 12 | from .roi_pool import ROIPool 13 | from .roi_pool import roi_pool 14 | from .smooth_l1_loss import smooth_l1_loss 15 | from .sigmoid_focal_loss import SigmoidFocalLoss 16 | from .iou_loss import IOULoss 17 | from .scale import Scale 18 | 19 | 20 | __all__ = ["nms", "roi_align", "ROIAlign", "roi_pool", "ROIPool", 21 | "smooth_l1_loss", "Conv2d", "ConvTranspose2d", "interpolate", 22 | "BatchNorm2d", "FrozenBatchNorm2d", "SigmoidFocalLoss", "IOULoss", 23 | "Scale"] 24 | 25 | -------------------------------------------------------------------------------- /strix/models/rcnn/utils/logger.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import logging 3 | import os 4 | import sys 5 | 6 | 7 | def setup_logger(name, save_dir, distributed_rank, filename="log.txt"): 8 | logger = logging.getLogger(name) 9 | logger.setLevel(logging.DEBUG) 10 | # don't log results for the non-master process 11 | if distributed_rank > 0: 12 | return logger 13 | ch = logging.StreamHandler(stream=sys.stdout) 14 | ch.setLevel(logging.DEBUG) 15 | formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s") 16 | ch.setFormatter(formatter) 17 | logger.addHandler(ch) 18 | 19 | if save_dir: 20 | fh = logging.FileHandler(os.path.join(save_dir, filename)) 21 | fh.setLevel(logging.DEBUG) 22 | fh.setFormatter(formatter) 23 | logger.addHandler(fh) 24 | 25 | return logger 26 | -------------------------------------------------------------------------------- /strix/misc/configs/fcos/fcos_bn_bs16_MNV2_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "https://cloudstor.aarnet.edu.au/plus/s/xtixKaxLWmbcyf7/download#mobilenet_v2-ecbe2b5.pth" 4 | RPN_ONLY: True 5 | FCOS_ON: True 6 | BACKBONE: 7 | CONV_BODY: "MNV2-FPN-RETINANET" 8 | FREEZE_CONV_BODY_AT: 0 9 | RESNETS: 10 | BACKBONE_OUT_CHANNELS: 256 11 | RETINANET: 12 | USE_C5: False # FCOS uses P5 instead of C5 13 | USE_SYNCBN: False 14 | DATASETS: 15 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 16 | TEST: ("coco_2014_minival",) 17 | INPUT: 18 | MIN_SIZE_TRAIN: (800,) 19 | MAX_SIZE_TRAIN: 1333 20 | MIN_SIZE_TEST: 800 21 | MAX_SIZE_TEST: 1333 22 | DATALOADER: 23 | SIZE_DIVISIBILITY: 32 24 | SOLVER: 25 | BASE_LR: 0.01 26 | WEIGHT_DECAY: 0.0001 27 | STEPS: (60000, 80000) 28 | MAX_ITER: 90000 29 | IMS_PER_BATCH: 16 30 | WARMUP_METHOD: "constant" 31 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /strix/misc/configs/fcos/fcos_X_101_32x8d_FPN_2x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/FAIR/20171220/X-101-32x8d" 4 | RPN_ONLY: True 5 | FCOS_ON: True 6 | BACKBONE: 7 | CONV_BODY: "R-101-FPN-RETINANET" 8 | RESNETS: 9 | STRIDE_IN_1X1: False 10 | BACKBONE_OUT_CHANNELS: 256 11 | NUM_GROUPS: 32 12 | WIDTH_PER_GROUP: 8 13 | RETINANET: 14 | USE_C5: False # FCOS uses P5 instead of C5 15 | DATASETS: 16 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 17 | TEST: ("coco_2014_minival",) 18 | INPUT: 19 | MIN_SIZE_RANGE_TRAIN: (640, 800) 20 | MAX_SIZE_TRAIN: 1333 21 | MIN_SIZE_TEST: 800 22 | MAX_SIZE_TEST: 1333 23 | DATALOADER: 24 | SIZE_DIVISIBILITY: 32 25 | SOLVER: 26 | BASE_LR: 0.01 27 | WEIGHT_DECAY: 0.0001 28 | STEPS: (120000, 160000) 29 | MAX_ITER: 180000 30 | IMS_PER_BATCH: 16 31 | WARMUP_METHOD: "constant" 32 | -------------------------------------------------------------------------------- /strix/misc/configs/fcos/fcos_X_101_64x4d_FPN_2x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/FAIR/20171220/X-101-64x4d" 4 | RPN_ONLY: True 5 | FCOS_ON: True 6 | BACKBONE: 7 | CONV_BODY: "R-101-FPN-RETINANET" 8 | RESNETS: 9 | STRIDE_IN_1X1: False 10 | BACKBONE_OUT_CHANNELS: 256 11 | NUM_GROUPS: 64 12 | WIDTH_PER_GROUP: 4 13 | RETINANET: 14 | USE_C5: False # FCOS uses P5 instead of C5 15 | DATASETS: 16 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 17 | TEST: ("coco_2014_minival",) 18 | INPUT: 19 | MIN_SIZE_RANGE_TRAIN: (640, 800) 20 | MAX_SIZE_TRAIN: 1333 21 | MIN_SIZE_TEST: 800 22 | MAX_SIZE_TEST: 1333 23 | DATALOADER: 24 | SIZE_DIVISIBILITY: 32 25 | SOLVER: 26 | BASE_LR: 0.01 27 | WEIGHT_DECAY: 0.0001 28 | STEPS: (120000, 160000) 29 | MAX_ITER: 180000 30 | IMS_PER_BATCH: 16 31 | WARMUP_METHOD: "constant" 32 | -------------------------------------------------------------------------------- /strix/misc/configs/fcos/fcos_syncbn_bs32_MNV2_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "https://cloudstor.aarnet.edu.au/plus/s/xtixKaxLWmbcyf7/download#mobilenet_v2-ecbe2b5.pth" 4 | RPN_ONLY: True 5 | FCOS_ON: True 6 | BACKBONE: 7 | CONV_BODY: "MNV2-FPN-RETINANET" 8 | FREEZE_CONV_BODY_AT: 0 9 | RESNETS: 10 | BACKBONE_OUT_CHANNELS: 256 11 | RETINANET: 12 | USE_C5: False # FCOS uses P5 instead of C5 13 | USE_SYNCBN: True 14 | DATASETS: 15 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 16 | TEST: ("coco_2014_minival",) 17 | INPUT: 18 | MIN_SIZE_TRAIN: (800,) 19 | MAX_SIZE_TRAIN: 1333 20 | MIN_SIZE_TEST: 800 21 | MAX_SIZE_TEST: 1333 22 | DATALOADER: 23 | SIZE_DIVISIBILITY: 32 24 | SOLVER: 25 | BASE_LR: 0.01 26 | WEIGHT_DECAY: 0.0001 27 | STEPS: (60000, 80000) 28 | MAX_ITER: 90000 29 | IMS_PER_BATCH: 32 30 | WARMUP_METHOD: "constant" 31 | -------------------------------------------------------------------------------- /strix/models/rcnn/layers/batch_norm.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import torch 3 | from torch import nn 4 | 5 | 6 | class FrozenBatchNorm2d(nn.Module): 7 | """ 8 | BatchNorm2d where the batch statistics and the affine parameters 9 | are fixed 10 | """ 11 | 12 | def __init__(self, n): 13 | super(FrozenBatchNorm2d, self).__init__() 14 | self.register_buffer("weight", torch.ones(n)) 15 | self.register_buffer("bias", torch.zeros(n)) 16 | self.register_buffer("running_mean", torch.zeros(n)) 17 | self.register_buffer("running_var", torch.ones(n)) 18 | 19 | def forward(self, x): 20 | scale = self.weight * self.running_var.rsqrt() 21 | bias = self.bias - self.running_mean * scale 22 | scale = scale.reshape(1, -1, 1, 1) 23 | bias = bias.reshape(1, -1, 1, 1) 24 | return x * scale + bias 25 | -------------------------------------------------------------------------------- /strix/tests/test_click_numeric_choice.py: -------------------------------------------------------------------------------- 1 | import click 2 | import pytest 3 | from strix.utilities.click_callbacks import NumericChoice as Choice 4 | 5 | 6 | def test_choices_list_in_prompt(runner, monkeypatch): 7 | @click.command() 8 | @click.option( 9 | "-g", type=Choice(["none", "day", "week", "month"]), prompt=True 10 | ) 11 | def cli_with_choices(g): 12 | pass 13 | 14 | @click.command() 15 | @click.option( 16 | "-g", type=Choice(["none", "day", "week", "month"]), prompt=True, show_choices=False 17 | ) 18 | def cli_without_choices(g): 19 | pass 20 | 21 | result = runner.invoke(cli_with_choices, [], input="none") 22 | assert "(1: none, 2: day, 3: week, 4: month)" in result.output 23 | 24 | result = runner.invoke(cli_without_choices, [], input="none") 25 | print(result.output) 26 | assert "(1: none, 2: day, 3: week, 4: month)" not in result.output -------------------------------------------------------------------------------- /strix/misc/configs/fcos/fcos_syncbn_bs32_c128_MNV2_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "https://cloudstor.aarnet.edu.au/plus/s/xtixKaxLWmbcyf7/download#mobilenet_v2-ecbe2b5.pth" 4 | RPN_ONLY: True 5 | FCOS_ON: True 6 | BACKBONE: 7 | CONV_BODY: "MNV2-FPN-RETINANET" 8 | FREEZE_CONV_BODY_AT: 0 9 | RESNETS: 10 | BACKBONE_OUT_CHANNELS: 128 11 | RETINANET: 12 | USE_C5: False # FCOS uses P5 instead of C5 13 | USE_SYNCBN: True 14 | DATASETS: 15 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 16 | TEST: ("coco_2014_minival",) 17 | INPUT: 18 | MIN_SIZE_TRAIN: (800,) 19 | MAX_SIZE_TRAIN: 1333 20 | MIN_SIZE_TEST: 800 21 | MAX_SIZE_TEST: 1333 22 | DATALOADER: 23 | SIZE_DIVISIBILITY: 32 24 | SOLVER: 25 | BASE_LR: 0.01 26 | WEIGHT_DECAY: 0.0001 27 | STEPS: (60000, 80000) 28 | MAX_ITER: 90000 29 | IMS_PER_BATCH: 32 30 | WARMUP_METHOD: "constant" 31 | -------------------------------------------------------------------------------- /strix/misc/configs/fcos/fcos_syncbn_bs32_c128_ms_MNV2_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "https://cloudstor.aarnet.edu.au/plus/s/xtixKaxLWmbcyf7/download#mobilenet_v2-ecbe2b5.pth" 4 | RPN_ONLY: True 5 | FCOS_ON: True 6 | BACKBONE: 7 | CONV_BODY: "MNV2-FPN-RETINANET" 8 | FREEZE_CONV_BODY_AT: 0 9 | RESNETS: 10 | BACKBONE_OUT_CHANNELS: 128 11 | RETINANET: 12 | USE_C5: False # FCOS uses P5 instead of C5 13 | USE_SYNCBN: True 14 | DATASETS: 15 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 16 | TEST: ("coco_2014_minival",) 17 | INPUT: 18 | MIN_SIZE_RANGE_TRAIN: (640, 800) 19 | MAX_SIZE_TRAIN: 1333 20 | MIN_SIZE_TEST: 800 21 | MAX_SIZE_TEST: 1333 22 | DATALOADER: 23 | SIZE_DIVISIBILITY: 32 24 | SOLVER: 25 | BASE_LR: 0.01 26 | WEIGHT_DECAY: 0.0001 27 | STEPS: (60000, 80000) 28 | MAX_ITER: 90000 29 | IMS_PER_BATCH: 32 30 | WARMUP_METHOD: "constant" 31 | -------------------------------------------------------------------------------- /strix/misc/configs/fcos/fcos_syncbn_bs64_c128_ms_MNV2_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "https://cloudstor.aarnet.edu.au/plus/s/xtixKaxLWmbcyf7/download#mobilenet_v2-ecbe2b5.pth" 4 | RPN_ONLY: True 5 | FCOS_ON: True 6 | BACKBONE: 7 | CONV_BODY: "MNV2-FPN-RETINANET" 8 | FREEZE_CONV_BODY_AT: 0 9 | RESNETS: 10 | BACKBONE_OUT_CHANNELS: 128 11 | RETINANET: 12 | USE_C5: False # FCOS uses P5 instead of C5 13 | USE_SYNCBN: True 14 | DATASETS: 15 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 16 | TEST: ("coco_2014_minival",) 17 | INPUT: 18 | MIN_SIZE_RANGE_TRAIN: (640, 800) 19 | MAX_SIZE_TRAIN: 1333 20 | MIN_SIZE_TEST: 800 21 | MAX_SIZE_TEST: 1333 22 | DATALOADER: 23 | SIZE_DIVISIBILITY: 32 24 | SOLVER: 25 | BASE_LR: 0.01 26 | WEIGHT_DECAY: 0.0001 27 | STEPS: (60000, 80000) 28 | MAX_ITER: 90000 29 | IMS_PER_BATCH: 64 30 | WARMUP_METHOD: "constant" 31 | -------------------------------------------------------------------------------- /strix/configures/__init__.py: -------------------------------------------------------------------------------- 1 | from configparser import ConfigParser 2 | from pathlib import Path 3 | 4 | from strix.configures import config as cfg 5 | from monai_ex.engines.utils import CustomKeys 6 | from monai_ex.engines.utils import get_keys_dict as keys_dict 7 | 8 | conf = ConfigParser() 9 | conf.optionxform = str 10 | fname = cfg.DEFAULT_STRIX_CONFIG['CONFIG_FNAME'] 11 | cfg_file = Path(__file__).parent.joinpath(fname) 12 | 13 | 14 | if not cfg_file.is_file(): 15 | with cfg_file.open('w') as cfgfile: 16 | 17 | conf.add_section("STRIX_CONFIG") 18 | for k, v in cfg.DEFAULT_STRIX_CONFIG.items(): 19 | conf.set('STRIX_CONFIG', k.upper(), v) 20 | 21 | conf.add_section('CUSTOM_KEYS') 22 | for k, v in keys_dict(CustomKeys).items(): 23 | conf.set('CUSTOM_KEYS', k.upper(), v) 24 | 25 | conf.add_section("GUI_CONFIG") 26 | 27 | conf.write(cfgfile) 28 | 29 | cfg.init(add_path=True) 30 | -------------------------------------------------------------------------------- /strix/models/rcnn/utils/imports.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import torch 3 | 4 | if torch._six.PY3: 5 | import importlib 6 | import importlib.util 7 | import sys 8 | 9 | 10 | # from https://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa 11 | def import_file(module_name, file_path, make_importable=False): 12 | spec = importlib.util.spec_from_file_location(module_name, file_path) 13 | module = importlib.util.module_from_spec(spec) 14 | spec.loader.exec_module(module) 15 | if make_importable: 16 | sys.modules[module_name] = module 17 | return module 18 | else: 19 | import imp 20 | 21 | def import_file(module_name, file_path, make_importable=None): 22 | module = imp.load_source(module_name, file_path) 23 | return module 24 | -------------------------------------------------------------------------------- /install.md: -------------------------------------------------------------------------------- 1 | ## How to install? 2 | --- 3 | ### 1. Create a new virtual env. 4 | 5 | ``` 6 | conda create -n strix python=3.8 7 | ``` 8 | 9 | ### 2. Install pytorch (here show example of installing pytorch1.9) 10 | ``` 11 | conda activate strix 12 | conda install pytorch==1.9.1 torchvision==0.10.0 cudatoolkit=11.3 -c conda-forge 13 | ``` 14 | 15 | ### 3. If you want to develop Strix, you can download Strix project. 16 | ``` 17 | git clone https://github.com/Project-Strix/Strix.git 18 | pip install -e ./Strix/MONAI_ex 19 | pip install -e ./Strix 20 | ``` 21 | ### 4. If you just want to use Strix, you can directly install Strix by: 22 | ``` 23 | pip install git+https://github.com/Project-Strix/MONAI_EX.git 24 | pip install git+https://github.com/Project-Strix/Strix.git 25 | ``` 26 | 27 | _Notice that Strix is only tested on **Linux** only, not on Windows. If you find any problem with the deployment on Windows, please submit an [issue](https://github.com/Project-Strix/Strix/issues)._ -------------------------------------------------------------------------------- /strix/misc/configs/e2e_faster_rcnn_R_101_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-101" 4 | BACKBONE: 5 | CONV_BODY: "R-101-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | RPN: 9 | USE_FPN: True 10 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 11 | PRE_NMS_TOP_N_TRAIN: 2000 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 1000 14 | FPN_POST_NMS_TOP_N_TEST: 1000 15 | ROI_HEADS: 16 | USE_FPN: True 17 | ROI_BOX_HEAD: 18 | POOLER_RESOLUTION: 7 19 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 20 | POOLER_SAMPLING_RATIO: 2 21 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 22 | PREDICTOR: "FPNPredictor" 23 | DATASETS: 24 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 25 | TEST: ("coco_2014_minival",) 26 | DATALOADER: 27 | SIZE_DIVISIBILITY: 32 28 | SOLVER: 29 | BASE_LR: 0.02 30 | WEIGHT_DECAY: 0.0001 31 | STEPS: (60000, 80000) 32 | MAX_ITER: 90000 33 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_faster_rcnn_R_50_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | BACKBONE: 5 | CONV_BODY: "R-50-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | RPN: 9 | USE_FPN: True 10 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 11 | PRE_NMS_TOP_N_TRAIN: 2000 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 1000 14 | FPN_POST_NMS_TOP_N_TEST: 1000 15 | ROI_HEADS: 16 | USE_FPN: True 17 | ROI_BOX_HEAD: 18 | POOLER_RESOLUTION: 7 19 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 20 | POOLER_SAMPLING_RATIO: 2 21 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 22 | PREDICTOR: "FPNPredictor" 23 | DATASETS: 24 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 25 | TEST: ("coco_2014_minival",) 26 | DATALOADER: 27 | SIZE_DIVISIBILITY: 32 28 | SOLVER: 29 | BASE_LR: 0.02 30 | WEIGHT_DECAY: 0.0001 31 | STEPS: (60000, 80000) 32 | MAX_ITER: 90000 33 | -------------------------------------------------------------------------------- /strix/models/cnn/engines/gan_engines.py: -------------------------------------------------------------------------------- 1 | from strix.models.cnn.engines import TRAIN_ENGINES, TEST_ENGINES, ENSEMBLE_TEST_ENGINES 2 | from monai_ex.engines import GanTrainer 3 | 4 | @TRAIN_ENGINES.register('gan') 5 | def build_gan_engine(**kwargs): 6 | opts = kwargs['opts'] 7 | train_loader = kwargs['train_loader'] 8 | test_loader = kwargs['test_loader'] 9 | net = kwargs['net'] 10 | loss = kwargs['loss'] 11 | optim = kwargs['optim'] 12 | lr_scheduler = kwargs['lr_scheduler'] 13 | writer = kwargs['writer'] 14 | valid_interval = kwargs['valid_interval'] 15 | device = kwargs['device'] 16 | model_dir = kwargs['model_dir'] 17 | logger_name = kwargs.get('logger_name', None) 18 | 19 | GanTrainer( 20 | device=device, 21 | max_epochs=opts.n_epoch, 22 | train_data_loader=train_loader, 23 | g_network=, 24 | g_optimizer=, 25 | g_loss_function=, 26 | d_network=, 27 | d_optimizer=, 28 | d_loss_function=, 29 | epoch_length=int(opts.n_epoch_len), 30 | ) -------------------------------------------------------------------------------- /strix/misc/configs/cityscapes/e2e_faster_rcnn_R_50_FPN_1x_cocostyle.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | BACKBONE: 5 | CONV_BODY: "R-50-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | RPN: 9 | USE_FPN: True 10 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 11 | PRE_NMS_TOP_N_TRAIN: 2000 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 1000 14 | FPN_POST_NMS_TOP_N_TEST: 1000 15 | ROI_HEADS: 16 | USE_FPN: True 17 | ROI_BOX_HEAD: 18 | POOLER_RESOLUTION: 7 19 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 20 | POOLER_SAMPLING_RATIO: 2 21 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 22 | PREDICTOR: "FPNPredictor" 23 | NUM_CLASSES: 9 24 | DATASETS: 25 | TRAIN: ("cityscapes_fine_instanceonly_seg_train_cocostyle",) 26 | TEST: ("cityscapes_fine_instanceonly_seg_val_cocostyle",) 27 | DATALOADER: 28 | SIZE_DIVISIBILITY: 32 29 | SOLVER: 30 | BASE_LR: 0.01 31 | WEIGHT_DECAY: 0.0001 32 | STEPS: (18000,) 33 | MAX_ITER: 24000 34 | -------------------------------------------------------------------------------- /strix/models/cnn/nets/multihead_net.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | from typing import Union 5 | 6 | 7 | class MultiOutputNet(nn.Module): 8 | def __init__( 9 | self, 10 | backbone: Union[nn.Module, nn.Sequential], 11 | multiheads: nn.ModuleList, 12 | mode='independent' 13 | ): 14 | super().__init__() 15 | self.backbone = backbone 16 | self.multiheads = multiheads 17 | self.mode = mode 18 | modes = ['continous', 'independent'] 19 | if self.mode not in modes: 20 | raise ValueError(f'Mode must be {modes}, but got {self.mode}') 21 | 22 | def forward(self, x): 23 | x = self.backbone(x) 24 | if self.mode == 'independent': 25 | return tuple(head(x) for head in self.multiheads) 26 | elif self.mode == 'continous': 27 | outputs = [] 28 | for i, head in enumerate(self.multiheads): 29 | for h in self.multiheads[:i]: 30 | x = h(x) 31 | outputs.append(head(x)) 32 | return tuple(outputs) 33 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_faster_rcnn_X_101_32x8d_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/FAIR/20171220/X-101-32x8d" 4 | BACKBONE: 5 | CONV_BODY: "R-101-FPN" 6 | RPN: 7 | USE_FPN: True 8 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 9 | PRE_NMS_TOP_N_TRAIN: 2000 10 | PRE_NMS_TOP_N_TEST: 1000 11 | POST_NMS_TOP_N_TEST: 1000 12 | FPN_POST_NMS_TOP_N_TEST: 1000 13 | ROI_HEADS: 14 | USE_FPN: True 15 | ROI_BOX_HEAD: 16 | POOLER_RESOLUTION: 7 17 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 18 | POOLER_SAMPLING_RATIO: 2 19 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 20 | PREDICTOR: "FPNPredictor" 21 | RESNETS: 22 | BACKBONE_OUT_CHANNELS: 256 23 | STRIDE_IN_1X1: False 24 | NUM_GROUPS: 32 25 | WIDTH_PER_GROUP: 8 26 | DATASETS: 27 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 28 | TEST: ("coco_2014_minival",) 29 | DATALOADER: 30 | SIZE_DIVISIBILITY: 32 31 | SOLVER: 32 | BASE_LR: 0.01 33 | WEIGHT_DECAY: 0.0001 34 | STEPS: (120000, 160000) 35 | MAX_ITER: 180000 36 | IMS_PER_BATCH: 8 37 | -------------------------------------------------------------------------------- /strix/models/rcnn/solver/build.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import torch 3 | 4 | from .lr_scheduler import WarmupMultiStepLR 5 | 6 | 7 | def make_optimizer(cfg, model): 8 | params = [] 9 | for key, value in model.named_parameters(): 10 | if not value.requires_grad: 11 | continue 12 | lr = cfg.SOLVER.BASE_LR 13 | weight_decay = cfg.SOLVER.WEIGHT_DECAY 14 | if "bias" in key: 15 | lr = cfg.SOLVER.BASE_LR * cfg.SOLVER.BIAS_LR_FACTOR 16 | weight_decay = cfg.SOLVER.WEIGHT_DECAY_BIAS 17 | params += [{"params": [value], "lr": lr, "weight_decay": weight_decay}] 18 | 19 | optimizer = torch.optim.SGD(params, lr, momentum=cfg.SOLVER.MOMENTUM) 20 | return optimizer 21 | 22 | 23 | def make_lr_scheduler(cfg, optimizer): 24 | return WarmupMultiStepLR( 25 | optimizer, 26 | cfg.SOLVER.STEPS, 27 | cfg.SOLVER.GAMMA, 28 | warmup_factor=cfg.SOLVER.WARMUP_FACTOR, 29 | warmup_iters=cfg.SOLVER.WARMUP_ITERS, 30 | warmup_method=cfg.SOLVER.WARMUP_METHOD, 31 | ) 32 | -------------------------------------------------------------------------------- /strix/models/rcnn/data/datasets/list_dataset.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | """ 3 | Simple dataset class that wraps a list of path names 4 | """ 5 | 6 | from PIL import Image 7 | 8 | from strix.models.rcnn.structures.bounding_box import BoxList 9 | 10 | 11 | class ListDataset(object): 12 | def __init__(self, image_lists, transforms=None): 13 | self.image_lists = image_lists 14 | self.transforms = transforms 15 | 16 | def __getitem__(self, item): 17 | img = Image.open(self.image_lists[item]).convert("RGB") 18 | 19 | # dummy target 20 | w, h = img.size 21 | target = BoxList([[0, 0, w, h]], img.size, mode="xyxy") 22 | 23 | if self.transforms is not None: 24 | img, target = self.transforms(img, target) 25 | 26 | return img, target 27 | 28 | def __len__(self): 29 | return len(self.image_lists) 30 | 31 | def get_img_info(self, item): 32 | """ 33 | Return the image dimensions for the image, without 34 | loading and pre-processing it 35 | """ 36 | pass 37 | -------------------------------------------------------------------------------- /strix/models/rcnn/data/datasets/evaluation/__init__.py: -------------------------------------------------------------------------------- 1 | from strix.models.rcnn.data import datasets 2 | 3 | from .coco import coco_evaluation 4 | from .voc import voc_evaluation 5 | 6 | 7 | def evaluate(dataset, predictions, output_folder, **kwargs): 8 | """evaluate dataset using different methods based on dataset type. 9 | Args: 10 | dataset: Dataset object 11 | predictions(list[BoxList]): each item in the list represents the 12 | prediction results for one image. 13 | output_folder: output folder, to save evaluation files or results. 14 | **kwargs: other args. 15 | Returns: 16 | evaluation result 17 | """ 18 | args = dict( 19 | dataset=dataset, predictions=predictions, output_folder=output_folder, **kwargs 20 | ) 21 | if isinstance(dataset, datasets.COCODataset): 22 | return coco_evaluation(**args) 23 | elif isinstance(dataset, datasets.PascalVOCDataset): 24 | return voc_evaluation(**args) 25 | else: 26 | dataset_name = dataset.__class__.__name__ 27 | raise NotImplementedError("Unsupported dataset type {}.".format(dataset_name)) 28 | -------------------------------------------------------------------------------- /strix/misc/configs/quick_schedules/e2e_faster_rcnn_R_50_FPN_quick.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | BACKBONE: 5 | CONV_BODY: "R-50-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | RPN: 9 | USE_FPN: True 10 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 11 | PRE_NMS_TOP_N_TRAIN: 2000 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 1000 14 | FPN_POST_NMS_TOP_N_TEST: 1000 15 | ROI_HEADS: 16 | USE_FPN: True 17 | BATCH_SIZE_PER_IMAGE: 256 18 | ROI_BOX_HEAD: 19 | POOLER_RESOLUTION: 7 20 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 21 | POOLER_SAMPLING_RATIO: 2 22 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 23 | PREDICTOR: "FPNPredictor" 24 | DATASETS: 25 | TRAIN: ("coco_2014_minival",) 26 | TEST: ("coco_2014_minival",) 27 | INPUT: 28 | MIN_SIZE_TRAIN: (600,) 29 | MAX_SIZE_TRAIN: 1000 30 | MIN_SIZE_TEST: 800 31 | MAX_SIZE_TEST: 1000 32 | DATALOADER: 33 | SIZE_DIVISIBILITY: 32 34 | SOLVER: 35 | BASE_LR: 0.005 36 | WEIGHT_DECAY: 0.0001 37 | STEPS: (1500,) 38 | MAX_ITER: 2000 39 | IMS_PER_BATCH: 4 40 | TEST: 41 | IMS_PER_BATCH: 2 42 | -------------------------------------------------------------------------------- /strix/data_io/__init__.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from strix.utilities.imports import import_file 3 | from strix.configures import config as cfg 4 | from strix.data_io.base_dataset.classification_dataset import * 5 | from strix.data_io.base_dataset.selflearning_dataset import * 6 | from strix.data_io.base_dataset.segmentation_dataset import * 7 | from strix.data_io.base_dataset.siamese_dataset import * 8 | 9 | from strix.data_io.dataio import ( 10 | CLASSIFICATION_DATASETS, 11 | SEGMENTATION_DATASETS, 12 | SIAMESE_DATASETS, 13 | SELFLEARNING_DATASETS, 14 | MULTITASK_DATASETS, 15 | DATASET_MAPPING, 16 | ) 17 | from strix.data_io.generate_dataset import register_dataset_from_cfg 18 | 19 | internal_dataset_dir = Path(__file__).parent.parent.joinpath("datasets") 20 | external_dataset_dir = Path(cfg.get_strix_cfg('EXTERNAL_DATASET_DIR')) 21 | 22 | dataset_dirs = [internal_dataset_dir, external_dataset_dir] 23 | 24 | for data_dir in dataset_dirs: 25 | if data_dir.is_dir(): 26 | for f in data_dir.glob("*.py"): 27 | # print('Import module from file:', str(f)) 28 | import_file(f.stem, str(f)) 29 | for j in data_dir.glob("*.yaml"): 30 | register_dataset_from_cfg(j) 31 | -------------------------------------------------------------------------------- /strix/models/rcnn/csrc/SigmoidFocalLoss.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "cpu/vision.h" 4 | 5 | #ifdef WITH_CUDA 6 | #include "cuda/vision.h" 7 | #endif 8 | 9 | // Interface for Python 10 | at::Tensor SigmoidFocalLoss_forward( 11 | const at::Tensor& logits, 12 | const at::Tensor& targets, 13 | const int num_classes, 14 | const float gamma, 15 | const float alpha) { 16 | if (logits.type().is_cuda()) { 17 | #ifdef WITH_CUDA 18 | return SigmoidFocalLoss_forward_cuda(logits, targets, num_classes, gamma, alpha); 19 | #else 20 | AT_ERROR("Not compiled with GPU support"); 21 | #endif 22 | } 23 | AT_ERROR("Not implemented on the CPU"); 24 | } 25 | 26 | at::Tensor SigmoidFocalLoss_backward( 27 | const at::Tensor& logits, 28 | const at::Tensor& targets, 29 | const at::Tensor& d_losses, 30 | const int num_classes, 31 | const float gamma, 32 | const float alpha) { 33 | if (logits.type().is_cuda()) { 34 | #ifdef WITH_CUDA 35 | return SigmoidFocalLoss_backward_cuda(logits, targets, d_losses, num_classes, gamma, alpha); 36 | #else 37 | AT_ERROR("Not compiled with GPU support"); 38 | #endif 39 | } 40 | AT_ERROR("Not implemented on the CPU"); 41 | } 42 | -------------------------------------------------------------------------------- /strix/tests/test_basicclassificationdataset.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from monai.data import Dataset 3 | from strix.data_io import BasicClassificationDataset 4 | 5 | filelist = [ 6 | { 7 | "image": "/homes/clwang/Data/kits19_seg/data/case_00000/segmentation.nii.gz", 8 | "mask": "/homes/clwang/Data/kits19_seg/data/case_00000/segmentation.nii.gz", 9 | "label": 1, 10 | }, 11 | { 12 | "image": "/homes/clwang/Data/kits19_seg/data/case_00000/segmentation.nii.gz", 13 | "mask": "/homes/clwang/Data/kits19_seg/data/case_00000/segmentation.nii.gz", 14 | "label": 1, 15 | } 16 | ] 17 | 18 | 19 | def test_basic_clf_dataset(): 20 | data = BasicClassificationDataset( 21 | files_list=filelist, 22 | loader=lambda x: x, 23 | channeler=None, 24 | orienter=None, 25 | spacer=None, 26 | rescaler=None, 27 | resizer=None, 28 | cropper=None, 29 | caster=None, 30 | to_tensor=None, 31 | is_supervised=True, 32 | dataset_type=Dataset, 33 | dataset_kwargs={}, 34 | check_data=True, 35 | verbose=False 36 | ) 37 | 38 | assert len(data) == 2 39 | assert list(data[0].keys()) == ['image', 'mask', 'label'] -------------------------------------------------------------------------------- /strix/misc/configs/e2e_faster_rcnn_fbnet.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | BACKBONE: 4 | CONV_BODY: FBNet 5 | FBNET: 6 | ARCH: "default" 7 | BN_TYPE: "bn" 8 | WIDTH_DIVISOR: 8 9 | DW_CONV_SKIP_BN: True 10 | DW_CONV_SKIP_RELU: True 11 | RPN: 12 | ANCHOR_SIZES: (16, 32, 64, 128, 256) 13 | ANCHOR_STRIDE: (16, ) 14 | BATCH_SIZE_PER_IMAGE: 256 15 | PRE_NMS_TOP_N_TRAIN: 6000 16 | PRE_NMS_TOP_N_TEST: 6000 17 | POST_NMS_TOP_N_TRAIN: 2000 18 | POST_NMS_TOP_N_TEST: 100 19 | RPN_HEAD: FBNet.rpn_head 20 | ROI_HEADS: 21 | BATCH_SIZE_PER_IMAGE: 512 22 | ROI_BOX_HEAD: 23 | POOLER_RESOLUTION: 6 24 | FEATURE_EXTRACTOR: FBNet.roi_head 25 | NUM_CLASSES: 81 26 | DATASETS: 27 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 28 | TEST: ("coco_2014_minival",) 29 | SOLVER: 30 | BASE_LR: 0.06 31 | WARMUP_FACTOR: 0.1 32 | WEIGHT_DECAY: 0.0001 33 | STEPS: (60000, 80000) 34 | MAX_ITER: 90000 35 | IMS_PER_BATCH: 128 # for 8GPUs 36 | # TEST: 37 | # IMS_PER_BATCH: 8 38 | INPUT: 39 | MIN_SIZE_TRAIN: (320, ) 40 | MAX_SIZE_TRAIN: 640 41 | MIN_SIZE_TEST: 320 42 | MAX_SIZE_TEST: 640 43 | PIXEL_MEAN: [103.53, 116.28, 123.675] 44 | PIXEL_STD: [57.375, 57.12, 58.395] 45 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_faster_rcnn_fbnet_600.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | BACKBONE: 4 | CONV_BODY: FBNet 5 | FBNET: 6 | ARCH: "default" 7 | BN_TYPE: "bn" 8 | WIDTH_DIVISOR: 8 9 | DW_CONV_SKIP_BN: True 10 | DW_CONV_SKIP_RELU: True 11 | RPN: 12 | ANCHOR_SIZES: (32, 64, 128, 256, 512) 13 | ANCHOR_STRIDE: (16, ) 14 | BATCH_SIZE_PER_IMAGE: 256 15 | PRE_NMS_TOP_N_TRAIN: 6000 16 | PRE_NMS_TOP_N_TEST: 6000 17 | POST_NMS_TOP_N_TRAIN: 2000 18 | POST_NMS_TOP_N_TEST: 200 19 | RPN_HEAD: FBNet.rpn_head 20 | ROI_HEADS: 21 | BATCH_SIZE_PER_IMAGE: 256 22 | ROI_BOX_HEAD: 23 | POOLER_RESOLUTION: 6 24 | FEATURE_EXTRACTOR: FBNet.roi_head 25 | NUM_CLASSES: 81 26 | DATASETS: 27 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 28 | TEST: ("coco_2014_minival",) 29 | SOLVER: 30 | BASE_LR: 0.06 31 | WARMUP_FACTOR: 0.1 32 | WEIGHT_DECAY: 0.0001 33 | STEPS: (60000, 80000) 34 | MAX_ITER: 90000 35 | IMS_PER_BATCH: 128 # for 8GPUs 36 | # TEST: 37 | # IMS_PER_BATCH: 8 38 | INPUT: 39 | MIN_SIZE_TRAIN: (600, ) 40 | MAX_SIZE_TRAIN: 1000 41 | MIN_SIZE_TEST: 600 42 | MAX_SIZE_TEST: 1000 43 | PIXEL_MEAN: [103.53, 116.28, 123.675] 44 | PIXEL_STD: [57.375, 57.12, 58.395] 45 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_faster_rcnn_fbnet_chamv1a_600.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | BACKBONE: 4 | CONV_BODY: FBNet 5 | FBNET: 6 | ARCH: "cham_v1a" 7 | BN_TYPE: "bn" 8 | WIDTH_DIVISOR: 8 9 | DW_CONV_SKIP_BN: True 10 | DW_CONV_SKIP_RELU: True 11 | RPN: 12 | ANCHOR_SIZES: (32, 64, 128, 256, 512) 13 | ANCHOR_STRIDE: (16, ) 14 | BATCH_SIZE_PER_IMAGE: 256 15 | PRE_NMS_TOP_N_TRAIN: 6000 16 | PRE_NMS_TOP_N_TEST: 6000 17 | POST_NMS_TOP_N_TRAIN: 2000 18 | POST_NMS_TOP_N_TEST: 200 19 | RPN_HEAD: FBNet.rpn_head 20 | ROI_HEADS: 21 | BATCH_SIZE_PER_IMAGE: 128 22 | ROI_BOX_HEAD: 23 | POOLER_RESOLUTION: 6 24 | FEATURE_EXTRACTOR: FBNet.roi_head 25 | NUM_CLASSES: 81 26 | DATASETS: 27 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 28 | TEST: ("coco_2014_minival",) 29 | SOLVER: 30 | BASE_LR: 0.045 31 | WARMUP_FACTOR: 0.1 32 | WEIGHT_DECAY: 0.0001 33 | STEPS: (90000, 120000) 34 | MAX_ITER: 135000 35 | IMS_PER_BATCH: 96 # for 8GPUs 36 | # TEST: 37 | # IMS_PER_BATCH: 8 38 | INPUT: 39 | MIN_SIZE_TRAIN: (600, ) 40 | MAX_SIZE_TRAIN: 1000 41 | MIN_SIZE_TEST: 600 42 | MAX_SIZE_TEST: 1000 43 | PIXEL_MEAN: [103.53, 116.28, 123.675] 44 | PIXEL_STD: [57.375, 57.12, 58.395] 45 | -------------------------------------------------------------------------------- /strix/misc/configs/quick_schedules/e2e_faster_rcnn_X_101_32x8d_FPN_quick.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/FAIR/20171220/X-101-32x8d" 4 | BACKBONE: 5 | CONV_BODY: "R-101-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | STRIDE_IN_1X1: False 9 | NUM_GROUPS: 32 10 | WIDTH_PER_GROUP: 8 11 | RPN: 12 | USE_FPN: True 13 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 14 | PRE_NMS_TOP_N_TRAIN: 2000 15 | PRE_NMS_TOP_N_TEST: 1000 16 | POST_NMS_TOP_N_TEST: 1000 17 | FPN_POST_NMS_TOP_N_TEST: 1000 18 | ROI_HEADS: 19 | USE_FPN: True 20 | BATCH_SIZE_PER_IMAGE: 256 21 | ROI_BOX_HEAD: 22 | POOLER_RESOLUTION: 7 23 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 24 | POOLER_SAMPLING_RATIO: 2 25 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 26 | PREDICTOR: "FPNPredictor" 27 | DATASETS: 28 | TRAIN: ("coco_2014_minival",) 29 | TEST: ("coco_2014_minival",) 30 | INPUT: 31 | MIN_SIZE_TRAIN: (600,) 32 | MAX_SIZE_TRAIN: 1000 33 | MIN_SIZE_TEST: 800 34 | MAX_SIZE_TEST: 1000 35 | DATALOADER: 36 | SIZE_DIVISIBILITY: 32 37 | SOLVER: 38 | BASE_LR: 0.005 39 | WEIGHT_DECAY: 0.0001 40 | STEPS: (1500,) 41 | MAX_ITER: 2000 42 | IMS_PER_BATCH: 2 43 | TEST: 44 | IMS_PER_BATCH: 2 45 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_mask_rcnn_R_50_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | BACKBONE: 5 | CONV_BODY: "R-50-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | RPN: 9 | USE_FPN: True 10 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 11 | PRE_NMS_TOP_N_TRAIN: 2000 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 1000 14 | FPN_POST_NMS_TOP_N_TEST: 1000 15 | ROI_HEADS: 16 | USE_FPN: True 17 | ROI_BOX_HEAD: 18 | POOLER_RESOLUTION: 7 19 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 20 | POOLER_SAMPLING_RATIO: 2 21 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 22 | PREDICTOR: "FPNPredictor" 23 | ROI_MASK_HEAD: 24 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 25 | FEATURE_EXTRACTOR: "MaskRCNNFPNFeatureExtractor" 26 | PREDICTOR: "MaskRCNNC4Predictor" 27 | POOLER_RESOLUTION: 14 28 | POOLER_SAMPLING_RATIO: 2 29 | RESOLUTION: 28 30 | SHARE_BOX_FEATURE_EXTRACTOR: False 31 | MASK_ON: True 32 | DATASETS: 33 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 34 | TEST: ("coco_2014_minival",) 35 | DATALOADER: 36 | SIZE_DIVISIBILITY: 32 37 | SOLVER: 38 | BASE_LR: 0.02 39 | WEIGHT_DECAY: 0.0001 40 | STEPS: (60000, 80000) 41 | MAX_ITER: 90000 42 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_mask_rcnn_R_101_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-101" 4 | BACKBONE: 5 | CONV_BODY: "R-101-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | RPN: 9 | USE_FPN: True 10 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 11 | PRE_NMS_TOP_N_TRAIN: 2000 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 1000 14 | FPN_POST_NMS_TOP_N_TEST: 1000 15 | ROI_HEADS: 16 | USE_FPN: True 17 | ROI_BOX_HEAD: 18 | POOLER_RESOLUTION: 7 19 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 20 | POOLER_SAMPLING_RATIO: 2 21 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 22 | PREDICTOR: "FPNPredictor" 23 | ROI_MASK_HEAD: 24 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 25 | FEATURE_EXTRACTOR: "MaskRCNNFPNFeatureExtractor" 26 | PREDICTOR: "MaskRCNNC4Predictor" 27 | POOLER_RESOLUTION: 14 28 | POOLER_SAMPLING_RATIO: 2 29 | RESOLUTION: 28 30 | SHARE_BOX_FEATURE_EXTRACTOR: False 31 | MASK_ON: True 32 | DATASETS: 33 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 34 | TEST: ("coco_2014_minival",) 35 | DATALOADER: 36 | SIZE_DIVISIBILITY: 32 37 | SOLVER: 38 | BASE_LR: 0.02 39 | WEIGHT_DECAY: 0.0001 40 | STEPS: (60000, 80000) 41 | MAX_ITER: 90000 42 | -------------------------------------------------------------------------------- /strix/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import click 3 | 4 | import warnings 5 | 6 | warnings.filterwarnings("ignore") 7 | 8 | 9 | @click.group() 10 | def main(): 11 | """Main entry of this program. 12 | 13 | For training: 14 | python3 picc.py train --params 15 | 16 | For training from config file: 17 | python3 picc.py train_from_cfg --params 18 | """ 19 | # model = __init__(args) 20 | 21 | 22 | if __name__ == "__main__": 23 | assert sys.version_info >= (3, 6), "Python ver. >=3.6 is required!" 24 | 25 | from strix.main_entry import train 26 | from strix.main_entry import train_cfg 27 | from strix.main_entry import test_cfg 28 | from strix.main_entry import train_and_test 29 | from nni_search import nni_search 30 | from nni_search import train_nni 31 | from data_checker import check_data 32 | from interpreter import gradcam 33 | from tools import merge_roc_curves, summarize_data 34 | 35 | main.add_command(train) 36 | main.add_command(train_cfg) 37 | main.add_command(test_cfg) 38 | main.add_command(train_and_test) 39 | main.add_command(nni_search) 40 | main.add_command(train_nni) 41 | main.add_command(check_data) 42 | main.add_command(gradcam) 43 | main.add_command(merge_roc_curves) 44 | main.add_command(summarize_data) 45 | main() 46 | -------------------------------------------------------------------------------- /strix/misc/configs/pascal_voc/e2e_mask_rcnn_R_50_FPN_1x_cocostyle.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | BACKBONE: 5 | CONV_BODY: "R-50-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | RPN: 9 | USE_FPN: True 10 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 11 | PRE_NMS_TOP_N_TRAIN: 2000 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 1000 14 | FPN_POST_NMS_TOP_N_TEST: 1000 15 | ROI_HEADS: 16 | USE_FPN: True 17 | ROI_BOX_HEAD: 18 | POOLER_RESOLUTION: 7 19 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 20 | POOLER_SAMPLING_RATIO: 2 21 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 22 | PREDICTOR: "FPNPredictor" 23 | NUM_CLASSES: 21 24 | ROI_MASK_HEAD: 25 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 26 | FEATURE_EXTRACTOR: "MaskRCNNFPNFeatureExtractor" 27 | PREDICTOR: "MaskRCNNC4Predictor" 28 | POOLER_RESOLUTION: 14 29 | POOLER_SAMPLING_RATIO: 2 30 | RESOLUTION: 28 31 | SHARE_BOX_FEATURE_EXTRACTOR: False 32 | MASK_ON: True 33 | DATASETS: 34 | TRAIN: ("voc_2012_train_cocostyle",) 35 | TEST: ("voc_2012_val_cocostyle",) 36 | DATALOADER: 37 | SIZE_DIVISIBILITY: 32 38 | SOLVER: 39 | BASE_LR: 0.01 40 | WEIGHT_DECAY: 0.0001 41 | STEPS: (18000,) 42 | MAX_ITER: 24000 43 | -------------------------------------------------------------------------------- /strix/models/rcnn/data/samplers/iteration_based_batch_sampler.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from torch.utils.data.sampler import BatchSampler 3 | 4 | 5 | class IterationBasedBatchSampler(BatchSampler): 6 | """ 7 | Wraps a BatchSampler, resampling from it until 8 | a specified number of iterations have been sampled 9 | """ 10 | 11 | def __init__(self, batch_sampler, num_iterations, start_iter=0): 12 | self.batch_sampler = batch_sampler 13 | self.num_iterations = num_iterations 14 | self.start_iter = start_iter 15 | 16 | def __iter__(self): 17 | iteration = self.start_iter 18 | while iteration <= self.num_iterations: 19 | # if the underlying sampler has a set_epoch method, like 20 | # DistributedSampler, used for making each process see 21 | # a different split of the dataset, then set it 22 | if hasattr(self.batch_sampler.sampler, "set_epoch"): 23 | self.batch_sampler.sampler.set_epoch(iteration) 24 | for batch in self.batch_sampler: 25 | iteration += 1 26 | if iteration > self.num_iterations: 27 | break 28 | yield batch 29 | 30 | def __len__(self): 31 | return self.num_iterations 32 | -------------------------------------------------------------------------------- /strix/models/rcnn/utils/timer.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | 3 | 4 | import time 5 | import datetime 6 | 7 | 8 | class Timer(object): 9 | def __init__(self): 10 | self.reset() 11 | 12 | @property 13 | def average_time(self): 14 | return self.total_time / self.calls if self.calls > 0 else 0.0 15 | 16 | def tic(self): 17 | # using time.time instead of time.clock because time time.clock 18 | # does not normalize for multithreading 19 | self.start_time = time.time() 20 | 21 | def toc(self, average=True): 22 | self.add(time.time() - self.start_time) 23 | if average: 24 | return self.average_time 25 | else: 26 | return self.diff 27 | 28 | def add(self, time_diff): 29 | self.diff = time_diff 30 | self.total_time += self.diff 31 | self.calls += 1 32 | 33 | def reset(self): 34 | self.total_time = 0.0 35 | self.calls = 0 36 | self.start_time = 0.0 37 | self.diff = 0.0 38 | 39 | def avg_time_str(self): 40 | time_str = str(datetime.timedelta(seconds=self.average_time)) 41 | return time_str 42 | 43 | 44 | def get_time_str(time_diff): 45 | time_str = str(datetime.timedelta(seconds=time_diff)) 46 | return time_str 47 | -------------------------------------------------------------------------------- /strix/models/rcnn/layers/_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import glob 3 | import os.path 4 | 5 | import torch 6 | 7 | try: 8 | from torch.utils.cpp_extension import load as load_ext 9 | from torch.utils.cpp_extension import CUDA_HOME 10 | except ImportError: 11 | raise ImportError("The cpp layer extensions requires PyTorch 0.4 or higher") 12 | 13 | 14 | def _load_C_extensions(): 15 | this_dir = os.path.dirname(os.path.abspath(__file__)) 16 | this_dir = os.path.dirname(this_dir) 17 | this_dir = os.path.join(this_dir, "csrc") 18 | 19 | main_file = glob.glob(os.path.join(this_dir, "*.cpp")) 20 | source_cpu = glob.glob(os.path.join(this_dir, "cpu", "*.cpp")) 21 | source_cuda = glob.glob(os.path.join(this_dir, "cuda", "*.cu")) 22 | 23 | source = main_file + source_cpu 24 | 25 | extra_cflags = [] 26 | if torch.cuda.is_available() and CUDA_HOME is not None: 27 | source.extend(source_cuda) 28 | extra_cflags = ["-DWITH_CUDA"] 29 | source = [os.path.join(this_dir, s) for s in source] 30 | extra_include_paths = [this_dir] 31 | return load_ext( 32 | "torchvision", 33 | source, 34 | extra_cflags=extra_cflags, 35 | extra_include_paths=extra_include_paths, 36 | ) 37 | 38 | 39 | _C = _load_C_extensions() 40 | -------------------------------------------------------------------------------- /strix/models/rcnn/data/transforms/build.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from . import transforms as T 3 | 4 | 5 | def build_transforms(cfg, is_train=True): 6 | if is_train: 7 | if cfg.INPUT.MIN_SIZE_RANGE_TRAIN[0] == -1: 8 | min_size = cfg.INPUT.MIN_SIZE_TRAIN 9 | else: 10 | assert len(cfg.INPUT.MIN_SIZE_RANGE_TRAIN) == 2, \ 11 | "MIN_SIZE_RANGE_TRAIN must have two elements (lower bound, upper bound)" 12 | min_size = list(range( 13 | cfg.INPUT.MIN_SIZE_RANGE_TRAIN[0], 14 | cfg.INPUT.MIN_SIZE_RANGE_TRAIN[1] + 1 15 | )) 16 | max_size = cfg.INPUT.MAX_SIZE_TRAIN 17 | flip_prob = 0.5 # cfg.INPUT.FLIP_PROB_TRAIN 18 | else: 19 | min_size = cfg.INPUT.MIN_SIZE_TEST 20 | max_size = cfg.INPUT.MAX_SIZE_TEST 21 | flip_prob = 0 22 | 23 | to_bgr255 = cfg.INPUT.TO_BGR255 24 | normalize_transform = T.Normalize( 25 | mean=cfg.INPUT.PIXEL_MEAN, std=cfg.INPUT.PIXEL_STD, to_bgr255=to_bgr255 26 | ) 27 | 28 | transform = T.Compose( 29 | [ 30 | T.Resize(min_size, max_size), 31 | T.RandomHorizontalFlip(flip_prob), 32 | T.ToTensor(), 33 | normalize_transform, 34 | ] 35 | ) 36 | return transform 37 | -------------------------------------------------------------------------------- /strix/models/transformer/transformer_nets.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | 3 | import os 4 | import torch 5 | 6 | from strix.models import SEGMENTATION_ARCHI 7 | from monai_ex.networks.nets import UNETR 8 | 9 | 10 | @SEGMENTATION_ARCHI.register("2D", "UNETR") 11 | @SEGMENTATION_ARCHI.register("3D", "UNETR") 12 | def strix_unetr( 13 | spatial_dims: int, 14 | in_channels: int, 15 | out_channels: int, 16 | act: str, 17 | norm: str, 18 | n_depth: int, 19 | n_group: int, 20 | drop_out: float, 21 | is_prunable: bool, 22 | pretrained: bool, 23 | pretrained_model_path: str, 24 | **kwargs: Any 25 | ): 26 | image_sz = kwargs.get("image_size") 27 | pos_embed = kwargs.get("pos_embed", "perceptron") # conv 28 | num_heads = kwargs.get("num_heads", 12) 29 | feature_size = kwargs.get("feature_size", 16) 30 | if image_sz is None: 31 | raise ValueError("Please specify input image size!") 32 | 33 | return UNETR( 34 | spatial_dims=spatial_dims, 35 | in_channels=in_channels, 36 | out_channels=out_channels, 37 | img_size=image_sz, 38 | feature_size=int(feature_size), 39 | hidden_size=768, 40 | mlp_dim=3072, 41 | num_heads=int(num_heads), 42 | pos_embed=pos_embed, 43 | norm_name=norm, 44 | conv_block=True, 45 | res_block=True, 46 | ) 47 | -------------------------------------------------------------------------------- /strix/misc/configs/cityscapes/e2e_mask_rcnn_R_50_FPN_1x_cocostyle.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | BACKBONE: 5 | CONV_BODY: "R-50-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | RPN: 9 | USE_FPN: True 10 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 11 | PRE_NMS_TOP_N_TRAIN: 2000 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 1000 14 | FPN_POST_NMS_TOP_N_TEST: 1000 15 | ROI_HEADS: 16 | USE_FPN: True 17 | ROI_BOX_HEAD: 18 | POOLER_RESOLUTION: 7 19 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 20 | POOLER_SAMPLING_RATIO: 2 21 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 22 | PREDICTOR: "FPNPredictor" 23 | NUM_CLASSES: 9 24 | ROI_MASK_HEAD: 25 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 26 | FEATURE_EXTRACTOR: "MaskRCNNFPNFeatureExtractor" 27 | PREDICTOR: "MaskRCNNC4Predictor" 28 | POOLER_RESOLUTION: 14 29 | POOLER_SAMPLING_RATIO: 2 30 | RESOLUTION: 28 31 | SHARE_BOX_FEATURE_EXTRACTOR: False 32 | MASK_ON: True 33 | DATASETS: 34 | TRAIN: ("cityscapes_fine_instanceonly_seg_train_cocostyle",) 35 | TEST: ("cityscapes_fine_instanceonly_seg_val_cocostyle",) 36 | DATALOADER: 37 | SIZE_DIVISIBILITY: 32 38 | SOLVER: 39 | BASE_LR: 0.01 40 | WEIGHT_DECAY: 0.0001 41 | STEPS: (18000,) 42 | MAX_ITER: 24000 43 | -------------------------------------------------------------------------------- /strix/misc/configs/retinanet/retinanet_R-50-FPN_1x_quick.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | RPN_ONLY: True 5 | RETINANET_ON: True 6 | BACKBONE: 7 | CONV_BODY: "R-50-FPN-RETINANET" 8 | RESNETS: 9 | BACKBONE_OUT_CHANNELS: 256 10 | RPN: 11 | USE_FPN: True 12 | FG_IOU_THRESHOLD: 0.5 13 | BG_IOU_THRESHOLD: 0.4 14 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 15 | PRE_NMS_TOP_N_TRAIN: 2000 16 | PRE_NMS_TOP_N_TEST: 1000 17 | POST_NMS_TOP_N_TEST: 1000 18 | FPN_POST_NMS_TOP_N_TEST: 1000 19 | ROI_HEADS: 20 | USE_FPN: True 21 | BATCH_SIZE_PER_IMAGE: 256 22 | ROI_BOX_HEAD: 23 | POOLER_RESOLUTION: 7 24 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 25 | POOLER_SAMPLING_RATIO: 2 26 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 27 | PREDICTOR: "FPNPredictor" 28 | RETINANET: 29 | SCALES_PER_OCTAVE: 3 30 | STRADDLE_THRESH: -1 31 | FG_IOU_THRESHOLD: 0.5 32 | BG_IOU_THRESHOLD: 0.4 33 | DATASETS: 34 | TRAIN: ("coco_2014_minival",) 35 | TEST: ("coco_2014_minival",) 36 | INPUT: 37 | MIN_SIZE_TRAIN: (600,) 38 | MAX_SIZE_TRAIN: 1000 39 | MIN_SIZE_TEST: 800 40 | MAX_SIZE_TEST: 1000 41 | DATALOADER: 42 | SIZE_DIVISIBILITY: 32 43 | SOLVER: 44 | BASE_LR: 0.005 45 | WEIGHT_DECAY: 0.0001 46 | STEPS: (3500,) 47 | MAX_ITER: 4000 48 | IMS_PER_BATCH: 4 49 | -------------------------------------------------------------------------------- /strix/models/rcnn/utils/env.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import os 3 | 4 | from strix.models.rcnn.utils.imports import import_file 5 | 6 | 7 | def setup_environment(): 8 | """Perform environment setup work. The default setup is a no-op, but this 9 | function allows the user to specify a Python source file that performs 10 | custom setup work that may be necessary to their computing environment. 11 | """ 12 | custom_module_path = os.environ.get("TORCH_DETECTRON_ENV_MODULE") 13 | if custom_module_path: 14 | setup_custom_environment(custom_module_path) 15 | else: 16 | # The default setup is a no-op 17 | pass 18 | 19 | 20 | def setup_custom_environment(custom_module_path): 21 | """Load custom environment setup from a Python source file and run the setup 22 | function. 23 | """ 24 | module = import_file("strix.models.rcnn.utils.env.custom_module", custom_module_path) 25 | assert hasattr(module, "setup_environment") and callable( 26 | module.setup_environment 27 | ), ( 28 | "Custom environment module defined in {} does not have the " 29 | "required callable attribute 'setup_environment'." 30 | ).format( 31 | custom_module_path 32 | ) 33 | module.setup_environment() 34 | 35 | 36 | # Force environment setup when this module is imported 37 | setup_environment() 38 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_mask_rcnn_X_101_32x8d_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/FAIR/20171220/X-101-32x8d" 4 | BACKBONE: 5 | CONV_BODY: "R-101-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | STRIDE_IN_1X1: False 9 | NUM_GROUPS: 32 10 | WIDTH_PER_GROUP: 8 11 | RPN: 12 | USE_FPN: True 13 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 14 | PRE_NMS_TOP_N_TRAIN: 2000 15 | PRE_NMS_TOP_N_TEST: 1000 16 | POST_NMS_TOP_N_TEST: 1000 17 | FPN_POST_NMS_TOP_N_TEST: 1000 18 | ROI_HEADS: 19 | USE_FPN: True 20 | ROI_BOX_HEAD: 21 | POOLER_RESOLUTION: 7 22 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 23 | POOLER_SAMPLING_RATIO: 2 24 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 25 | PREDICTOR: "FPNPredictor" 26 | ROI_MASK_HEAD: 27 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 28 | FEATURE_EXTRACTOR: "MaskRCNNFPNFeatureExtractor" 29 | PREDICTOR: "MaskRCNNC4Predictor" 30 | POOLER_RESOLUTION: 14 31 | POOLER_SAMPLING_RATIO: 2 32 | RESOLUTION: 28 33 | SHARE_BOX_FEATURE_EXTRACTOR: False 34 | MASK_ON: True 35 | DATASETS: 36 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 37 | TEST: ("coco_2014_minival",) 38 | DATALOADER: 39 | SIZE_DIVISIBILITY: 32 40 | SOLVER: 41 | BASE_LR: 0.01 42 | WEIGHT_DECAY: 0.0001 43 | STEPS: (120000, 160000) 44 | MAX_ITER: 180000 45 | IMS_PER_BATCH: 8 46 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_keypoint_rcnn_R_50_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | BACKBONE: 5 | CONV_BODY: "R-50-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | RPN: 9 | USE_FPN: True 10 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 11 | PRE_NMS_TOP_N_TRAIN: 2000 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 1000 14 | FPN_POST_NMS_TOP_N_TEST: 1000 15 | ROI_HEADS: 16 | USE_FPN: True 17 | ROI_BOX_HEAD: 18 | POOLER_RESOLUTION: 7 19 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 20 | POOLER_SAMPLING_RATIO: 2 21 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 22 | PREDICTOR: "FPNPredictor" 23 | NUM_CLASSES: 2 24 | ROI_KEYPOINT_HEAD: 25 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 26 | FEATURE_EXTRACTOR: "KeypointRCNNFeatureExtractor" 27 | PREDICTOR: "KeypointRCNNPredictor" 28 | POOLER_RESOLUTION: 14 29 | POOLER_SAMPLING_RATIO: 2 30 | RESOLUTION: 56 31 | SHARE_BOX_FEATURE_EXTRACTOR: False 32 | KEYPOINT_ON: True 33 | DATASETS: 34 | TRAIN: ("keypoints_coco_2014_train", "keypoints_coco_2014_valminusminival",) 35 | TEST: ("keypoints_coco_2014_minival",) 36 | INPUT: 37 | MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) 38 | DATALOADER: 39 | SIZE_DIVISIBILITY: 32 40 | SOLVER: 41 | BASE_LR: 0.02 42 | WEIGHT_DECAY: 0.0001 43 | STEPS: (60000, 80000) 44 | MAX_ITER: 90000 45 | -------------------------------------------------------------------------------- /strix/misc/configs/retinanet/retinanet_R-50-FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | RPN_ONLY: True 5 | RETINANET_ON: True 6 | BACKBONE: 7 | CONV_BODY: "R-50-FPN-RETINANET" 8 | RESNETS: 9 | BACKBONE_OUT_CHANNELS: 256 10 | RPN: 11 | USE_FPN: True 12 | FG_IOU_THRESHOLD: 0.5 13 | BG_IOU_THRESHOLD: 0.4 14 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 15 | PRE_NMS_TOP_N_TRAIN: 2000 16 | PRE_NMS_TOP_N_TEST: 1000 17 | POST_NMS_TOP_N_TEST: 1000 18 | FPN_POST_NMS_TOP_N_TEST: 1000 19 | ROI_HEADS: 20 | USE_FPN: True 21 | BATCH_SIZE_PER_IMAGE: 256 22 | ROI_BOX_HEAD: 23 | POOLER_RESOLUTION: 7 24 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 25 | POOLER_SAMPLING_RATIO: 2 26 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 27 | PREDICTOR: "FPNPredictor" 28 | RETINANET: 29 | SCALES_PER_OCTAVE: 3 30 | STRADDLE_THRESH: -1 31 | FG_IOU_THRESHOLD: 0.5 32 | BG_IOU_THRESHOLD: 0.4 33 | DATASETS: 34 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 35 | TEST: ("coco_2014_minival",) 36 | INPUT: 37 | MIN_SIZE_TRAIN: (800,) 38 | MAX_SIZE_TRAIN: 1333 39 | MIN_SIZE_TEST: 800 40 | MAX_SIZE_TEST: 1333 41 | DATALOADER: 42 | SIZE_DIVISIBILITY: 32 43 | SOLVER: 44 | # Assume 4 gpus 45 | BASE_LR: 0.005 46 | WEIGHT_DECAY: 0.0001 47 | STEPS: (120000, 160000) 48 | MAX_ITER: 180000 49 | IMS_PER_BATCH: 8 50 | -------------------------------------------------------------------------------- /strix/misc/configs/retinanet/retinanet_R-101-FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-101" 4 | RPN_ONLY: True 5 | RETINANET_ON: True 6 | BACKBONE: 7 | CONV_BODY: "R-101-FPN-RETINANET" 8 | RESNETS: 9 | BACKBONE_OUT_CHANNELS: 256 10 | RPN: 11 | USE_FPN: True 12 | FG_IOU_THRESHOLD: 0.5 13 | BG_IOU_THRESHOLD: 0.4 14 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 15 | PRE_NMS_TOP_N_TRAIN: 2000 16 | PRE_NMS_TOP_N_TEST: 1000 17 | POST_NMS_TOP_N_TEST: 1000 18 | FPN_POST_NMS_TOP_N_TEST: 1000 19 | ROI_HEADS: 20 | USE_FPN: True 21 | BATCH_SIZE_PER_IMAGE: 256 22 | ROI_BOX_HEAD: 23 | POOLER_RESOLUTION: 7 24 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 25 | POOLER_SAMPLING_RATIO: 2 26 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 27 | PREDICTOR: "FPNPredictor" 28 | RETINANET: 29 | SCALES_PER_OCTAVE: 3 30 | STRADDLE_THRESH: -1 31 | FG_IOU_THRESHOLD: 0.5 32 | BG_IOU_THRESHOLD: 0.4 33 | DATASETS: 34 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 35 | TEST: ("coco_2014_minival",) 36 | INPUT: 37 | MIN_SIZE_TRAIN: (800, ) 38 | MAX_SIZE_TRAIN: 1333 39 | MIN_SIZE_TEST: 800 40 | MAX_SIZE_TEST: 1333 41 | DATALOADER: 42 | SIZE_DIVISIBILITY: 32 43 | SOLVER: 44 | # Assume 4 gpus 45 | BASE_LR: 0.005 46 | WEIGHT_DECAY: 0.0001 47 | STEPS: (120000, 160000) 48 | MAX_ITER: 180000 49 | IMS_PER_BATCH: 8 50 | -------------------------------------------------------------------------------- /strix/misc/configs/retinanet/retinanet_R-50-FPN_P5_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | RPN_ONLY: True 5 | RETINANET_ON: True 6 | BACKBONE: 7 | CONV_BODY: "R-50-FPN-RETINANET" 8 | RESNETS: 9 | BACKBONE_OUT_CHANNELS: 256 10 | RPN: 11 | USE_FPN: True 12 | FG_IOU_THRESHOLD: 0.5 13 | BG_IOU_THRESHOLD: 0.4 14 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 15 | PRE_NMS_TOP_N_TRAIN: 2000 16 | PRE_NMS_TOP_N_TEST: 1000 17 | POST_NMS_TOP_N_TEST: 1000 18 | FPN_POST_NMS_TOP_N_TEST: 1000 19 | ROI_HEADS: 20 | USE_FPN: True 21 | BATCH_SIZE_PER_IMAGE: 256 22 | ROI_BOX_HEAD: 23 | POOLER_RESOLUTION: 7 24 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 25 | POOLER_SAMPLING_RATIO: 2 26 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 27 | PREDICTOR: "FPNPredictor" 28 | RETINANET: 29 | SCALES_PER_OCTAVE: 3 30 | STRADDLE_THRESH: -1 31 | USE_C5: False 32 | FG_IOU_THRESHOLD: 0.5 33 | BG_IOU_THRESHOLD: 0.4 34 | DATASETS: 35 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 36 | TEST: ("coco_2014_minival",) 37 | INPUT: 38 | MIN_SIZE_TRAIN: (800,) 39 | MAX_SIZE_TRAIN: 1333 40 | MIN_SIZE_TEST: 800 41 | MAX_SIZE_TEST: 1333 42 | DATALOADER: 43 | SIZE_DIVISIBILITY: 32 44 | SOLVER: 45 | # Assume 4 gpus 46 | BASE_LR: 0.005 47 | WEIGHT_DECAY: 0.0001 48 | STEPS: (120000, 160000) 49 | MAX_ITER: 180000 50 | IMS_PER_BATCH: 8 51 | -------------------------------------------------------------------------------- /strix/misc/configs/retinanet/retinanet_R-101-FPN_P5_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-101" 4 | RPN_ONLY: True 5 | RETINANET_ON: True 6 | BACKBONE: 7 | CONV_BODY: "R-101-FPN-RETINANET" 8 | RESNETS: 9 | BACKBONE_OUT_CHANNELS: 256 10 | RPN: 11 | USE_FPN: True 12 | FG_IOU_THRESHOLD: 0.5 13 | BG_IOU_THRESHOLD: 0.4 14 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 15 | PRE_NMS_TOP_N_TRAIN: 2000 16 | PRE_NMS_TOP_N_TEST: 1000 17 | POST_NMS_TOP_N_TEST: 1000 18 | FPN_POST_NMS_TOP_N_TEST: 1000 19 | ROI_HEADS: 20 | USE_FPN: True 21 | BATCH_SIZE_PER_IMAGE: 256 22 | ROI_BOX_HEAD: 23 | POOLER_RESOLUTION: 7 24 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 25 | POOLER_SAMPLING_RATIO: 2 26 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 27 | PREDICTOR: "FPNPredictor" 28 | RETINANET: 29 | SCALES_PER_OCTAVE: 3 30 | STRADDLE_THRESH: -1 31 | USE_C5: False 32 | FG_IOU_THRESHOLD: 0.5 33 | BG_IOU_THRESHOLD: 0.4 34 | DATASETS: 35 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 36 | TEST: ("coco_2014_minival",) 37 | INPUT: 38 | MIN_SIZE_TRAIN: (800, ) 39 | MAX_SIZE_TRAIN: 1333 40 | MIN_SIZE_TEST: 800 41 | MAX_SIZE_TEST: 1333 42 | DATALOADER: 43 | SIZE_DIVISIBILITY: 32 44 | SOLVER: 45 | # Assume 4 gpus 46 | BASE_LR: 0.005 47 | WEIGHT_DECAY: 0.0001 48 | STEPS: (120000, 160000) 49 | MAX_ITER: 180000 50 | IMS_PER_BATCH: 8 51 | -------------------------------------------------------------------------------- /strix/misc/configs/gn_baselines/e2e_faster_rcnn_R_50_FPN_1x_gn.yaml: -------------------------------------------------------------------------------- 1 | INPUT: 2 | MIN_SIZE_TRAIN: (800,) 3 | MAX_SIZE_TRAIN: 1333 4 | MIN_SIZE_TEST: 800 5 | MAX_SIZE_TEST: 1333 6 | MODEL: 7 | META_ARCHITECTURE: "GeneralizedRCNN" 8 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50-GN" 9 | BACKBONE: 10 | CONV_BODY: "R-50-FPN" 11 | RESNETS: # use GN for backbone 12 | BACKBONE_OUT_CHANNELS: 256 13 | STRIDE_IN_1X1: False 14 | TRANS_FUNC: "BottleneckWithGN" 15 | STEM_FUNC: "StemWithGN" 16 | FPN: 17 | USE_GN: True # use GN for FPN 18 | RPN: 19 | USE_FPN: True 20 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 21 | PRE_NMS_TOP_N_TRAIN: 2000 22 | PRE_NMS_TOP_N_TEST: 1000 23 | POST_NMS_TOP_N_TEST: 1000 24 | FPN_POST_NMS_TOP_N_TEST: 1000 25 | ROI_HEADS: 26 | USE_FPN: True 27 | BATCH_SIZE_PER_IMAGE: 512 28 | POSITIVE_FRACTION: 0.25 29 | ROI_BOX_HEAD: 30 | USE_GN: True # use GN for bbox head 31 | POOLER_RESOLUTION: 7 32 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 33 | POOLER_SAMPLING_RATIO: 2 34 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 35 | PREDICTOR: "FPNPredictor" 36 | DATASETS: 37 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 38 | TEST: ("coco_2014_minival",) 39 | DATALOADER: 40 | SIZE_DIVISIBILITY: 32 41 | SOLVER: 42 | # Assume 8 gpus 43 | BASE_LR: 0.02 44 | WEIGHT_DECAY: 0.0001 45 | STEPS: (60000, 80000) 46 | MAX_ITER: 90000 47 | IMS_PER_BATCH: 16 48 | TEST: 49 | IMS_PER_BATCH: 8 50 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/roi_heads/keypoint_head/roi_keypoint_predictors.py: -------------------------------------------------------------------------------- 1 | from torch import nn 2 | 3 | from strix.models.rcnn import layers 4 | from strix.models.rcnn.modeling import registry 5 | 6 | 7 | @registry.ROI_KEYPOINT_PREDICTOR.register("KeypointRCNNPredictor") 8 | class KeypointRCNNPredictor(nn.Module): 9 | def __init__(self, cfg, in_channels): 10 | super(KeypointRCNNPredictor, self).__init__() 11 | input_features = in_channels 12 | num_keypoints = cfg.MODEL.ROI_KEYPOINT_HEAD.NUM_CLASSES 13 | deconv_kernel = 4 14 | self.kps_score_lowres = layers.ConvTranspose2d( 15 | input_features, 16 | num_keypoints, 17 | deconv_kernel, 18 | stride=2, 19 | padding=deconv_kernel // 2 - 1, 20 | ) 21 | nn.init.kaiming_normal_( 22 | self.kps_score_lowres.weight, mode="fan_out", nonlinearity="relu" 23 | ) 24 | nn.init.constant_(self.kps_score_lowres.bias, 0) 25 | self.up_scale = 2 26 | self.out_channels = num_keypoints 27 | 28 | def forward(self, x): 29 | x = self.kps_score_lowres(x) 30 | x = layers.interpolate( 31 | x, scale_factor=self.up_scale, mode="bilinear", align_corners=False 32 | ) 33 | return x 34 | 35 | 36 | def make_roi_keypoint_predictor(cfg, in_channels): 37 | func = registry.ROI_KEYPOINT_PREDICTOR[cfg.MODEL.ROI_KEYPOINT_HEAD.PREDICTOR] 38 | return func(cfg, in_channels) 39 | -------------------------------------------------------------------------------- /strix/misc/configs/quick_schedules/e2e_mask_rcnn_R_50_FPN_quick.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | BACKBONE: 5 | CONV_BODY: "R-50-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | RPN: 9 | USE_FPN: True 10 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 11 | PRE_NMS_TOP_N_TRAIN: 2000 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 1000 14 | FPN_POST_NMS_TOP_N_TEST: 1000 15 | ROI_HEADS: 16 | USE_FPN: True 17 | BATCH_SIZE_PER_IMAGE: 256 18 | ROI_BOX_HEAD: 19 | POOLER_RESOLUTION: 7 20 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 21 | POOLER_SAMPLING_RATIO: 2 22 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 23 | PREDICTOR: "FPNPredictor" 24 | ROI_MASK_HEAD: 25 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 26 | FEATURE_EXTRACTOR: "MaskRCNNFPNFeatureExtractor" 27 | PREDICTOR: "MaskRCNNC4Predictor" 28 | POOLER_RESOLUTION: 14 29 | POOLER_SAMPLING_RATIO: 2 30 | RESOLUTION: 28 31 | SHARE_BOX_FEATURE_EXTRACTOR: False 32 | MASK_ON: True 33 | DATASETS: 34 | TRAIN: ("coco_2014_minival",) 35 | TEST: ("coco_2014_minival",) 36 | INPUT: 37 | MIN_SIZE_TRAIN: (600,) 38 | MAX_SIZE_TRAIN: 1000 39 | MIN_SIZE_TEST: 800 40 | MAX_SIZE_TEST: 1000 41 | DATALOADER: 42 | SIZE_DIVISIBILITY: 32 43 | SOLVER: 44 | BASE_LR: 0.005 45 | WEIGHT_DECAY: 0.0001 46 | STEPS: (1500,) 47 | MAX_ITER: 2000 48 | IMS_PER_BATCH: 4 49 | TEST: 50 | IMS_PER_BATCH: 2 51 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_mask_rcnn_fbnet.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | BACKBONE: 4 | CONV_BODY: FBNet 5 | FBNET: 6 | ARCH: "default" 7 | BN_TYPE: "bn" 8 | WIDTH_DIVISOR: 8 9 | DW_CONV_SKIP_BN: True 10 | DW_CONV_SKIP_RELU: True 11 | DET_HEAD_LAST_SCALE: 0.0 12 | RPN: 13 | ANCHOR_SIZES: (16, 32, 64, 128, 256) 14 | ANCHOR_STRIDE: (16, ) 15 | BATCH_SIZE_PER_IMAGE: 256 16 | PRE_NMS_TOP_N_TRAIN: 6000 17 | PRE_NMS_TOP_N_TEST: 6000 18 | POST_NMS_TOP_N_TRAIN: 2000 19 | POST_NMS_TOP_N_TEST: 100 20 | RPN_HEAD: FBNet.rpn_head 21 | ROI_HEADS: 22 | BATCH_SIZE_PER_IMAGE: 256 23 | ROI_BOX_HEAD: 24 | POOLER_RESOLUTION: 6 25 | FEATURE_EXTRACTOR: FBNet.roi_head 26 | NUM_CLASSES: 81 27 | ROI_MASK_HEAD: 28 | POOLER_RESOLUTION: 6 29 | FEATURE_EXTRACTOR: FBNet.roi_head_mask 30 | PREDICTOR: "MaskRCNNConv1x1Predictor" 31 | RESOLUTION: 12 32 | SHARE_BOX_FEATURE_EXTRACTOR: False 33 | MASK_ON: True 34 | DATASETS: 35 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 36 | TEST: ("coco_2014_minival",) 37 | SOLVER: 38 | BASE_LR: 0.06 39 | WARMUP_FACTOR: 0.1 40 | WEIGHT_DECAY: 0.0001 41 | STEPS: (60000, 80000) 42 | MAX_ITER: 90000 43 | IMS_PER_BATCH: 128 # for 8GPUs 44 | # TEST: 45 | # IMS_PER_BATCH: 8 46 | INPUT: 47 | MIN_SIZE_TRAIN: (320, ) 48 | MAX_SIZE_TRAIN: 640 49 | MIN_SIZE_TEST: 320 50 | MAX_SIZE_TEST: 640 51 | PIXEL_MEAN: [103.53, 116.28, 123.675] 52 | PIXEL_STD: [57.375, 57.12, 58.395] 53 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_mask_rcnn_fbnet_600.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | BACKBONE: 4 | CONV_BODY: FBNet 5 | FBNET: 6 | ARCH: "default" 7 | BN_TYPE: "bn" 8 | WIDTH_DIVISOR: 8 9 | DW_CONV_SKIP_BN: True 10 | DW_CONV_SKIP_RELU: True 11 | DET_HEAD_LAST_SCALE: 0.0 12 | RPN: 13 | ANCHOR_SIZES: (32, 64, 128, 256, 512) 14 | ANCHOR_STRIDE: (16, ) 15 | BATCH_SIZE_PER_IMAGE: 256 16 | PRE_NMS_TOP_N_TRAIN: 6000 17 | PRE_NMS_TOP_N_TEST: 6000 18 | POST_NMS_TOP_N_TRAIN: 2000 19 | POST_NMS_TOP_N_TEST: 200 20 | RPN_HEAD: FBNet.rpn_head 21 | ROI_HEADS: 22 | BATCH_SIZE_PER_IMAGE: 256 23 | ROI_BOX_HEAD: 24 | POOLER_RESOLUTION: 6 25 | FEATURE_EXTRACTOR: FBNet.roi_head 26 | NUM_CLASSES: 81 27 | ROI_MASK_HEAD: 28 | POOLER_RESOLUTION: 6 29 | FEATURE_EXTRACTOR: FBNet.roi_head_mask 30 | PREDICTOR: "MaskRCNNConv1x1Predictor" 31 | RESOLUTION: 12 32 | SHARE_BOX_FEATURE_EXTRACTOR: False 33 | MASK_ON: True 34 | DATASETS: 35 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 36 | TEST: ("coco_2014_minival",) 37 | SOLVER: 38 | BASE_LR: 0.06 39 | WARMUP_FACTOR: 0.1 40 | WEIGHT_DECAY: 0.0001 41 | STEPS: (60000, 80000) 42 | MAX_ITER: 90000 43 | IMS_PER_BATCH: 128 # for 8GPUs 44 | # TEST: 45 | # IMS_PER_BATCH: 8 46 | INPUT: 47 | MIN_SIZE_TRAIN: (600, ) 48 | MAX_SIZE_TRAIN: 1000 49 | MIN_SIZE_TEST: 600 50 | MAX_SIZE_TEST: 1000 51 | PIXEL_MEAN: [103.53, 116.28, 123.675] 52 | PIXEL_STD: [57.375, 57.12, 58.395] 53 | -------------------------------------------------------------------------------- /strix/misc/configs/gn_baselines/scratch_e2e_faster_rcnn_R_50_FPN_3x_gn.yaml: -------------------------------------------------------------------------------- 1 | INPUT: 2 | MIN_SIZE_TRAIN: (800,) 3 | MAX_SIZE_TRAIN: 1333 4 | MIN_SIZE_TEST: 800 5 | MAX_SIZE_TEST: 1333 6 | MODEL: 7 | META_ARCHITECTURE: "GeneralizedRCNN" 8 | WEIGHT: "" # no pretrained model 9 | BACKBONE: 10 | CONV_BODY: "R-50-FPN" 11 | FREEZE_CONV_BODY_AT: 0 # finetune all layers 12 | RESNETS: # use GN for backbone 13 | BACKBONE_OUT_CHANNELS: 256 14 | STRIDE_IN_1X1: False 15 | TRANS_FUNC: "BottleneckWithGN" 16 | STEM_FUNC: "StemWithGN" 17 | FPN: 18 | USE_GN: True # use GN for FPN 19 | RPN: 20 | USE_FPN: True 21 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 22 | PRE_NMS_TOP_N_TRAIN: 2000 23 | PRE_NMS_TOP_N_TEST: 1000 24 | POST_NMS_TOP_N_TEST: 1000 25 | FPN_POST_NMS_TOP_N_TEST: 1000 26 | ROI_HEADS: 27 | USE_FPN: True 28 | BATCH_SIZE_PER_IMAGE: 512 29 | POSITIVE_FRACTION: 0.25 30 | ROI_BOX_HEAD: 31 | USE_GN: True # use GN for bbox head 32 | POOLER_RESOLUTION: 7 33 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 34 | POOLER_SAMPLING_RATIO: 2 35 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 36 | PREDICTOR: "FPNPredictor" 37 | DATASETS: 38 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 39 | TEST: ("coco_2014_minival",) 40 | DATALOADER: 41 | SIZE_DIVISIBILITY: 32 42 | SOLVER: 43 | # Assume 8 gpus 44 | BASE_LR: 0.02 45 | WEIGHT_DECAY: 0.0001 46 | STEPS: (210000, 250000) 47 | MAX_ITER: 270000 48 | IMS_PER_BATCH: 16 49 | TEST: 50 | IMS_PER_BATCH: 8 51 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_mask_rcnn_fbnet_xirb16d_dsmask.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | BACKBONE: 4 | CONV_BODY: FBNet 5 | FBNET: 6 | ARCH: "xirb16d_dsmask" 7 | BN_TYPE: "bn" 8 | WIDTH_DIVISOR: 8 9 | DW_CONV_SKIP_BN: True 10 | DW_CONV_SKIP_RELU: True 11 | DET_HEAD_LAST_SCALE: -1.0 12 | RPN: 13 | ANCHOR_SIZES: (16, 32, 64, 128, 256) 14 | ANCHOR_STRIDE: (16, ) 15 | BATCH_SIZE_PER_IMAGE: 256 16 | PRE_NMS_TOP_N_TRAIN: 6000 17 | PRE_NMS_TOP_N_TEST: 6000 18 | POST_NMS_TOP_N_TRAIN: 2000 19 | POST_NMS_TOP_N_TEST: 100 20 | RPN_HEAD: FBNet.rpn_head 21 | ROI_HEADS: 22 | BATCH_SIZE_PER_IMAGE: 512 23 | ROI_BOX_HEAD: 24 | POOLER_RESOLUTION: 6 25 | FEATURE_EXTRACTOR: FBNet.roi_head 26 | NUM_CLASSES: 81 27 | ROI_MASK_HEAD: 28 | POOLER_RESOLUTION: 6 29 | FEATURE_EXTRACTOR: FBNet.roi_head_mask 30 | PREDICTOR: "MaskRCNNConv1x1Predictor" 31 | RESOLUTION: 12 32 | SHARE_BOX_FEATURE_EXTRACTOR: False 33 | MASK_ON: True 34 | DATASETS: 35 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 36 | TEST: ("coco_2014_minival",) 37 | SOLVER: 38 | BASE_LR: 0.06 39 | WARMUP_FACTOR: 0.1 40 | WEIGHT_DECAY: 0.0001 41 | STEPS: (60000, 80000) 42 | MAX_ITER: 90000 43 | IMS_PER_BATCH: 128 # for 8GPUs 44 | # TEST: 45 | # IMS_PER_BATCH: 8 46 | INPUT: 47 | MIN_SIZE_TRAIN: (320, ) 48 | MAX_SIZE_TRAIN: 640 49 | MIN_SIZE_TEST: 320 50 | MAX_SIZE_TEST: 640 51 | PIXEL_MEAN: [103.53, 116.28, 123.675] 52 | PIXEL_STD: [57.375, 57.12, 58.395] 53 | -------------------------------------------------------------------------------- /strix/misc/configs/e2e_mask_rcnn_fbnet_xirb16d_dsmask_600.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | BACKBONE: 4 | CONV_BODY: FBNet 5 | FBNET: 6 | ARCH: "xirb16d_dsmask" 7 | BN_TYPE: "bn" 8 | WIDTH_DIVISOR: 8 9 | DW_CONV_SKIP_BN: True 10 | DW_CONV_SKIP_RELU: True 11 | DET_HEAD_LAST_SCALE: 0.0 12 | RPN: 13 | ANCHOR_SIZES: (32, 64, 128, 256, 512) 14 | ANCHOR_STRIDE: (16, ) 15 | BATCH_SIZE_PER_IMAGE: 256 16 | PRE_NMS_TOP_N_TRAIN: 6000 17 | PRE_NMS_TOP_N_TEST: 6000 18 | POST_NMS_TOP_N_TRAIN: 2000 19 | POST_NMS_TOP_N_TEST: 200 20 | RPN_HEAD: FBNet.rpn_head 21 | ROI_HEADS: 22 | BATCH_SIZE_PER_IMAGE: 256 23 | ROI_BOX_HEAD: 24 | POOLER_RESOLUTION: 6 25 | FEATURE_EXTRACTOR: FBNet.roi_head 26 | NUM_CLASSES: 81 27 | ROI_MASK_HEAD: 28 | POOLER_RESOLUTION: 6 29 | FEATURE_EXTRACTOR: FBNet.roi_head_mask 30 | PREDICTOR: "MaskRCNNConv1x1Predictor" 31 | RESOLUTION: 12 32 | SHARE_BOX_FEATURE_EXTRACTOR: False 33 | MASK_ON: True 34 | DATASETS: 35 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 36 | TEST: ("coco_2014_minival",) 37 | SOLVER: 38 | BASE_LR: 0.06 39 | WARMUP_FACTOR: 0.1 40 | WEIGHT_DECAY: 0.0001 41 | STEPS: (60000, 80000) 42 | MAX_ITER: 90000 43 | IMS_PER_BATCH: 128 # for 8GPUs 44 | # TEST: 45 | # IMS_PER_BATCH: 8 46 | INPUT: 47 | MIN_SIZE_TRAIN: (600, ) 48 | MAX_SIZE_TRAIN: 1000 49 | MIN_SIZE_TEST: 600 50 | MAX_SIZE_TEST: 1000 51 | PIXEL_MEAN: [103.53, 116.28, 123.675] 52 | PIXEL_STD: [57.375, 57.12, 58.395] 53 | -------------------------------------------------------------------------------- /strix/misc/configs/retinanet/retinanet_X_101_32x8d_FPN_1x.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/FAIR/20171220/X-101-32x8d" 4 | RPN_ONLY: True 5 | RETINANET_ON: True 6 | BACKBONE: 7 | CONV_BODY: "R-101-FPN-RETINANET" 8 | RESNETS: 9 | BACKBONE_OUT_CHANNELS: 256 10 | STRIDE_IN_1X1: False 11 | NUM_GROUPS: 32 12 | WIDTH_PER_GROUP: 8 13 | RPN: 14 | USE_FPN: True 15 | FG_IOU_THRESHOLD: 0.5 16 | BG_IOU_THRESHOLD: 0.4 17 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 18 | PRE_NMS_TOP_N_TRAIN: 2000 19 | PRE_NMS_TOP_N_TEST: 1000 20 | POST_NMS_TOP_N_TEST: 1000 21 | FPN_POST_NMS_TOP_N_TEST: 1000 22 | ROI_HEADS: 23 | USE_FPN: True 24 | BATCH_SIZE_PER_IMAGE: 256 25 | ROI_BOX_HEAD: 26 | POOLER_RESOLUTION: 7 27 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 28 | POOLER_SAMPLING_RATIO: 2 29 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 30 | PREDICTOR: "FPNPredictor" 31 | RETINANET: 32 | SCALES_PER_OCTAVE: 3 33 | STRADDLE_THRESH: -1 34 | FG_IOU_THRESHOLD: 0.5 35 | BG_IOU_THRESHOLD: 0.4 36 | DATASETS: 37 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 38 | TEST: ("coco_2014_minival",) 39 | INPUT: 40 | MIN_SIZE_TRAIN: (800, ) 41 | MAX_SIZE_TRAIN: 1333 42 | MIN_SIZE_TEST: 800 43 | MAX_SIZE_TEST: 1333 44 | DATALOADER: 45 | SIZE_DIVISIBILITY: 32 46 | SOLVER: 47 | # Assume 4 gpus 48 | BASE_LR: 0.0025 49 | WEIGHT_DECAY: 0.0001 50 | STEPS: (240000, 320000) 51 | MAX_ITER: 360000 52 | IMS_PER_BATCH: 4 53 | -------------------------------------------------------------------------------- /strix/misc/configs/gn_baselines/e2e_faster_rcnn_R_50_FPN_Xconv1fc_1x_gn.yaml: -------------------------------------------------------------------------------- 1 | INPUT: 2 | MIN_SIZE_TRAIN: (800,) 3 | MAX_SIZE_TRAIN: 1333 4 | MIN_SIZE_TEST: 800 5 | MAX_SIZE_TEST: 1333 6 | MODEL: 7 | META_ARCHITECTURE: "GeneralizedRCNN" 8 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50-GN" 9 | BACKBONE: 10 | CONV_BODY: "R-50-FPN" 11 | RESNETS: # use GN for backbone 12 | BACKBONE_OUT_CHANNELS: 256 13 | STRIDE_IN_1X1: False 14 | TRANS_FUNC: "BottleneckWithGN" 15 | STEM_FUNC: "StemWithGN" 16 | FPN: 17 | USE_GN: True # use GN for FPN 18 | RPN: 19 | USE_FPN: True 20 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 21 | PRE_NMS_TOP_N_TRAIN: 2000 22 | PRE_NMS_TOP_N_TEST: 1000 23 | POST_NMS_TOP_N_TEST: 1000 24 | FPN_POST_NMS_TOP_N_TEST: 1000 25 | ROI_HEADS: 26 | USE_FPN: True 27 | BATCH_SIZE_PER_IMAGE: 512 28 | POSITIVE_FRACTION: 0.25 29 | ROI_BOX_HEAD: 30 | USE_GN: True # use GN for bbox head 31 | POOLER_RESOLUTION: 7 32 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 33 | POOLER_SAMPLING_RATIO: 2 34 | CONV_HEAD_DIM: 256 35 | NUM_STACKED_CONVS: 4 36 | FEATURE_EXTRACTOR: "FPNXconv1fcFeatureExtractor" 37 | PREDICTOR: "FPNPredictor" 38 | DATASETS: 39 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 40 | TEST: ("coco_2014_minival",) 41 | DATALOADER: 42 | SIZE_DIVISIBILITY: 32 43 | SOLVER: 44 | # Assume 8 gpus 45 | BASE_LR: 0.02 46 | WEIGHT_DECAY: 0.0001 47 | STEPS: (60000, 80000) 48 | MAX_ITER: 90000 49 | IMS_PER_BATCH: 16 50 | TEST: 51 | IMS_PER_BATCH: 8 52 | -------------------------------------------------------------------------------- /strix/misc/configs/quick_schedules/e2e_keypoint_rcnn_R_50_FPN_quick.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" 4 | BACKBONE: 5 | CONV_BODY: "R-50-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | RPN: 9 | USE_FPN: True 10 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 11 | PRE_NMS_TOP_N_TRAIN: 2000 12 | PRE_NMS_TOP_N_TEST: 1000 13 | POST_NMS_TOP_N_TEST: 1000 14 | FPN_POST_NMS_TOP_N_TEST: 1000 15 | ROI_HEADS: 16 | USE_FPN: True 17 | BATCH_SIZE_PER_IMAGE: 256 18 | ROI_BOX_HEAD: 19 | POOLER_RESOLUTION: 7 20 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 21 | POOLER_SAMPLING_RATIO: 2 22 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 23 | PREDICTOR: "FPNPredictor" 24 | NUM_CLASSES: 2 25 | ROI_KEYPOINT_HEAD: 26 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 27 | FEATURE_EXTRACTOR: "KeypointRCNNFeatureExtractor" 28 | PREDICTOR: "KeypointRCNNPredictor" 29 | POOLER_RESOLUTION: 14 30 | POOLER_SAMPLING_RATIO: 2 31 | RESOLUTION: 56 32 | SHARE_BOX_FEATURE_EXTRACTOR: False 33 | KEYPOINT_ON: True 34 | DATASETS: 35 | TRAIN: ("keypoints_coco_2014_minival",) 36 | TEST: ("keypoints_coco_2014_minival",) 37 | INPUT: 38 | MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) 39 | MAX_SIZE_TRAIN: 1000 40 | MIN_SIZE_TEST: 800 41 | MAX_SIZE_TEST: 1000 42 | DATALOADER: 43 | SIZE_DIVISIBILITY: 32 44 | SOLVER: 45 | BASE_LR: 0.005 46 | WEIGHT_DECAY: 0.0001 47 | STEPS: (1500,) 48 | MAX_ITER: 2000 49 | IMS_PER_BATCH: 4 50 | TEST: 51 | IMS_PER_BATCH: 2 52 | -------------------------------------------------------------------------------- /strix/models/rcnn/utils/registry.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | 3 | 4 | def _register_generic(module_dict, module_name, module): 5 | assert module_name not in module_dict 6 | module_dict[module_name] = module 7 | 8 | 9 | class Registry(dict): 10 | ''' 11 | A helper class for managing registering modules, it extends a dictionary 12 | and provides a register functions. 13 | 14 | Eg. creeting a registry: 15 | some_registry = Registry({"default": default_module}) 16 | 17 | There're two ways of registering new modules: 18 | 1): normal way is just calling register function: 19 | def foo(): 20 | ... 21 | some_registry.register("foo_module", foo) 22 | 2): used as decorator when declaring the module: 23 | @some_registry.register("foo_module") 24 | @some_registry.register("foo_modeul_nickname") 25 | def foo(): 26 | ... 27 | 28 | Access of module is just like using a dictionary, eg: 29 | f = some_registry["foo_modeul"] 30 | ''' 31 | def __init__(self, *args, **kwargs): 32 | super(Registry, self).__init__(*args, **kwargs) 33 | 34 | def register(self, module_name, module=None): 35 | # used as function call 36 | if module is not None: 37 | _register_generic(self, module_name, module) 38 | return 39 | 40 | # used as decorator 41 | def register_fn(fn): 42 | _register_generic(self, module_name, fn) 43 | return fn 44 | 45 | return register_fn 46 | -------------------------------------------------------------------------------- /strix/misc/configs/gn_baselines/scratch_e2e_faster_rcnn_R_50_FPN_Xconv1fc_3x_gn.yaml: -------------------------------------------------------------------------------- 1 | INPUT: 2 | MIN_SIZE_TRAIN: (800,) 3 | MAX_SIZE_TRAIN: 1333 4 | MIN_SIZE_TEST: 800 5 | MAX_SIZE_TEST: 1333 6 | MODEL: 7 | META_ARCHITECTURE: "GeneralizedRCNN" 8 | WEIGHT: "" # no pretrained model 9 | BACKBONE: 10 | CONV_BODY: "R-50-FPN" 11 | FREEZE_CONV_BODY_AT: 0 # finetune all layers 12 | RESNETS: # use GN for backbone 13 | BACKBONE_OUT_CHANNELS: 256 14 | STRIDE_IN_1X1: False 15 | TRANS_FUNC: "BottleneckWithGN" 16 | STEM_FUNC: "StemWithGN" 17 | FPN: 18 | USE_GN: True # use GN for FPN 19 | RPN: 20 | USE_FPN: True 21 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 22 | PRE_NMS_TOP_N_TRAIN: 2000 23 | PRE_NMS_TOP_N_TEST: 1000 24 | POST_NMS_TOP_N_TEST: 1000 25 | FPN_POST_NMS_TOP_N_TEST: 1000 26 | ROI_HEADS: 27 | USE_FPN: True 28 | BATCH_SIZE_PER_IMAGE: 512 29 | POSITIVE_FRACTION: 0.25 30 | ROI_BOX_HEAD: 31 | USE_GN: True # use GN for bbox head 32 | POOLER_RESOLUTION: 7 33 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 34 | POOLER_SAMPLING_RATIO: 2 35 | CONV_HEAD_DIM: 256 36 | NUM_STACKED_CONVS: 4 37 | FEATURE_EXTRACTOR: "FPNXconv1fcFeatureExtractor" 38 | PREDICTOR: "FPNPredictor" 39 | DATASETS: 40 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 41 | TEST: ("coco_2014_minival",) 42 | DATALOADER: 43 | SIZE_DIVISIBILITY: 32 44 | SOLVER: 45 | # Assume 8 gpus 46 | BASE_LR: 0.02 47 | WEIGHT_DECAY: 0.0001 48 | STEPS: (210000, 250000) 49 | MAX_ITER: 270000 50 | IMS_PER_BATCH: 16 51 | TEST: 52 | IMS_PER_BATCH: 8 53 | -------------------------------------------------------------------------------- /strix/misc/configs/quick_schedules/e2e_mask_rcnn_X_101_32x8d_FPN_quick.yaml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "GeneralizedRCNN" 3 | WEIGHT: "catalog://ImageNetPretrained/FAIR/20171220/X-101-32x8d" 4 | BACKBONE: 5 | CONV_BODY: "R-101-FPN" 6 | RESNETS: 7 | BACKBONE_OUT_CHANNELS: 256 8 | STRIDE_IN_1X1: False 9 | NUM_GROUPS: 32 10 | WIDTH_PER_GROUP: 8 11 | RPN: 12 | USE_FPN: True 13 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 14 | PRE_NMS_TOP_N_TRAIN: 2000 15 | PRE_NMS_TOP_N_TEST: 1000 16 | POST_NMS_TOP_N_TEST: 1000 17 | FPN_POST_NMS_TOP_N_TEST: 1000 18 | ROI_HEADS: 19 | USE_FPN: True 20 | BATCH_SIZE_PER_IMAGE: 256 21 | ROI_BOX_HEAD: 22 | POOLER_RESOLUTION: 7 23 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 24 | POOLER_SAMPLING_RATIO: 2 25 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 26 | PREDICTOR: "FPNPredictor" 27 | ROI_MASK_HEAD: 28 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 29 | FEATURE_EXTRACTOR: "MaskRCNNFPNFeatureExtractor" 30 | PREDICTOR: "MaskRCNNC4Predictor" 31 | POOLER_RESOLUTION: 14 32 | POOLER_SAMPLING_RATIO: 2 33 | RESOLUTION: 28 34 | SHARE_BOX_FEATURE_EXTRACTOR: False 35 | MASK_ON: True 36 | DATASETS: 37 | TRAIN: ("coco_2014_minival",) 38 | TEST: ("coco_2014_minival",) 39 | INPUT: 40 | MIN_SIZE_TRAIN: (600,) 41 | MAX_SIZE_TRAIN: 1000 42 | MIN_SIZE_TEST: 800 43 | MAX_SIZE_TEST: 1000 44 | DATALOADER: 45 | SIZE_DIVISIBILITY: 32 46 | SOLVER: 47 | BASE_LR: 0.005 48 | WEIGHT_DECAY: 0.0001 49 | STEPS: (1500,) 50 | MAX_ITER: 2000 51 | IMS_PER_BATCH: 2 52 | TEST: 53 | IMS_PER_BATCH: 2 54 | -------------------------------------------------------------------------------- /strix/utilities/oyaml.py: -------------------------------------------------------------------------------- 1 | import platform 2 | import sys 3 | from collections import OrderedDict 4 | 5 | import yaml as pyyaml 6 | 7 | 8 | _items = "viewitems" if sys.version_info < (3,) else "items" 9 | _std_dict_is_order_preserving = sys.version_info >= (3, 7) or ( 10 | sys.version_info >= (3, 6) and platform.python_implementation() == "CPython" 11 | ) 12 | 13 | 14 | def map_representer(dumper, data): 15 | return dumper.represent_dict(getattr(data, _items)()) 16 | 17 | 18 | def map_constructor(loader, node): 19 | loader.flatten_mapping(node) 20 | pairs = loader.construct_pairs(node) 21 | try: 22 | return OrderedDict(pairs) 23 | except TypeError: 24 | loader.construct_mapping(node) # trigger any contextual error 25 | raise 26 | 27 | 28 | _loaders = [getattr(pyyaml.loader, x) for x in pyyaml.loader.__all__] 29 | _dumpers = [getattr(pyyaml.dumper, x) for x in pyyaml.dumper.__all__] 30 | try: 31 | _cyaml = pyyaml.cyaml.__all__ 32 | except AttributeError: 33 | pass 34 | else: 35 | _loaders += [getattr(pyyaml.cyaml, x) for x in _cyaml if x.endswith("Loader")] 36 | _dumpers += [getattr(pyyaml.cyaml, x) for x in _cyaml if x.endswith("Dumper")] 37 | 38 | Dumper = None 39 | for Dumper in _dumpers: 40 | pyyaml.add_representer(dict, map_representer, Dumper=Dumper) 41 | pyyaml.add_representer(OrderedDict, map_representer, Dumper=Dumper) 42 | 43 | Loader = None 44 | if not _std_dict_is_order_preserving: 45 | for Loader in _loaders: 46 | pyyaml.add_constructor("tag:yaml.org,2002:map", map_constructor, Loader=Loader) 47 | 48 | 49 | # Merge PyYAML namespace into ours. 50 | # This allows users a drop-in replacement: 51 | # import oyaml as yaml 52 | del map_constructor, map_representer, Loader, Dumper 53 | from yaml import * 54 | -------------------------------------------------------------------------------- /strix/models/cnn/losses/__init__.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from strix.utilities.registry import Registry 3 | from monai_ex.losses import ( 4 | DiceLoss, 5 | GeneralizedDiceLoss, 6 | FocalLoss, 7 | DiceFocalLoss, 8 | DiceCELoss, 9 | DiceTopKLoss 10 | ) 11 | from .losses import ( 12 | ContrastiveLoss, 13 | ContrastiveCELoss, 14 | ContrastiveBCELoss, 15 | CrossEntropyLossEx, 16 | BCEWithLogitsLossEx, 17 | CombinationLoss, 18 | ) 19 | 20 | CLASSIFICATION_LOSS = Registry() 21 | SEGMENTATION_LOSS = Registry() 22 | SIAMESE_LOSS = Registry() 23 | SELFLEARNING_LOSS = Registry() 24 | MULTITASK_LOSS = Registry() 25 | 26 | LOSS_MAPPING = { 27 | "classification": CLASSIFICATION_LOSS, 28 | "segmentation": SEGMENTATION_LOSS, 29 | "siamese": SIAMESE_LOSS, 30 | "selflearning": SELFLEARNING_LOSS, 31 | "multitask": MULTITASK_LOSS, 32 | } 33 | 34 | CLASSIFICATION_LOSS.register('CE', CrossEntropyLossEx) 35 | CLASSIFICATION_LOSS.register('WCE', CrossEntropyLossEx) 36 | CLASSIFICATION_LOSS.register('BCE', BCEWithLogitsLossEx) 37 | CLASSIFICATION_LOSS.register('WBCE', BCEWithLogitsLossEx) 38 | # CLASSIFICATION_LOSS.register('FocalLoss', FocalLoss) 39 | 40 | SEGMENTATION_LOSS.register('DCE', DiceLoss) 41 | SEGMENTATION_LOSS.register('GDL', GeneralizedDiceLoss) 42 | SEGMENTATION_LOSS.register('CE-DCE', DiceCELoss) 43 | SEGMENTATION_LOSS.register('DiceFocalLoss', DiceFocalLoss) 44 | SEGMENTATION_LOSS.register('DiceTopKLoss', DiceTopKLoss) 45 | 46 | SIAMESE_LOSS.register('ContrastiveLoss', ContrastiveLoss) 47 | SIAMESE_LOSS.register('ContrastiveCELoss', ContrastiveCELoss) 48 | SIAMESE_LOSS.register('ContrastiveBCELoss', ContrastiveBCELoss) 49 | 50 | SELFLEARNING_LOSS.register('MSE', torch.nn.MSELoss) 51 | 52 | MULTITASK_LOSS.register("CombinationLoss", CombinationLoss) 53 | -------------------------------------------------------------------------------- /strix/models/rcnn/csrc/ROIPool.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "cpu/vision.h" 5 | 6 | #ifdef WITH_CUDA 7 | #include "cuda/vision.h" 8 | #endif 9 | 10 | 11 | std::tuple ROIPool_forward(const at::Tensor& input, 12 | const at::Tensor& rois, 13 | const float spatial_scale, 14 | const int pooled_height, 15 | const int pooled_width) { 16 | if (input.type().is_cuda()) { 17 | #ifdef WITH_CUDA 18 | return ROIPool_forward_cuda(input, rois, spatial_scale, pooled_height, pooled_width); 19 | #else 20 | AT_ERROR("Not compiled with GPU support"); 21 | #endif 22 | } 23 | AT_ERROR("Not implemented on the CPU"); 24 | } 25 | 26 | at::Tensor ROIPool_backward(const at::Tensor& grad, 27 | const at::Tensor& input, 28 | const at::Tensor& rois, 29 | const at::Tensor& argmax, 30 | const float spatial_scale, 31 | const int pooled_height, 32 | const int pooled_width, 33 | const int batch_size, 34 | const int channels, 35 | const int height, 36 | const int width) { 37 | if (grad.type().is_cuda()) { 38 | #ifdef WITH_CUDA 39 | return ROIPool_backward_cuda(grad, input, rois, argmax, spatial_scale, pooled_height, pooled_width, batch_size, channels, height, width); 40 | #else 41 | AT_ERROR("Not compiled with GPU support"); 42 | #endif 43 | } 44 | AT_ERROR("Not implemented on the CPU"); 45 | } 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /strix/models/rcnn/csrc/ROIAlign.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "cpu/vision.h" 5 | 6 | #ifdef WITH_CUDA 7 | #include "cuda/vision.h" 8 | #endif 9 | 10 | // Interface for Python 11 | at::Tensor ROIAlign_forward(const at::Tensor& input, 12 | const at::Tensor& rois, 13 | const float spatial_scale, 14 | const int pooled_height, 15 | const int pooled_width, 16 | const int sampling_ratio) { 17 | if (input.type().is_cuda()) { 18 | #ifdef WITH_CUDA 19 | return ROIAlign_forward_cuda(input, rois, spatial_scale, pooled_height, pooled_width, sampling_ratio); 20 | #else 21 | AT_ERROR("Not compiled with GPU support"); 22 | #endif 23 | } 24 | return ROIAlign_forward_cpu(input, rois, spatial_scale, pooled_height, pooled_width, sampling_ratio); 25 | } 26 | 27 | at::Tensor ROIAlign_backward(const at::Tensor& grad, 28 | const at::Tensor& rois, 29 | const float spatial_scale, 30 | const int pooled_height, 31 | const int pooled_width, 32 | const int batch_size, 33 | const int channels, 34 | const int height, 35 | const int width, 36 | const int sampling_ratio) { 37 | if (grad.type().is_cuda()) { 38 | #ifdef WITH_CUDA 39 | return ROIAlign_backward_cuda(grad, rois, spatial_scale, pooled_height, pooled_width, batch_size, channels, height, width, sampling_ratio); 40 | #else 41 | AT_ERROR("Not compiled with GPU support"); 42 | #endif 43 | } 44 | AT_ERROR("Not implemented on the CPU"); 45 | } 46 | 47 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/rpn/utils.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | """ 3 | Utility functions minipulating the prediction layers 4 | """ 5 | 6 | from ..utils import cat 7 | 8 | import torch 9 | 10 | def permute_and_flatten(layer, N, A, C, H, W): 11 | layer = layer.view(N, -1, C, H, W) 12 | layer = layer.permute(0, 3, 4, 1, 2) 13 | layer = layer.reshape(N, -1, C) 14 | return layer 15 | 16 | 17 | def concat_box_prediction_layers(box_cls, box_regression): 18 | box_cls_flattened = [] 19 | box_regression_flattened = [] 20 | # for each feature level, permute the outputs to make them be in the 21 | # same format as the labels. Note that the labels are computed for 22 | # all feature levels concatenated, so we keep the same representation 23 | # for the objectness and the box_regression 24 | for box_cls_per_level, box_regression_per_level in zip( 25 | box_cls, box_regression 26 | ): 27 | N, AxC, H, W = box_cls_per_level.shape 28 | Ax4 = box_regression_per_level.shape[1] 29 | A = Ax4 // 4 30 | C = AxC // A 31 | box_cls_per_level = permute_and_flatten( 32 | box_cls_per_level, N, A, C, H, W 33 | ) 34 | box_cls_flattened.append(box_cls_per_level) 35 | 36 | box_regression_per_level = permute_and_flatten( 37 | box_regression_per_level, N, A, 4, H, W 38 | ) 39 | box_regression_flattened.append(box_regression_per_level) 40 | # concatenate on the first dimension (representing the feature levels), to 41 | # take into account the way the labels were generated (with all feature maps 42 | # being concatenated as well) 43 | box_cls = cat(box_cls_flattened, dim=1).reshape(-1, C) 44 | box_regression = cat(box_regression_flattened, dim=1).reshape(-1, 4) 45 | return box_cls, box_regression 46 | -------------------------------------------------------------------------------- /strix/misc/configs/gn_baselines/e2e_mask_rcnn_R_50_FPN_1x_gn.yaml: -------------------------------------------------------------------------------- 1 | INPUT: 2 | MIN_SIZE_TRAIN: (800,) 3 | MAX_SIZE_TRAIN: 1333 4 | MIN_SIZE_TEST: 800 5 | MAX_SIZE_TEST: 1333 6 | MODEL: 7 | META_ARCHITECTURE: "GeneralizedRCNN" 8 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50-GN" 9 | BACKBONE: 10 | CONV_BODY: "R-50-FPN" 11 | RESNETS: # use GN for backbone 12 | BACKBONE_OUT_CHANNELS: 256 13 | STRIDE_IN_1X1: False 14 | TRANS_FUNC: "BottleneckWithGN" 15 | STEM_FUNC: "StemWithGN" 16 | FPN: 17 | USE_GN: True # use GN for FPN 18 | RPN: 19 | USE_FPN: True 20 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 21 | PRE_NMS_TOP_N_TRAIN: 2000 22 | PRE_NMS_TOP_N_TEST: 1000 23 | POST_NMS_TOP_N_TEST: 1000 24 | FPN_POST_NMS_TOP_N_TEST: 1000 25 | ROI_HEADS: 26 | USE_FPN: True 27 | BATCH_SIZE_PER_IMAGE: 512 28 | POSITIVE_FRACTION: 0.25 29 | ROI_BOX_HEAD: 30 | USE_GN: True # use GN for bbox head 31 | POOLER_RESOLUTION: 7 32 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 33 | POOLER_SAMPLING_RATIO: 2 34 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 35 | PREDICTOR: "FPNPredictor" 36 | ROI_MASK_HEAD: 37 | USE_GN: True # use GN for mask head 38 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 39 | CONV_LAYERS: (256, 256, 256, 256) 40 | FEATURE_EXTRACTOR: "MaskRCNNFPNFeatureExtractor" 41 | PREDICTOR: "MaskRCNNC4Predictor" 42 | POOLER_RESOLUTION: 14 43 | POOLER_SAMPLING_RATIO: 2 44 | RESOLUTION: 28 45 | SHARE_BOX_FEATURE_EXTRACTOR: False 46 | MASK_ON: True 47 | DATASETS: 48 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 49 | TEST: ("coco_2014_minival",) 50 | DATALOADER: 51 | SIZE_DIVISIBILITY: 32 52 | SOLVER: 53 | # Assume 8 gpus 54 | BASE_LR: 0.02 55 | WEIGHT_DECAY: 0.0001 56 | STEPS: (60000, 80000) 57 | MAX_ITER: 90000 58 | IMS_PER_BATCH: 16 59 | TEST: 60 | IMS_PER_BATCH: 8 61 | -------------------------------------------------------------------------------- /strix/misc/configs/gn_baselines/scratch_e2e_mask_rcnn_R_50_FPN_3x_gn.yaml: -------------------------------------------------------------------------------- 1 | INPUT: 2 | MIN_SIZE_TRAIN: (800,) 3 | MAX_SIZE_TRAIN: 1333 4 | MIN_SIZE_TEST: 800 5 | MAX_SIZE_TEST: 1333 6 | MODEL: 7 | META_ARCHITECTURE: "GeneralizedRCNN" 8 | WEIGHT: "" # no pretrained model 9 | BACKBONE: 10 | CONV_BODY: "R-50-FPN" 11 | FREEZE_CONV_BODY_AT: 0 # finetune all layers 12 | RESNETS: # use GN for backbone 13 | BACKBONE_OUT_CHANNELS: 256 14 | STRIDE_IN_1X1: False 15 | TRANS_FUNC: "BottleneckWithGN" 16 | STEM_FUNC: "StemWithGN" 17 | FPN: 18 | USE_GN: True # use GN for FPN 19 | RPN: 20 | USE_FPN: True 21 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 22 | PRE_NMS_TOP_N_TRAIN: 2000 23 | PRE_NMS_TOP_N_TEST: 1000 24 | POST_NMS_TOP_N_TEST: 1000 25 | FPN_POST_NMS_TOP_N_TEST: 1000 26 | ROI_HEADS: 27 | USE_FPN: True 28 | BATCH_SIZE_PER_IMAGE: 512 29 | POSITIVE_FRACTION: 0.25 30 | ROI_BOX_HEAD: 31 | USE_GN: True # use GN for bbox head 32 | POOLER_RESOLUTION: 7 33 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 34 | POOLER_SAMPLING_RATIO: 2 35 | FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor" 36 | PREDICTOR: "FPNPredictor" 37 | ROI_MASK_HEAD: 38 | USE_GN: True # use GN for mask head 39 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 40 | CONV_LAYERS: (256, 256, 256, 256) 41 | FEATURE_EXTRACTOR: "MaskRCNNFPNFeatureExtractor" 42 | PREDICTOR: "MaskRCNNC4Predictor" 43 | POOLER_RESOLUTION: 14 44 | POOLER_SAMPLING_RATIO: 2 45 | RESOLUTION: 28 46 | SHARE_BOX_FEATURE_EXTRACTOR: False 47 | MASK_ON: True 48 | DATASETS: 49 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 50 | TEST: ("coco_2014_minival",) 51 | DATALOADER: 52 | SIZE_DIVISIBILITY: 32 53 | SOLVER: 54 | # Assume 8 gpus 55 | BASE_LR: 0.02 56 | WEIGHT_DECAY: 0.0001 57 | STEPS: (210000, 250000) 58 | MAX_ITER: 270000 59 | IMS_PER_BATCH: 16 60 | TEST: 61 | IMS_PER_BATCH: 8 62 | -------------------------------------------------------------------------------- /strix/misc/configs/gn_baselines/e2e_mask_rcnn_R_50_FPN_Xconv1fc_1x_gn.yaml: -------------------------------------------------------------------------------- 1 | INPUT: 2 | MIN_SIZE_TRAIN: (800,) 3 | MAX_SIZE_TRAIN: 1333 4 | MIN_SIZE_TEST: 800 5 | MAX_SIZE_TEST: 1333 6 | MODEL: 7 | META_ARCHITECTURE: "GeneralizedRCNN" 8 | WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50-GN" 9 | BACKBONE: 10 | CONV_BODY: "R-50-FPN" 11 | RESNETS: # use GN for backbone 12 | BACKBONE_OUT_CHANNELS: 256 13 | STRIDE_IN_1X1: False 14 | TRANS_FUNC: "BottleneckWithGN" 15 | STEM_FUNC: "StemWithGN" 16 | FPN: 17 | USE_GN: True # use GN for FPN 18 | RPN: 19 | USE_FPN: True 20 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 21 | PRE_NMS_TOP_N_TRAIN: 2000 22 | PRE_NMS_TOP_N_TEST: 1000 23 | POST_NMS_TOP_N_TEST: 1000 24 | FPN_POST_NMS_TOP_N_TEST: 1000 25 | ROI_HEADS: 26 | USE_FPN: True 27 | BATCH_SIZE_PER_IMAGE: 512 28 | POSITIVE_FRACTION: 0.25 29 | ROI_BOX_HEAD: 30 | USE_GN: True # use GN for bbox head 31 | POOLER_RESOLUTION: 7 32 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 33 | POOLER_SAMPLING_RATIO: 2 34 | CONV_HEAD_DIM: 256 35 | NUM_STACKED_CONVS: 4 36 | FEATURE_EXTRACTOR: "FPNXconv1fcFeatureExtractor" 37 | PREDICTOR: "FPNPredictor" 38 | ROI_MASK_HEAD: 39 | USE_GN: True # use GN for mask head 40 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 41 | CONV_LAYERS: (256, 256, 256, 256) 42 | FEATURE_EXTRACTOR: "MaskRCNNFPNFeatureExtractor" 43 | PREDICTOR: "MaskRCNNC4Predictor" 44 | POOLER_RESOLUTION: 14 45 | POOLER_SAMPLING_RATIO: 2 46 | RESOLUTION: 28 47 | SHARE_BOX_FEATURE_EXTRACTOR: False 48 | MASK_ON: True 49 | DATASETS: 50 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 51 | TEST: ("coco_2014_minival",) 52 | DATALOADER: 53 | SIZE_DIVISIBILITY: 32 54 | SOLVER: 55 | # Assume 8 gpus 56 | BASE_LR: 0.02 57 | WEIGHT_DECAY: 0.0001 58 | STEPS: (60000, 80000) 59 | MAX_ITER: 90000 60 | IMS_PER_BATCH: 16 61 | TEST: 62 | IMS_PER_BATCH: 8 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | *.pyc 6 | 7 | # Saved results 8 | runs/ 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | wheels/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | MANIFEST 31 | strix.egg-info 32 | 33 | # PyInstaller 34 | # Usually these files are written by a python script from a template 35 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 36 | *.manifest 37 | *.spec 38 | 39 | # Installer logs 40 | pip-log.txt 41 | pip-delete-this-directory.txt 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .coverage 47 | .coverage.* 48 | .cache 49 | nosetests.xml 50 | coverage.xml 51 | *.cover 52 | .hypothesis/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | .static_storage/ 61 | .media/ 62 | local_settings.py 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # pyenv 81 | .python-version 82 | 83 | # celery beat schedule file 84 | celerybeat-schedule 85 | 86 | # SageMath parsed files 87 | *.sage.py 88 | 89 | # Environments 90 | .env 91 | .venv 92 | env/ 93 | venv/ 94 | ENV/ 95 | env.bak/ 96 | venv.bak/ 97 | 98 | # Spyder project settings 99 | .spyderproject 100 | .spyproject 101 | 102 | # Rope project settings 103 | .ropeproject 104 | .vscode 105 | 106 | # mkdocs documentation 107 | /site 108 | 109 | 110 | # my extension 111 | *.nii.gz 112 | *.json 113 | *.list 114 | *.zip 115 | strix/tmp.py 116 | strix_configures.cfg 117 | *.code-workspace 118 | -------------------------------------------------------------------------------- /strix/tests/test_TensoboardDumper: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import tempfile 4 | import unittest 5 | 6 | from ignite.engine import Engine, Events 7 | from torch.utils.tensorboard import SummaryWriter 8 | 9 | from monai.handlers import TensorBoardStatsHandler 10 | from strix.models.cnn import * 11 | from monai_ex.handlers import TensorboardDumper 12 | 13 | 14 | class TestTensorboardDumper(unittest.TestCase): 15 | def test_image_saver(self): 16 | pass 17 | 18 | def test_summary_plot(self): 19 | with tempfile.TemporaryDirectory() as tempdir: 20 | # set up engine 21 | def _train_func(engine, batch): 22 | return batch + 1.0 23 | 24 | engine = Engine(_train_func) 25 | 26 | # set up dummy metric 27 | @engine.on(Events.EPOCH_COMPLETED) 28 | def _update_metric(engine): 29 | current_metric = engine.state.metrics.get("acc", 0.1) 30 | engine.state.metrics["acc"] = current_metric + 0.1 31 | 32 | # set up testing handler 33 | writer = SummaryWriter(log_dir=tempdir) 34 | stats_handler = TensorBoardStatsHandler( 35 | writer, 36 | output_transform=lambda x: {"loss": x}, 37 | global_epoch_transform=lambda x: x, 38 | ) 39 | stats_handler.attach(engine) 40 | 41 | dump_handler = TensorboardDumper(log_dir=tempdir, epoch_level=True) 42 | dump_handler.attach(engine) 43 | 44 | engine.run(range(10), max_epochs=10) 45 | writer.close() 46 | # check logging output 47 | print("Saved files:", os.listdir(tempdir)) 48 | shutil.copyfile( 49 | os.path.join(tempdir, "summary.png"), 50 | "/homes/clwang/test_tb_summary.png", 51 | ) 52 | self.assertTrue(len(os.listdir(tempdir)) == 2) 53 | 54 | 55 | if __name__ == "__main__": 56 | unittest.main() -------------------------------------------------------------------------------- /strix/misc/configs/gn_baselines/scratch_e2e_mask_rcnn_R_50_FPN_Xconv1fc_3x_gn.yaml: -------------------------------------------------------------------------------- 1 | INPUT: 2 | MIN_SIZE_TRAIN: (800,) 3 | MAX_SIZE_TRAIN: 1333 4 | MIN_SIZE_TEST: 800 5 | MAX_SIZE_TEST: 1333 6 | MODEL: 7 | META_ARCHITECTURE: "GeneralizedRCNN" 8 | WEIGHT: "" # no pretrained model 9 | BACKBONE: 10 | CONV_BODY: "R-50-FPN" 11 | FREEZE_CONV_BODY_AT: 0 # finetune all layers 12 | RESNETS: # use GN for backbone 13 | BACKBONE_OUT_CHANNELS: 256 14 | STRIDE_IN_1X1: False 15 | TRANS_FUNC: "BottleneckWithGN" 16 | STEM_FUNC: "StemWithGN" 17 | FPN: 18 | USE_GN: True # use GN for FPN 19 | RPN: 20 | USE_FPN: True 21 | ANCHOR_STRIDE: (4, 8, 16, 32, 64) 22 | PRE_NMS_TOP_N_TRAIN: 2000 23 | PRE_NMS_TOP_N_TEST: 1000 24 | POST_NMS_TOP_N_TEST: 1000 25 | FPN_POST_NMS_TOP_N_TEST: 1000 26 | ROI_HEADS: 27 | USE_FPN: True 28 | BATCH_SIZE_PER_IMAGE: 512 29 | POSITIVE_FRACTION: 0.25 30 | ROI_BOX_HEAD: 31 | USE_GN: True # use GN for bbox head 32 | POOLER_RESOLUTION: 7 33 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 34 | POOLER_SAMPLING_RATIO: 2 35 | CONV_HEAD_DIM: 256 36 | NUM_STACKED_CONVS: 4 37 | FEATURE_EXTRACTOR: "FPNXconv1fcFeatureExtractor" 38 | PREDICTOR: "FPNPredictor" 39 | ROI_MASK_HEAD: 40 | USE_GN: True # use GN for mask head 41 | POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125) 42 | CONV_LAYERS: (256, 256, 256, 256) 43 | FEATURE_EXTRACTOR: "MaskRCNNFPNFeatureExtractor" 44 | PREDICTOR: "MaskRCNNC4Predictor" 45 | POOLER_RESOLUTION: 14 46 | POOLER_SAMPLING_RATIO: 2 47 | RESOLUTION: 28 48 | SHARE_BOX_FEATURE_EXTRACTOR: False 49 | MASK_ON: True 50 | DATASETS: 51 | TRAIN: ("coco_2014_train", "coco_2014_valminusminival") 52 | TEST: ("coco_2014_minival",) 53 | DATALOADER: 54 | SIZE_DIVISIBILITY: 32 55 | SOLVER: 56 | # Assume 8 gpus 57 | BASE_LR: 0.02 58 | WEIGHT_DECAY: 0.0001 59 | STEPS: (210000, 250000) 60 | MAX_ITER: 270000 61 | IMS_PER_BATCH: 16 62 | TEST: 63 | IMS_PER_BATCH: 8 64 | -------------------------------------------------------------------------------- /strix/configures/config.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pathlib import Path 3 | from configparser import ConfigParser 4 | 5 | 6 | DEFAULT_STRIX_CONFIG = { 7 | "MODE": "dev", # release 8 | "CONFIG_FNAME": "strix_configures.cfg", 9 | "CACHE_DIR": str(Path.home() / "Strix"), 10 | "OUTPUT_DIR": str(Path.home() / "Strix" / "strix_exp"), 11 | "EXTERNAL_DATASET_DIR": str(Path.home() / "Strix" / "strix_datasets"), 12 | "EXTERNAL_NETWORK_DIR": str(Path.home() / "Strix" / "strix_networks"), 13 | } 14 | 15 | 16 | def __config_to_dict(config: ConfigParser): 17 | d = dict(config._sections) 18 | for k in d: 19 | d[k] = dict(d[k]) 20 | return d 21 | 22 | 23 | def init(add_path=True): 24 | global _config_dict 25 | 26 | try: 27 | fname = DEFAULT_STRIX_CONFIG["CONFIG_FNAME"] 28 | cfg_file = Path(__file__).parent.joinpath(fname) 29 | conf = ConfigParser() 30 | conf.optionxform = str 31 | 32 | conf.read(cfg_file) 33 | _config_dict = __config_to_dict(conf) 34 | except FileNotFoundError as e: 35 | raise FileNotFoundError(f"Missing config file {cfg_file}") 36 | except Exception as e: 37 | raise Exception(f"Error occured during reading config: {e}") 38 | 39 | if add_path: 40 | sys.path.append(_config_dict["STRIX_CONFIG"]["EXTERNAL_DATASET_DIR"]) 41 | sys.path.append(_config_dict["STRIX_CONFIG"]["EXTERNAL_NETWORK_DIR"]) 42 | 43 | 44 | def get_cfg(section_name, keyword): 45 | return _config_dict[section_name][keyword.upper()] 46 | 47 | 48 | def get_strix_cfg(keyword): 49 | return _config_dict["STRIX_CONFIG"][keyword.upper()] 50 | 51 | 52 | def get_key(key_name): 53 | return _config_dict["CUSTOM_KEYS"][key_name.upper()] 54 | 55 | 56 | def set_key(key_name, value): 57 | _config_dict["CUSTOM_KEYS"][key_name.upper()] = value 58 | 59 | 60 | def get_keys_dict(): 61 | return dict(_config_dict.get("CUSTOM_KEYS")) 62 | 63 | 64 | def get_keys_list(): 65 | return list(_config_dict.get("CUSTOM_KEYS").values()) -------------------------------------------------------------------------------- /strix/models/rcnn/solver/lr_scheduler.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from bisect import bisect_right 3 | 4 | import torch 5 | 6 | 7 | # FIXME ideally this would be achieved with a CombinedLRScheduler, 8 | # separating MultiStepLR with WarmupLR 9 | # but the current LRScheduler design doesn't allow it 10 | class WarmupMultiStepLR(torch.optim.lr_scheduler._LRScheduler): 11 | def __init__( 12 | self, 13 | optimizer, 14 | milestones, 15 | gamma=0.1, 16 | warmup_factor=1.0 / 3, 17 | warmup_iters=500, 18 | warmup_method="linear", 19 | last_epoch=-1, 20 | ): 21 | if not list(milestones) == sorted(milestones): 22 | raise ValueError( 23 | "Milestones should be a list of" " increasing integers. Got {}", 24 | milestones, 25 | ) 26 | 27 | if warmup_method not in ("constant", "linear"): 28 | raise ValueError( 29 | "Only 'constant' or 'linear' warmup_method accepted" 30 | "got {}".format(warmup_method) 31 | ) 32 | self.milestones = milestones 33 | self.gamma = gamma 34 | self.warmup_factor = warmup_factor 35 | self.warmup_iters = warmup_iters 36 | self.warmup_method = warmup_method 37 | super(WarmupMultiStepLR, self).__init__(optimizer, last_epoch) 38 | 39 | def get_lr(self): 40 | warmup_factor = 1 41 | if self.last_epoch < self.warmup_iters: 42 | if self.warmup_method == "constant": 43 | warmup_factor = self.warmup_factor 44 | elif self.warmup_method == "linear": 45 | alpha = float(self.last_epoch) / self.warmup_iters 46 | warmup_factor = self.warmup_factor * (1 - alpha) + alpha 47 | return [ 48 | base_lr 49 | * warmup_factor 50 | * self.gamma ** bisect_right(self.milestones, self.last_epoch) 51 | for base_lr in self.base_lrs 52 | ] 53 | -------------------------------------------------------------------------------- /strix/models/rcnn/layers/iou_loss.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | 4 | 5 | class IOULoss(nn.Module): 6 | def __init__(self, loc_loss_type): 7 | super(IOULoss, self).__init__() 8 | self.loc_loss_type = loc_loss_type 9 | 10 | def forward(self, pred, target, weight=None): 11 | pred_left = pred[:, 0] 12 | pred_top = pred[:, 1] 13 | pred_right = pred[:, 2] 14 | pred_bottom = pred[:, 3] 15 | 16 | target_left = target[:, 0] 17 | target_top = target[:, 1] 18 | target_right = target[:, 2] 19 | target_bottom = target[:, 3] 20 | 21 | target_area = (target_left + target_right) * \ 22 | (target_top + target_bottom) 23 | pred_area = (pred_left + pred_right) * \ 24 | (pred_top + pred_bottom) 25 | 26 | w_intersect = torch.min(pred_left, target_left) + torch.min(pred_right, target_right) 27 | g_w_intersect = torch.max(pred_left, target_left) + torch.max( 28 | pred_right, target_right) 29 | h_intersect = torch.min(pred_bottom, target_bottom) + torch.min(pred_top, target_top) 30 | g_h_intersect = torch.max(pred_bottom, target_bottom) + torch.max(pred_top, target_top) 31 | ac_uion = g_w_intersect * g_h_intersect + 1e-7 32 | area_intersect = w_intersect * h_intersect 33 | area_union = target_area + pred_area - area_intersect 34 | ious = (area_intersect + 1.0) / (area_union + 1.0) 35 | gious = ious - (ac_uion - area_union) / ac_uion 36 | if self.loc_loss_type == 'iou': 37 | losses = -torch.log(ious) 38 | elif self.loc_loss_type == 'linear_iou': 39 | losses = 1 - ious 40 | elif self.loc_loss_type == 'giou': 41 | losses = 1 - gious 42 | else: 43 | raise NotImplementedError 44 | 45 | if weight is not None and weight.sum() > 0: 46 | return (losses * weight).sum() / weight.sum() 47 | else: 48 | assert losses.numel() != 0 49 | return losses.mean() 50 | -------------------------------------------------------------------------------- /strix/tests/test_click_remeber_last.py: -------------------------------------------------------------------------------- 1 | import click 2 | import pytest 3 | from functools import partial 4 | from strix.utilities.click_callbacks import NumericChoice as Choice, dump_params 5 | from strix.utilities.click import OptionEx, CommandEx 6 | from strix.utilities.utils import get_items 7 | 8 | option = partial(click.option, cls=OptionEx) 9 | command = partial(click.command, cls=CommandEx) 10 | 11 | def test_prompt_remember_last_choice(runner, tmp_path): 12 | @command() 13 | @option( 14 | "-g", type=Choice(["none", "day", "week", "month"]), prompt=True 15 | ) 16 | def cli_normal_case(g): 17 | pass 18 | 19 | out_path = tmp_path/'history.json' 20 | 21 | @command() 22 | @option("-d", is_flag=True, default=True) 23 | @option("-g", type=Choice(["none", "day", "week", "month"]), default='day', prompt=True, show_default=True) 24 | @option("-dump", type=bool, default=True, callback=partial(dump_params, output_path=out_path)) 25 | def cli_remeber_case(d, g): 26 | pass 27 | 28 | result = runner.invoke(cli_normal_case, [], input="none") 29 | assert "(1: none, 2: day, 3: week, 4: month)" in result.output 30 | 31 | result = runner.invoke(cli_remeber_case, [], input="week") 32 | print(result.output) 33 | assert "(1: none, 2: day, 3: week, 4: month) [day]:" in result.output 34 | 35 | print(get_items(out_path, allow_filenotfound=True)) 36 | 37 | @pytest.mark.parametrize('prompt', [True, False]) 38 | def test_remeber_options(prompt, runner, tmp_path): 39 | @command(context_settings={ 40 | "prompt_in_default_map": prompt, 41 | "default_map": {"g": "day"} 42 | }) 43 | @option("-g", type=Choice(["none", "day", "week", "month"]), default='day', prompt=True, show_default=True) 44 | def cli_remeber_case2(g): 45 | pass 46 | 47 | result = runner.invoke(cli_remeber_case2, [], input="none") 48 | print(result.output) 49 | if prompt: 50 | assert "(1: none, 2: day, 3: week, 4: month) [day]: none" in result.output 51 | else: 52 | assert len(result.output) == 0 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /strix/models/rcnn/layers/roi_pool.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import torch 3 | from torch import nn 4 | from torch.autograd import Function 5 | from torch.autograd.function import once_differentiable 6 | from torch.nn.modules.utils import _pair 7 | 8 | from strix.models.rcnn import _C 9 | 10 | 11 | class _ROIPool(Function): 12 | @staticmethod 13 | def forward(ctx, input, roi, output_size, spatial_scale): 14 | ctx.output_size = _pair(output_size) 15 | ctx.spatial_scale = spatial_scale 16 | ctx.input_shape = input.size() 17 | output, argmax = _C.roi_pool_forward( 18 | input, roi, spatial_scale, output_size[0], output_size[1] 19 | ) 20 | ctx.save_for_backward(input, roi, argmax) 21 | return output 22 | 23 | @staticmethod 24 | @once_differentiable 25 | def backward(ctx, grad_output): 26 | input, rois, argmax = ctx.saved_tensors 27 | output_size = ctx.output_size 28 | spatial_scale = ctx.spatial_scale 29 | bs, ch, h, w = ctx.input_shape 30 | grad_input = _C.roi_pool_backward( 31 | grad_output, 32 | input, 33 | rois, 34 | argmax, 35 | spatial_scale, 36 | output_size[0], 37 | output_size[1], 38 | bs, 39 | ch, 40 | h, 41 | w, 42 | ) 43 | return grad_input, None, None, None 44 | 45 | 46 | roi_pool = _ROIPool.apply 47 | 48 | 49 | class ROIPool(nn.Module): 50 | def __init__(self, output_size, spatial_scale): 51 | super(ROIPool, self).__init__() 52 | self.output_size = output_size 53 | self.spatial_scale = spatial_scale 54 | 55 | def forward(self, input, rois): 56 | return roi_pool(input, rois, self.output_size, self.spatial_scale) 57 | 58 | def __repr__(self): 59 | tmpstr = self.__class__.__name__ + "(" 60 | tmpstr += "output_size=" + str(self.output_size) 61 | tmpstr += ", spatial_scale=" + str(self.spatial_scale) 62 | tmpstr += ")" 63 | return tmpstr 64 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/roi_heads/keypoint_head/roi_keypoint_feature_extractors.py: -------------------------------------------------------------------------------- 1 | from torch import nn 2 | from torch.nn import functional as F 3 | 4 | from strix.models.rcnn.modeling import registry 5 | from strix.models.rcnn.modeling.poolers import Pooler 6 | 7 | from strix.models.rcnn.layers import Conv2d 8 | 9 | 10 | @registry.ROI_KEYPOINT_FEATURE_EXTRACTORS.register("KeypointRCNNFeatureExtractor") 11 | class KeypointRCNNFeatureExtractor(nn.Module): 12 | def __init__(self, cfg, in_channels): 13 | super(KeypointRCNNFeatureExtractor, self).__init__() 14 | 15 | resolution = cfg.MODEL.ROI_KEYPOINT_HEAD.POOLER_RESOLUTION 16 | scales = cfg.MODEL.ROI_KEYPOINT_HEAD.POOLER_SCALES 17 | sampling_ratio = cfg.MODEL.ROI_KEYPOINT_HEAD.POOLER_SAMPLING_RATIO 18 | pooler = Pooler( 19 | output_size=(resolution, resolution), 20 | scales=scales, 21 | sampling_ratio=sampling_ratio, 22 | ) 23 | self.pooler = pooler 24 | 25 | input_features = in_channels 26 | layers = cfg.MODEL.ROI_KEYPOINT_HEAD.CONV_LAYERS 27 | next_feature = input_features 28 | self.blocks = [] 29 | for layer_idx, layer_features in enumerate(layers, 1): 30 | layer_name = "conv_fcn{}".format(layer_idx) 31 | module = Conv2d(next_feature, layer_features, 3, stride=1, padding=1) 32 | nn.init.kaiming_normal_(module.weight, mode="fan_out", nonlinearity="relu") 33 | nn.init.constant_(module.bias, 0) 34 | self.add_module(layer_name, module) 35 | next_feature = layer_features 36 | self.blocks.append(layer_name) 37 | self.out_channels = layer_features 38 | 39 | def forward(self, x, proposals): 40 | x = self.pooler(x, proposals) 41 | for layer_name in self.blocks: 42 | x = F.relu(getattr(self, layer_name)(x)) 43 | return x 44 | 45 | 46 | def make_roi_keypoint_feature_extractor(cfg, in_channels): 47 | func = registry.ROI_KEYPOINT_FEATURE_EXTRACTORS[ 48 | cfg.MODEL.ROI_KEYPOINT_HEAD.FEATURE_EXTRACTOR 49 | ] 50 | return func(cfg, in_channels) 51 | -------------------------------------------------------------------------------- /strix/models/rcnn/utils/metric_logger.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from collections import defaultdict 3 | from collections import deque 4 | 5 | import torch 6 | 7 | 8 | class SmoothedValue(object): 9 | """Track a series of values and provide access to smoothed values over a 10 | window or the global series average. 11 | """ 12 | 13 | def __init__(self, window_size=20): 14 | self.deque = deque(maxlen=window_size) 15 | self.series = [] 16 | self.total = 0.0 17 | self.count = 0 18 | 19 | def update(self, value): 20 | self.deque.append(value) 21 | self.series.append(value) 22 | self.count += 1 23 | self.total += value 24 | 25 | @property 26 | def median(self): 27 | d = torch.tensor(list(self.deque)) 28 | return d.median().item() 29 | 30 | @property 31 | def avg(self): 32 | d = torch.tensor(list(self.deque)) 33 | return d.mean().item() 34 | 35 | @property 36 | def global_avg(self): 37 | return self.total / self.count 38 | 39 | 40 | class MetricLogger(object): 41 | def __init__(self, delimiter="\t"): 42 | self.meters = defaultdict(SmoothedValue) 43 | self.delimiter = delimiter 44 | 45 | def update(self, **kwargs): 46 | for k, v in kwargs.items(): 47 | if isinstance(v, torch.Tensor): 48 | v = v.item() 49 | assert isinstance(v, (float, int)) 50 | self.meters[k].update(v) 51 | 52 | def __getattr__(self, attr): 53 | if attr in self.meters: 54 | return self.meters[attr] 55 | if attr in self.__dict__: 56 | return self.__dict__[attr] 57 | raise AttributeError("'{}' object has no attribute '{}'".format( 58 | type(self).__name__, attr)) 59 | 60 | def __str__(self): 61 | loss_str = [] 62 | for name, meter in self.meters.items(): 63 | loss_str.append( 64 | "{}: {:.4f} ({:.4f})".format(name, meter.median, meter.global_avg) 65 | ) 66 | return self.delimiter.join(loss_str) 67 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = strix 3 | author = Chenglong Wang 4 | author_email = clwang@phy.ecnu.edu.cn 5 | url = 6 | description = A Medical Deep Learning Platform 7 | long_description = file:readme.md 8 | long_description_content_type = text/markdown; charset=UTF-8 9 | platforms = OS Independent 10 | license = GNU General Public License 11 | license_files = 12 | LICENSE 13 | project_urls = 14 | Documentation=https://google.com/ 15 | Bug Tracker=https://github.com/Project-Strix/Strix/issues 16 | Source Code=https://github.com/Project-Strix/Strix 17 | 18 | [options] 19 | python_requires = >= 3.7 20 | # for compiling and develop setup only 21 | # no need to specify the versions so that we could 22 | # compile for multiple targeted versions. 23 | setup_requires = 24 | torch 25 | ninja 26 | install_requires = 27 | torch>=1.7 28 | numpy>=1.17 29 | monai==0.8.0 30 | monai_ex==0.1.0 31 | tb-nightly 32 | click 33 | tqdm>=4.47.0 34 | scikit-image>=0.14 35 | scipy 36 | numpy 37 | scikit-learn 38 | nibabel 39 | pytorch-ignite==0.4.7 40 | utils_cw 41 | pyyaml 42 | matplotlib 43 | torchvision 44 | pillow!=8.3.0 45 | 46 | [options.extras_require] 47 | pandas = 48 | pandas 49 | nni = 50 | nni 51 | 52 | [flake8] 53 | select = B,C,E,F,N,P,T4,W,B9 54 | max_line_length = 120 55 | # C408 ignored because we like the dict keyword argument syntax 56 | # E501 is not flexible enough, we're using B950 instead 57 | ignore = 58 | E203 59 | E501 60 | E741 61 | W503 62 | W504 63 | C408 64 | N812 # lowercase 'torch.nn.functional' imported as non lowercase 'F' 65 | per_file_ignores = __init__.py: F401, __main__.py: F401 66 | exclude = *.pyi,.git,.eggs,strix/_version.py,versioneer.py,venv,.venv,_version.py 67 | 68 | [isort] 69 | known_first_party = strix 70 | profile = black 71 | line_length = 120 72 | skip = .git, .eggs, venv, .venv, versioneer.py, _version.py, conf.py, strix/__init__.py 73 | skip_glob = *.pyi 74 | 75 | [versioneer] 76 | VCS = git 77 | style = pep440 78 | versionfile_source = strix/_version.py 79 | versionfile_build = strix/_version.py 80 | tag_prefix = 81 | parentdir_prefix = 82 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/roi_heads/keypoint_head/keypoint_head.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from .roi_keypoint_feature_extractors import make_roi_keypoint_feature_extractor 4 | from .roi_keypoint_predictors import make_roi_keypoint_predictor 5 | from .inference import make_roi_keypoint_post_processor 6 | from .loss import make_roi_keypoint_loss_evaluator 7 | 8 | 9 | class ROIKeypointHead(torch.nn.Module): 10 | def __init__(self, cfg, in_channels): 11 | super(ROIKeypointHead, self).__init__() 12 | self.cfg = cfg.clone() 13 | self.feature_extractor = make_roi_keypoint_feature_extractor(cfg, in_channels) 14 | self.predictor = make_roi_keypoint_predictor( 15 | cfg, self.feature_extractor.out_channels) 16 | self.post_processor = make_roi_keypoint_post_processor(cfg) 17 | self.loss_evaluator = make_roi_keypoint_loss_evaluator(cfg) 18 | 19 | def forward(self, features, proposals, targets=None): 20 | """ 21 | Arguments: 22 | features (list[Tensor]): feature-maps from possibly several levels 23 | proposals (list[BoxList]): proposal boxes 24 | targets (list[BoxList], optional): the ground-truth targets. 25 | 26 | Returns: 27 | x (Tensor): the result of the feature extractor 28 | proposals (list[BoxList]): during training, the original proposals 29 | are returned. During testing, the predicted boxlists are returned 30 | with the `mask` field set 31 | losses (dict[Tensor]): During training, returns the losses for the 32 | head. During testing, returns an empty dict. 33 | """ 34 | if self.training: 35 | with torch.no_grad(): 36 | proposals = self.loss_evaluator.subsample(proposals, targets) 37 | 38 | x = self.feature_extractor(features, proposals) 39 | kp_logits = self.predictor(x) 40 | 41 | if not self.training: 42 | result = self.post_processor(kp_logits, proposals) 43 | return x, result, {} 44 | 45 | loss_kp = self.loss_evaluator(proposals, kp_logits) 46 | 47 | return x, proposals, dict(loss_kp=loss_kp) 48 | 49 | 50 | def build_roi_keypoint_head(cfg, in_channels): 51 | return ROIKeypointHead(cfg, in_channels) 52 | -------------------------------------------------------------------------------- /strix/models/rcnn/layers/roi_align.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import torch 3 | from torch import nn 4 | from torch.autograd import Function 5 | from torch.autograd.function import once_differentiable 6 | from torch.nn.modules.utils import _pair 7 | 8 | from strix.models.rcnn import _C 9 | 10 | 11 | class _ROIAlign(Function): 12 | @staticmethod 13 | def forward(ctx, input, roi, output_size, spatial_scale, sampling_ratio): 14 | ctx.save_for_backward(roi) 15 | ctx.output_size = _pair(output_size) 16 | ctx.spatial_scale = spatial_scale 17 | ctx.sampling_ratio = sampling_ratio 18 | ctx.input_shape = input.size() 19 | output = _C.roi_align_forward( 20 | input, roi, spatial_scale, output_size[0], output_size[1], sampling_ratio 21 | ) 22 | return output 23 | 24 | @staticmethod 25 | @once_differentiable 26 | def backward(ctx, grad_output): 27 | rois, = ctx.saved_tensors 28 | output_size = ctx.output_size 29 | spatial_scale = ctx.spatial_scale 30 | sampling_ratio = ctx.sampling_ratio 31 | bs, ch, h, w = ctx.input_shape 32 | grad_input = _C.roi_align_backward( 33 | grad_output, 34 | rois, 35 | spatial_scale, 36 | output_size[0], 37 | output_size[1], 38 | bs, 39 | ch, 40 | h, 41 | w, 42 | sampling_ratio, 43 | ) 44 | return grad_input, None, None, None, None 45 | 46 | 47 | roi_align = _ROIAlign.apply 48 | 49 | 50 | class ROIAlign(nn.Module): 51 | def __init__(self, output_size, spatial_scale, sampling_ratio): 52 | super(ROIAlign, self).__init__() 53 | self.output_size = output_size 54 | self.spatial_scale = spatial_scale 55 | self.sampling_ratio = sampling_ratio 56 | 57 | def forward(self, input, rois): 58 | return roi_align( 59 | input, rois, self.output_size, self.spatial_scale, self.sampling_ratio 60 | ) 61 | 62 | def __repr__(self): 63 | tmpstr = self.__class__.__name__ + "(" 64 | tmpstr += "output_size=" + str(self.output_size) 65 | tmpstr += ", spatial_scale=" + str(self.spatial_scale) 66 | tmpstr += ", sampling_ratio=" + str(self.sampling_ratio) 67 | tmpstr += ")" 68 | return tmpstr 69 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/roi_heads/mask_head/roi_mask_predictors.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from torch import nn 3 | from torch.nn import functional as F 4 | 5 | from strix.models.rcnn.layers import Conv2d 6 | from strix.models.rcnn.layers import ConvTranspose2d 7 | from strix.models.rcnn.modeling import registry 8 | 9 | 10 | @registry.ROI_MASK_PREDICTOR.register("MaskRCNNC4Predictor") 11 | class MaskRCNNC4Predictor(nn.Module): 12 | def __init__(self, cfg, in_channels): 13 | super(MaskRCNNC4Predictor, self).__init__() 14 | num_classes = cfg.MODEL.ROI_BOX_HEAD.NUM_CLASSES 15 | dim_reduced = cfg.MODEL.ROI_MASK_HEAD.CONV_LAYERS[-1] 16 | num_inputs = in_channels 17 | 18 | self.conv5_mask = ConvTranspose2d(num_inputs, dim_reduced, 2, 2, 0) 19 | self.mask_fcn_logits = Conv2d(dim_reduced, num_classes, 1, 1, 0) 20 | 21 | for name, param in self.named_parameters(): 22 | if "bias" in name: 23 | nn.init.constant_(param, 0) 24 | elif "weight" in name: 25 | # Caffe2 implementation uses MSRAFill, which in fact 26 | # corresponds to kaiming_normal_ in PyTorch 27 | nn.init.kaiming_normal_(param, mode="fan_out", nonlinearity="relu") 28 | 29 | def forward(self, x): 30 | x = F.relu(self.conv5_mask(x)) 31 | return self.mask_fcn_logits(x) 32 | 33 | 34 | @registry.ROI_MASK_PREDICTOR.register("MaskRCNNConv1x1Predictor") 35 | class MaskRCNNConv1x1Predictor(nn.Module): 36 | def __init__(self, cfg, in_channels): 37 | super(MaskRCNNConv1x1Predictor, self).__init__() 38 | num_classes = cfg.MODEL.ROI_BOX_HEAD.NUM_CLASSES 39 | num_inputs = in_channels 40 | 41 | self.mask_fcn_logits = Conv2d(num_inputs, num_classes, 1, 1, 0) 42 | 43 | for name, param in self.named_parameters(): 44 | if "bias" in name: 45 | nn.init.constant_(param, 0) 46 | elif "weight" in name: 47 | # Caffe2 implementation uses MSRAFill, which in fact 48 | # corresponds to kaiming_normal_ in PyTorch 49 | nn.init.kaiming_normal_(param, mode="fan_out", nonlinearity="relu") 50 | 51 | def forward(self, x): 52 | return self.mask_fcn_logits(x) 53 | 54 | 55 | def make_roi_mask_predictor(cfg, in_channels): 56 | func = registry.ROI_MASK_PREDICTOR[cfg.MODEL.ROI_MASK_HEAD.PREDICTOR] 57 | return func(cfg, in_channels) 58 | -------------------------------------------------------------------------------- /strix/data_io/base_dataset/utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | from strix.configures import config as cfg 3 | 4 | def get_input_data(files_list, is_supervised, verbose, dataset_name=''): 5 | """ 6 | check input file_list format and existence. 7 | """ 8 | if verbose: 9 | print('Custom keys:', cfg.get_keys_dict()) 10 | 11 | input_data = [] 12 | for f in files_list: 13 | if is_supervised: 14 | if isinstance(f, (list, tuple)): # Recognize f as ['image','label'] 15 | assert os.path.exists(f[0]), f"File not exists: {f[0]}" 16 | assert os.path.exists(f[1]), f"File not exists: {f[1]}" 17 | input_data.append({cfg.get_key("IMAGE"): f[0], cfg.get_key("LABEL"): f[1]}) 18 | elif isinstance(f, dict): 19 | assert cfg.get_key("IMAGE") in f, f"File {f} doesn't contain image keyword '{cfg.get_key('IMAGE')}'" 20 | assert cfg.get_key("LABEL") in f, f"File {f} doesn't contain label keyword '{cfg.get_key('LABEL')}'" 21 | assert os.path.exists(f[cfg.get_key("IMAGE")]), f"File not exists: {f[cfg.get_key('IMAGE')]}" 22 | 23 | input_data.append( # filter the dict by keys defined in CustomKeys 24 | dict(filter(lambda k: k[0] in cfg.get_keys_list(), f.items())) 25 | ) 26 | 27 | else: 28 | raise ValueError( 29 | f"Not supported file_list format," 30 | f"Got {type(f)} in Supervised{dataset_name}" 31 | ) 32 | else: 33 | if isinstance(f, str): 34 | assert os.path.exists(f), f"Image file not exists: {f}" 35 | input_data.append({cfg.get_key('IMAGE'): f}) 36 | elif isinstance(f, dict): 37 | assert cfg.get_key('IMAGE') in f, f"File {f} doesn't contain image keyword '{cfg.get_key('IMAGE')}'" 38 | assert os.path.exists(f[cfg.get_key('IMAGE')]), f"File not exists: {f[cfg.get_key('IMAGE')]}" 39 | 40 | input_data.append( 41 | dict(filter(lambda k: k[0] in cfg.get_keys_list(), f.items())) 42 | ) 43 | else: 44 | raise ValueError( 45 | f"Not supported file_list format," 46 | f"Got {type(f)} in Unsupervised{dataset_name}" 47 | ) 48 | if verbose: 49 | print(f"Input data has {len(input_data)} items with keys: {list(input_data[0].keys())}") 50 | 51 | return input_data 52 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/detector/generalized_rcnn.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | """ 3 | Implements the Generalized R-CNN framework 4 | """ 5 | 6 | import torch 7 | from torch import nn 8 | 9 | from strix.models.rcnn.structures.image_list import to_image_list 10 | 11 | from ..backbone import build_backbone 12 | from ..rpn.rpn import build_rpn 13 | from ..roi_heads.roi_heads import build_roi_heads 14 | 15 | 16 | class GeneralizedRCNN(nn.Module): 17 | """ 18 | Main class for Generalized R-CNN. Currently supports boxes and masks. 19 | It consists of three main parts: 20 | - backbone 21 | - rpn 22 | - heads: takes the features + the proposals from the RPN and computes 23 | detections / masks from it. 24 | """ 25 | 26 | def __init__(self, cfg): 27 | super(GeneralizedRCNN, self).__init__() 28 | 29 | self.backbone = build_backbone(cfg) 30 | self.rpn = build_rpn(cfg, self.backbone.out_channels) 31 | self.roi_heads = build_roi_heads(cfg, self.backbone.out_channels) 32 | 33 | def forward(self, images, targets=None): 34 | """ 35 | Arguments: 36 | images (list[Tensor] or ImageList): images to be processed 37 | targets (list[BoxList]): ground-truth boxes present in the image (optional) 38 | 39 | Returns: 40 | result (list[BoxList] or dict[Tensor]): the output from the model. 41 | During training, it returns a dict[Tensor] which contains the losses. 42 | During testing, it returns list[BoxList] contains additional fields 43 | like `scores`, `labels` and `mask` (for Mask R-CNN models). 44 | 45 | """ 46 | if self.training and targets is None: 47 | raise ValueError("In training mode, targets should be passed") 48 | images = to_image_list(images) 49 | features = self.backbone(images.tensors) 50 | proposals, proposal_losses = self.rpn(images, features, targets) 51 | if self.roi_heads: 52 | x, result, detector_losses = self.roi_heads(features, proposals, targets) 53 | else: 54 | # RPN-only models don't have roi_heads 55 | x = features 56 | result = proposals 57 | detector_losses = {} 58 | 59 | if self.training: 60 | losses = {} 61 | losses.update(detector_losses) 62 | losses.update(proposal_losses) 63 | return result, losses 64 | 65 | return result 66 | -------------------------------------------------------------------------------- /strix/data_io/base_dataset/selflearning_dataset.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import Optional, Sequence, Union 3 | 4 | from monai_ex.data import CacheDataset, PersistentDataset 5 | from monai_ex.data import Dataset 6 | from monai_ex.transforms import * 7 | from monai_ex.utils import ensure_list 8 | from strix.data_io.base_dataset.utils import get_input_data 9 | 10 | 11 | class BasicSelflearningDataset(object): 12 | def __new__( 13 | self, 14 | files_list: Sequence, 15 | loader: Union[Sequence[MapTransform], MapTransform], 16 | channeler: Union[Sequence[MapTransform], MapTransform], 17 | orienter: Union[Sequence[MapTransform], MapTransform], 18 | spacer: Union[Sequence[MapTransform], MapTransform], 19 | rescaler: Union[Sequence[MapTransform], MapTransform], 20 | resizer: Union[Sequence[MapTransform], MapTransform], 21 | cropper: Union[Sequence[MapTransform], MapTransform], 22 | caster: Union[Sequence[MapTransform], MapTransform], 23 | to_tensor: Union[Sequence[MapTransform], MapTransform], 24 | dataset_type: Dataset, 25 | dataset_kwargs: dict, 26 | additional_transforms: Optional[Sequence[MapTransform]] = None, 27 | check_data: bool = True, 28 | verbose: bool = False, 29 | ): 30 | self.files_list = files_list 31 | self.verbose = verbose 32 | self.dataset = dataset_type 33 | self.dataset_kwargs = dataset_kwargs 34 | if check_data: 35 | self.input_data = get_input_data( 36 | files_list, False, verbose, self.__class__.__name__ 37 | ) 38 | else: 39 | self.input_data = files_list 40 | 41 | self.transforms = ensure_list(loader) 42 | if channeler is not None: 43 | self.transforms += ensure_list(channeler) 44 | if orienter is not None: 45 | self.transforms += ensure_list(orienter) 46 | if spacer is not None: 47 | self.transforms += ensure_list(spacer) 48 | if rescaler is not None: 49 | self.transforms += ensure_list(rescaler) 50 | if additional_transforms is not None: 51 | self.transforms += ensure_list(additional_transforms) 52 | if resizer is not None: 53 | self.transforms += ensure_list(resizer) 54 | if cropper is not None: 55 | self.transforms += ensure_list(cropper) 56 | 57 | self.transforms = Compose(self.transforms) 58 | 59 | return self.dataset(self.input_data, transform=self.transforms, **self.dataset_kwargs) 60 | 61 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/roi_heads/box_head/roi_box_predictors.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from strix.models.rcnn.modeling import registry 3 | from torch import nn 4 | 5 | 6 | @registry.ROI_BOX_PREDICTOR.register("FastRCNNPredictor") 7 | class FastRCNNPredictor(nn.Module): 8 | def __init__(self, config, in_channels): 9 | super(FastRCNNPredictor, self).__init__() 10 | assert in_channels is not None 11 | 12 | num_inputs = in_channels 13 | 14 | num_classes = config.MODEL.ROI_BOX_HEAD.NUM_CLASSES 15 | self.avgpool = nn.AdaptiveAvgPool2d(1) 16 | self.cls_score = nn.Linear(num_inputs, num_classes) 17 | num_bbox_reg_classes = 2 if config.MODEL.CLS_AGNOSTIC_BBOX_REG else num_classes 18 | self.bbox_pred = nn.Linear(num_inputs, num_bbox_reg_classes * 4) 19 | 20 | nn.init.normal_(self.cls_score.weight, mean=0, std=0.01) 21 | nn.init.constant_(self.cls_score.bias, 0) 22 | 23 | nn.init.normal_(self.bbox_pred.weight, mean=0, std=0.001) 24 | nn.init.constant_(self.bbox_pred.bias, 0) 25 | 26 | def forward(self, x): 27 | x = self.avgpool(x) 28 | x = x.view(x.size(0), -1) 29 | cls_logit = self.cls_score(x) 30 | bbox_pred = self.bbox_pred(x) 31 | return cls_logit, bbox_pred 32 | 33 | 34 | @registry.ROI_BOX_PREDICTOR.register("FPNPredictor") 35 | class FPNPredictor(nn.Module): 36 | def __init__(self, cfg, in_channels): 37 | super(FPNPredictor, self).__init__() 38 | num_classes = cfg.MODEL.ROI_BOX_HEAD.NUM_CLASSES 39 | representation_size = in_channels 40 | 41 | self.cls_score = nn.Linear(representation_size, num_classes) 42 | num_bbox_reg_classes = 2 if cfg.MODEL.CLS_AGNOSTIC_BBOX_REG else num_classes 43 | self.bbox_pred = nn.Linear(representation_size, num_bbox_reg_classes * 4) 44 | 45 | nn.init.normal_(self.cls_score.weight, std=0.01) 46 | nn.init.normal_(self.bbox_pred.weight, std=0.001) 47 | for l in [self.cls_score, self.bbox_pred]: 48 | nn.init.constant_(l.bias, 0) 49 | 50 | def forward(self, x): 51 | if x.ndimension() == 4: 52 | assert list(x.shape[2:]) == [1, 1] 53 | x = x.view(x.size(0), -1) 54 | scores = self.cls_score(x) 55 | bbox_deltas = self.bbox_pred(x) 56 | 57 | return scores, bbox_deltas 58 | 59 | 60 | def make_roi_box_predictor(cfg, in_channels): 61 | func = registry.ROI_BOX_PREDICTOR[cfg.MODEL.ROI_BOX_HEAD.PREDICTOR] 62 | return func(cfg, in_channels) 63 | -------------------------------------------------------------------------------- /strix/models/rcnn/layers/sigmoid_focal_loss.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.autograd import Function 4 | from torch.autograd.function import once_differentiable 5 | 6 | from strix.models.rcnn import _C 7 | 8 | # TODO: Use JIT to replace CUDA implementation in the future. 9 | class _SigmoidFocalLoss(Function): 10 | @staticmethod 11 | def forward(ctx, logits, targets, gamma, alpha): 12 | ctx.save_for_backward(logits, targets) 13 | num_classes = logits.shape[1] 14 | ctx.num_classes = num_classes 15 | ctx.gamma = gamma 16 | ctx.alpha = alpha 17 | 18 | losses = _C.sigmoid_focalloss_forward( 19 | logits, targets, num_classes, gamma, alpha 20 | ) 21 | return losses 22 | 23 | @staticmethod 24 | @once_differentiable 25 | def backward(ctx, d_loss): 26 | logits, targets = ctx.saved_tensors 27 | num_classes = ctx.num_classes 28 | gamma = ctx.gamma 29 | alpha = ctx.alpha 30 | d_loss = d_loss.contiguous() 31 | d_logits = _C.sigmoid_focalloss_backward( 32 | logits, targets, d_loss, num_classes, gamma, alpha 33 | ) 34 | return d_logits, None, None, None, None 35 | 36 | 37 | sigmoid_focal_loss_cuda = _SigmoidFocalLoss.apply 38 | 39 | 40 | def sigmoid_focal_loss_cpu(logits, targets, gamma, alpha): 41 | num_classes = logits.shape[1] 42 | gamma = gamma[0] 43 | alpha = alpha[0] 44 | dtype = targets.dtype 45 | device = targets.device 46 | class_range = torch.arange(1, num_classes+1, dtype=dtype, device=device).unsqueeze(0) 47 | 48 | t = targets.unsqueeze(1) 49 | p = torch.sigmoid(logits) 50 | term1 = (1 - p) ** gamma * torch.log(p) 51 | term2 = p ** gamma * torch.log(1 - p) 52 | return -(t == class_range).float() * term1 * alpha - ((t != class_range) * (t >= 0)).float() * term2 * (1 - alpha) 53 | 54 | 55 | class SigmoidFocalLoss(nn.Module): 56 | def __init__(self, gamma, alpha): 57 | super(SigmoidFocalLoss, self).__init__() 58 | self.gamma = gamma 59 | self.alpha = alpha 60 | 61 | def forward(self, logits, targets): 62 | device = logits.device 63 | if logits.is_cuda: 64 | loss_func = sigmoid_focal_loss_cuda 65 | else: 66 | loss_func = sigmoid_focal_loss_cpu 67 | 68 | loss = loss_func(logits, targets, self.gamma, self.alpha) 69 | return loss.sum() 70 | 71 | def __repr__(self): 72 | tmpstr = self.__class__.__name__ + "(" 73 | tmpstr += "gamma=" + str(self.gamma) 74 | tmpstr += ", alpha=" + str(self.alpha) 75 | tmpstr += ")" 76 | return tmpstr 77 | -------------------------------------------------------------------------------- /strix/models/rcnn/csrc/cpu/nms_cpu.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | #include "cpu/vision.h" 3 | 4 | 5 | template 6 | at::Tensor nms_cpu_kernel(const at::Tensor& dets, 7 | const at::Tensor& scores, 8 | const float threshold) { 9 | AT_ASSERTM(!dets.type().is_cuda(), "dets must be a CPU tensor"); 10 | AT_ASSERTM(!scores.type().is_cuda(), "scores must be a CPU tensor"); 11 | AT_ASSERTM(dets.type() == scores.type(), "dets should have the same type as scores"); 12 | 13 | if (dets.numel() == 0) { 14 | return at::empty({0}, dets.options().dtype(at::kLong).device(at::kCPU)); 15 | } 16 | 17 | auto x1_t = dets.select(1, 0).contiguous(); 18 | auto y1_t = dets.select(1, 1).contiguous(); 19 | auto x2_t = dets.select(1, 2).contiguous(); 20 | auto y2_t = dets.select(1, 3).contiguous(); 21 | 22 | at::Tensor areas_t = (x2_t - x1_t + 1) * (y2_t - y1_t + 1); 23 | 24 | auto order_t = std::get<1>(scores.sort(0, /* descending=*/true)); 25 | 26 | auto ndets = dets.size(0); 27 | at::Tensor suppressed_t = at::zeros({ndets}, dets.options().dtype(at::kByte).device(at::kCPU)); 28 | 29 | auto suppressed = suppressed_t.data(); 30 | auto order = order_t.data(); 31 | auto x1 = x1_t.data(); 32 | auto y1 = y1_t.data(); 33 | auto x2 = x2_t.data(); 34 | auto y2 = y2_t.data(); 35 | auto areas = areas_t.data(); 36 | 37 | for (int64_t _i = 0; _i < ndets; _i++) { 38 | auto i = order[_i]; 39 | if (suppressed[i] == 1) 40 | continue; 41 | auto ix1 = x1[i]; 42 | auto iy1 = y1[i]; 43 | auto ix2 = x2[i]; 44 | auto iy2 = y2[i]; 45 | auto iarea = areas[i]; 46 | 47 | for (int64_t _j = _i + 1; _j < ndets; _j++) { 48 | auto j = order[_j]; 49 | if (suppressed[j] == 1) 50 | continue; 51 | auto xx1 = std::max(ix1, x1[j]); 52 | auto yy1 = std::max(iy1, y1[j]); 53 | auto xx2 = std::min(ix2, x2[j]); 54 | auto yy2 = std::min(iy2, y2[j]); 55 | 56 | auto w = std::max(static_cast(0), xx2 - xx1 + 1); 57 | auto h = std::max(static_cast(0), yy2 - yy1 + 1); 58 | auto inter = w * h; 59 | auto ovr = inter / (iarea + areas[j] - inter); 60 | if (ovr >= threshold) 61 | suppressed[j] = 1; 62 | } 63 | } 64 | return at::nonzero(suppressed_t == 0).squeeze(1); 65 | } 66 | 67 | at::Tensor nms_cpu(const at::Tensor& dets, 68 | const at::Tensor& scores, 69 | const float threshold) { 70 | at::Tensor result; 71 | AT_DISPATCH_FLOATING_TYPES(dets.type(), "nms", [&] { 72 | result = nms_cpu_kernel(dets, scores, threshold); 73 | }); 74 | return result; 75 | } 76 | -------------------------------------------------------------------------------- /strix/models/rcnn/structures/image_list.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from __future__ import division 3 | 4 | import torch 5 | 6 | 7 | class ImageList(object): 8 | """ 9 | Structure that holds a list of images (of possibly 10 | varying sizes) as a single tensor. 11 | This works by padding the images to the same size, 12 | and storing in a field the original sizes of each image 13 | """ 14 | 15 | def __init__(self, tensors, image_sizes): 16 | """ 17 | Arguments: 18 | tensors (tensor) 19 | image_sizes (list[tuple[int, int]]) 20 | """ 21 | self.tensors = tensors 22 | self.image_sizes = image_sizes 23 | 24 | def to(self, *args, **kwargs): 25 | cast_tensor = self.tensors.to(*args, **kwargs) 26 | return ImageList(cast_tensor, self.image_sizes) 27 | 28 | 29 | def to_image_list(tensors, size_divisible=0): 30 | """ 31 | tensors can be an ImageList, a torch.Tensor or 32 | an iterable of Tensors. It can't be a numpy array. 33 | When tensors is an iterable of Tensors, it pads 34 | the Tensors with zeros so that they have the same 35 | shape 36 | """ 37 | if isinstance(tensors, torch.Tensor) and size_divisible > 0: 38 | tensors = [tensors] 39 | 40 | if isinstance(tensors, ImageList): 41 | return tensors 42 | elif isinstance(tensors, torch.Tensor): 43 | # single tensor shape can be inferred 44 | if tensors.dim() == 3: 45 | tensors = tensors[None] 46 | assert tensors.dim() == 4 47 | image_sizes = [tensor.shape[-2:] for tensor in tensors] 48 | return ImageList(tensors, image_sizes) 49 | elif isinstance(tensors, (tuple, list)): 50 | max_size = tuple(max(s) for s in zip(*[img.shape for img in tensors])) 51 | 52 | # TODO Ideally, just remove this and let me model handle arbitrary 53 | # input sizs 54 | if size_divisible > 0: 55 | import math 56 | 57 | stride = size_divisible 58 | max_size = list(max_size) 59 | max_size[1] = int(math.ceil(max_size[1] / stride) * stride) 60 | max_size[2] = int(math.ceil(max_size[2] / stride) * stride) 61 | max_size = tuple(max_size) 62 | 63 | batch_shape = (len(tensors),) + max_size 64 | batched_imgs = tensors[0].new(*batch_shape).zero_() 65 | for img, pad_img in zip(tensors, batched_imgs): 66 | pad_img[: img.shape[0], : img.shape[1], : img.shape[2]].copy_(img) 67 | 68 | image_sizes = [im.shape[-2:] for im in tensors] 69 | 70 | return ImageList(batched_imgs, image_sizes) 71 | else: 72 | raise TypeError("Unsupported type for to_image_list: {}".format(type(tensors))) 73 | -------------------------------------------------------------------------------- /strix/data_io/base_dataset/classification_dataset.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Sequence, Union 2 | 3 | from monai_ex.data import Dataset 4 | from monai_ex.transforms import MapTransform, Compose 5 | from monai_ex.utils import ensure_list 6 | from strix.data_io.base_dataset.utils import get_input_data 7 | 8 | 9 | class BasicClassificationDataset(object): 10 | def __new__( 11 | self, 12 | files_list: Sequence, 13 | loader: Union[Sequence[MapTransform], MapTransform], 14 | channeler: Union[Sequence[MapTransform], MapTransform], 15 | orienter: Union[Sequence[MapTransform], MapTransform], 16 | spacer: Union[Sequence[MapTransform], MapTransform], 17 | rescaler: Union[Sequence[MapTransform], MapTransform], 18 | resizer: Union[Sequence[MapTransform], MapTransform], 19 | cropper: Union[Sequence[MapTransform], MapTransform], 20 | caster: Union[Sequence[MapTransform], MapTransform], 21 | to_tensor: Union[Sequence[MapTransform], MapTransform], 22 | is_supervised: bool, 23 | dataset_type: Dataset, 24 | dataset_kwargs: Optional[dict] = {}, 25 | additional_transforms: Optional[Sequence[MapTransform]] = None, 26 | check_data: bool = True, 27 | verbose: bool = False, 28 | ): 29 | self.files_list = files_list 30 | self.verbose = verbose 31 | self.dataset = dataset_type 32 | self.dataset_kwargs = dataset_kwargs 33 | if check_data: 34 | self.input_data = get_input_data( 35 | files_list, is_supervised, verbose, self.__class__.__name__ 36 | ) 37 | else: 38 | self.input_data = files_list 39 | 40 | self.transforms = ensure_list(loader) 41 | if channeler is not None: 42 | self.transforms += ensure_list(channeler) 43 | if orienter is not None: 44 | self.transforms += ensure_list(orienter) 45 | if spacer is not None: 46 | self.transforms += ensure_list(spacer) 47 | if rescaler is not None: 48 | self.transforms += ensure_list(rescaler) 49 | if resizer is not None: 50 | self.transforms += ensure_list(resizer) 51 | if cropper is not None: 52 | self.transforms += ensure_list(cropper) 53 | if additional_transforms is not None: 54 | self.transforms += ensure_list(additional_transforms) 55 | 56 | if caster is not None: 57 | self.transforms += ensure_list(caster) 58 | if to_tensor is not None: 59 | self.transforms += ensure_list(to_tensor) 60 | 61 | self.transforms = Compose(self.transforms) 62 | 63 | return self.dataset( 64 | self.input_data, transform=self.transforms, **self.dataset_kwargs 65 | ) 66 | -------------------------------------------------------------------------------- /strix/data_io/base_dataset/segmentation_dataset.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Sequence, Union 2 | 3 | # from monai_ex.engines.utils import CustomKeys, get_keys_list 4 | from monai_ex.data import Dataset 5 | from monai_ex.transforms import MapTransform, ComposeEx as Compose 6 | from monai_ex.utils import ensure_list 7 | from strix.data_io.base_dataset.utils import get_input_data 8 | 9 | 10 | class BasicSegmentationDataset(object): 11 | def __new__( 12 | self, 13 | files_list: Sequence, 14 | loader: Union[Sequence[MapTransform], MapTransform], 15 | channeler: Union[Sequence[MapTransform], MapTransform], 16 | orienter: Union[Sequence[MapTransform], MapTransform], 17 | spacer: Union[Sequence[MapTransform], MapTransform], 18 | rescaler: Union[Sequence[MapTransform], MapTransform], 19 | resizer: Union[Sequence[MapTransform], MapTransform], 20 | cropper: Union[Sequence[MapTransform], MapTransform], 21 | caster: Union[Sequence[MapTransform], MapTransform], 22 | to_tensor: Union[Sequence[MapTransform], MapTransform], 23 | is_supervised: bool, 24 | dataset_type: Dataset, 25 | dataset_kwargs: dict, 26 | additional_transforms: Optional[Sequence[MapTransform]] = None, 27 | check_data: bool = True, 28 | verbose: bool = False, 29 | ): 30 | self.files_list = files_list 31 | self.verbose = verbose 32 | self.dataset = dataset_type 33 | self.dataset_kwargs = dataset_kwargs 34 | if check_data: 35 | self.input_data = get_input_data( 36 | files_list, is_supervised, verbose, self.__class__.__name__ 37 | ) 38 | else: 39 | self.input_data = files_list 40 | 41 | self.transforms = ensure_list(loader) 42 | if channeler is not None: 43 | self.transforms += ensure_list(channeler) 44 | if orienter is not None: 45 | self.transforms += ensure_list(orienter) 46 | if spacer is not None: 47 | self.transforms += ensure_list(spacer) 48 | if rescaler is not None: 49 | self.transforms += ensure_list(rescaler) 50 | if resizer is not None: 51 | self.transforms += ensure_list(resizer) 52 | if cropper is not None: 53 | self.transforms += ensure_list(cropper) 54 | if additional_transforms is not None: 55 | self.transforms += ensure_list(additional_transforms) 56 | 57 | if caster is not None: 58 | self.transforms += ensure_list(caster) 59 | if to_tensor is not None: 60 | self.transforms += ensure_list(to_tensor) 61 | 62 | self.transforms = Compose(self.transforms) 63 | 64 | return self.dataset(self.input_data, transform=self.transforms, **self.dataset_kwargs) 65 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/roi_heads/mask_head/roi_mask_feature_extractors.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | from torch import nn 3 | from torch.nn import functional as F 4 | 5 | from ..box_head.roi_box_feature_extractors import ResNet50Conv5ROIFeatureExtractor 6 | from strix.models.rcnn.modeling import registry 7 | from strix.models.rcnn.modeling.poolers import Pooler 8 | from strix.models.rcnn.modeling.make_layers import make_conv3x3 9 | 10 | 11 | registry.ROI_MASK_FEATURE_EXTRACTORS.register( 12 | "ResNet50Conv5ROIFeatureExtractor", ResNet50Conv5ROIFeatureExtractor 13 | ) 14 | 15 | 16 | @registry.ROI_MASK_FEATURE_EXTRACTORS.register("MaskRCNNFPNFeatureExtractor") 17 | class MaskRCNNFPNFeatureExtractor(nn.Module): 18 | """ 19 | Heads for FPN for classification 20 | """ 21 | 22 | def __init__(self, cfg, in_channels): 23 | """ 24 | Arguments: 25 | num_classes (int): number of output classes 26 | input_size (int): number of channels of the input once it's flattened 27 | representation_size (int): size of the intermediate representation 28 | """ 29 | super(MaskRCNNFPNFeatureExtractor, self).__init__() 30 | 31 | resolution = cfg.MODEL.ROI_MASK_HEAD.POOLER_RESOLUTION 32 | scales = cfg.MODEL.ROI_MASK_HEAD.POOLER_SCALES 33 | sampling_ratio = cfg.MODEL.ROI_MASK_HEAD.POOLER_SAMPLING_RATIO 34 | pooler = Pooler( 35 | output_size=(resolution, resolution), 36 | scales=scales, 37 | sampling_ratio=sampling_ratio, 38 | ) 39 | input_size = in_channels 40 | self.pooler = pooler 41 | 42 | use_gn = cfg.MODEL.ROI_MASK_HEAD.USE_GN 43 | layers = cfg.MODEL.ROI_MASK_HEAD.CONV_LAYERS 44 | dilation = cfg.MODEL.ROI_MASK_HEAD.DILATION 45 | 46 | next_feature = input_size 47 | self.blocks = [] 48 | for layer_idx, layer_features in enumerate(layers, 1): 49 | layer_name = "mask_fcn{}".format(layer_idx) 50 | module = make_conv3x3( 51 | next_feature, layer_features, 52 | dilation=dilation, stride=1, use_gn=use_gn 53 | ) 54 | self.add_module(layer_name, module) 55 | next_feature = layer_features 56 | self.blocks.append(layer_name) 57 | self.out_channels = layer_features 58 | 59 | def forward(self, x, proposals): 60 | x = self.pooler(x, proposals) 61 | 62 | for layer_name in self.blocks: 63 | x = F.relu(getattr(self, layer_name)(x)) 64 | 65 | return x 66 | 67 | 68 | def make_roi_mask_feature_extractor(cfg, in_channels): 69 | func = registry.ROI_MASK_FEATURE_EXTRACTORS[ 70 | cfg.MODEL.ROI_MASK_HEAD.FEATURE_EXTRACTOR 71 | ] 72 | return func(cfg, in_channels) 73 | -------------------------------------------------------------------------------- /strix/models/rcnn/data/samplers/distributed.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | # Code is copy-pasted exactly as in torch.utils.data.distributed. 3 | # FIXME remove this once c10d fixes the bug it has 4 | import math 5 | import torch 6 | import torch.distributed as dist 7 | from torch.utils.data.sampler import Sampler 8 | 9 | 10 | class DistributedSampler(Sampler): 11 | """Sampler that restricts data loading to a subset of the dataset. 12 | It is especially useful in conjunction with 13 | :class:`torch.nn.parallel.DistributedDataParallel`. In such case, each 14 | process can pass a DistributedSampler instance as a DataLoader sampler, 15 | and load a subset of the original dataset that is exclusive to it. 16 | .. note:: 17 | Dataset is assumed to be of constant size. 18 | Arguments: 19 | dataset: Dataset used for sampling. 20 | num_replicas (optional): Number of processes participating in 21 | distributed training. 22 | rank (optional): Rank of the current process within num_replicas. 23 | """ 24 | 25 | def __init__(self, dataset, num_replicas=None, rank=None, shuffle=True): 26 | if num_replicas is None: 27 | if not dist.is_available(): 28 | raise RuntimeError("Requires distributed package to be available") 29 | num_replicas = dist.get_world_size() 30 | if rank is None: 31 | if not dist.is_available(): 32 | raise RuntimeError("Requires distributed package to be available") 33 | rank = dist.get_rank() 34 | self.dataset = dataset 35 | self.num_replicas = num_replicas 36 | self.rank = rank 37 | self.epoch = 0 38 | self.num_samples = int(math.ceil(len(self.dataset) * 1.0 / self.num_replicas)) 39 | self.total_size = self.num_samples * self.num_replicas 40 | self.shuffle = shuffle 41 | 42 | def __iter__(self): 43 | if self.shuffle: 44 | # deterministically shuffle based on epoch 45 | g = torch.Generator() 46 | g.manual_seed(self.epoch) 47 | indices = torch.randperm(len(self.dataset), generator=g).tolist() 48 | else: 49 | indices = torch.arange(len(self.dataset)).tolist() 50 | 51 | # add extra samples to make it evenly divisible 52 | indices += indices[: (self.total_size - len(indices))] 53 | assert len(indices) == self.total_size 54 | 55 | # subsample 56 | offset = self.num_samples * self.rank 57 | indices = indices[offset : offset + self.num_samples] 58 | assert len(indices) == self.num_samples 59 | 60 | return iter(indices) 61 | 62 | def __len__(self): 63 | return self.num_samples 64 | 65 | def set_epoch(self, epoch): 66 | self.epoch = epoch 67 | -------------------------------------------------------------------------------- /strix/models/rcnn/csrc/cuda/vision.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | #pragma once 3 | #include 4 | 5 | 6 | at::Tensor SigmoidFocalLoss_forward_cuda( 7 | const at::Tensor& logits, 8 | const at::Tensor& targets, 9 | const int num_classes, 10 | const float gamma, 11 | const float alpha); 12 | 13 | at::Tensor SigmoidFocalLoss_backward_cuda( 14 | const at::Tensor& logits, 15 | const at::Tensor& targets, 16 | const at::Tensor& d_losses, 17 | const int num_classes, 18 | const float gamma, 19 | const float alpha); 20 | 21 | at::Tensor ROIAlign_forward_cuda(const at::Tensor& input, 22 | const at::Tensor& rois, 23 | const float spatial_scale, 24 | const int pooled_height, 25 | const int pooled_width, 26 | const int sampling_ratio); 27 | 28 | at::Tensor ROIAlign_backward_cuda(const at::Tensor& grad, 29 | const at::Tensor& rois, 30 | const float spatial_scale, 31 | const int pooled_height, 32 | const int pooled_width, 33 | const int batch_size, 34 | const int channels, 35 | const int height, 36 | const int width, 37 | const int sampling_ratio); 38 | 39 | 40 | std::tuple ROIPool_forward_cuda(const at::Tensor& input, 41 | const at::Tensor& rois, 42 | const float spatial_scale, 43 | const int pooled_height, 44 | const int pooled_width); 45 | 46 | at::Tensor ROIPool_backward_cuda(const at::Tensor& grad, 47 | const at::Tensor& input, 48 | const at::Tensor& rois, 49 | const at::Tensor& argmax, 50 | const float spatial_scale, 51 | const int pooled_height, 52 | const int pooled_width, 53 | const int batch_size, 54 | const int channels, 55 | const int height, 56 | const int width); 57 | 58 | at::Tensor nms_cuda(const at::Tensor boxes, float nms_overlap_thresh); 59 | 60 | 61 | at::Tensor compute_flow_cuda(const at::Tensor& boxes, 62 | const int height, 63 | const int width); 64 | -------------------------------------------------------------------------------- /strix/models/rcnn/__init__.py: -------------------------------------------------------------------------------- 1 | # from strix.utilities.utils import ENGINES, assert_network_type 2 | # from strix.models.rcnn.modeling.detector.generalized_rcnn import GeneralizedRCNN 3 | 4 | # from monai_ex.engines import RcnnTrainer 5 | # from monai_ex.handlers import ( 6 | # StatsHandler, 7 | # TensorBoardStatsHandler, 8 | # TensorBoardImageHandler, 9 | # TensorBoardImageHandlerEx, 10 | # ValidationHandler, 11 | # LrScheduleHandler, 12 | # LrScheduleTensorboardHandler, 13 | # CheckpointSaver, 14 | # CheckpointLoader, 15 | # SegmentationSaver, 16 | # ClassificationSaver, 17 | # MeanDice, 18 | # MetricLogger, 19 | # ) 20 | 21 | # @ENGINES.register('detection') 22 | # def build_detection_engine(**kwargs): 23 | # opts = kwargs['opts'] 24 | # train_loader = kwargs['train_loader'] 25 | # test_loader = kwargs['test_loader'] 26 | # net = kwargs['net'] 27 | # loss = kwargs['loss'] 28 | # optim = kwargs['optim'] 29 | # lr_scheduler = kwargs['lr_scheduler'] 30 | # writer = kwargs['writer'] 31 | # valid_interval = kwargs['valid_interval'] 32 | # device = kwargs['device'] 33 | # model_dir = kwargs['model_dir'] 34 | # logger_name = kwargs.get('logger_name', None) 35 | 36 | # assert_network_type(opts.model_name, 'RCNN') 37 | 38 | # prepare_batch_fn = lambda x : (x["image"], x["target"]) 39 | # key_metric_transform_fn = lambda x : (x["pred"], x["target"]) 40 | 41 | # train_handlers = [ 42 | # LrScheduleTensorboardHandler(lr_scheduler=lr_scheduler, summary_writer=writer), 43 | # #ValidationHandler(validator=evaluator, interval=valid_interval, epoch_level=True), 44 | # StatsHandler(tag_name="train_loss", output_transform=lambda x:x["loss"], name=logger_name), 45 | # CheckpointSaver(save_dir=model_dir, save_dict={"net":net, "optim":optim}, save_interval=opts.save_epoch_freq, epoch_level=True, n_saved=5), 46 | # TensorBoardStatsHandler(summary_writer=writer, tag_name="train_loss", output_transform=lambda x:x["loss"]), 47 | # # TensorBoardImageHandlerEx( 48 | # # summary_writer=writer, 49 | # # batch_transform=lambda x: (x["image"], x["label"]), 50 | # # output_transform=lambda x: x["pred"], 51 | # # max_channels=opts.output_nc, 52 | # # prefix_name='train' 53 | # # ), 54 | # ] 55 | 56 | # trainer = RcnnTrainer( 57 | # device=device, 58 | # max_epochs=opts.n_epoch, 59 | # train_data_loader=train_loader, 60 | # network=net, 61 | # optimizer=optim, 62 | # loss_function=loss, 63 | # epoch_length=int(opts.n_epoch_len) if opts.n_epoch_len > 1.0 else int(opts.n_epoch_len*len(train_loader)), 64 | # prepare_batch=prepare_batch_fn, 65 | # post_transform=None, 66 | # train_handlers=train_handlers, 67 | # amp=opts.amp 68 | # ) 69 | # return trainer, net -------------------------------------------------------------------------------- /strix/models/rcnn/data/transforms/transforms.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import random 3 | 4 | import torch 5 | import torchvision 6 | from torchvision.transforms import functional as F 7 | 8 | 9 | class Compose(object): 10 | def __init__(self, transforms): 11 | self.transforms = transforms 12 | 13 | def __call__(self, image, target): 14 | for t in self.transforms: 15 | image, target = t(image, target) 16 | return image, target 17 | 18 | def __repr__(self): 19 | format_string = self.__class__.__name__ + "(" 20 | for t in self.transforms: 21 | format_string += "\n" 22 | format_string += " {0}".format(t) 23 | format_string += "\n)" 24 | return format_string 25 | 26 | 27 | class Resize(object): 28 | def __init__(self, min_size, max_size): 29 | if not isinstance(min_size, (list, tuple)): 30 | min_size = (min_size,) 31 | self.min_size = min_size 32 | self.max_size = max_size 33 | 34 | # modified from torchvision to add support for max size 35 | def get_size(self, image_size): 36 | w, h = image_size 37 | size = random.choice(self.min_size) 38 | max_size = self.max_size 39 | if max_size is not None: 40 | min_original_size = float(min((w, h))) 41 | max_original_size = float(max((w, h))) 42 | if max_original_size / min_original_size * size > max_size: 43 | size = int(round(max_size * min_original_size / max_original_size)) 44 | 45 | if (w <= h and w == size) or (h <= w and h == size): 46 | return (h, w) 47 | 48 | if w < h: 49 | ow = size 50 | oh = int(size * h / w) 51 | else: 52 | oh = size 53 | ow = int(size * w / h) 54 | 55 | return (oh, ow) 56 | 57 | def __call__(self, image, target): 58 | size = self.get_size(image.size) 59 | image = F.resize(image, size) 60 | target = target.resize(image.size) 61 | return image, target 62 | 63 | 64 | class RandomHorizontalFlip(object): 65 | def __init__(self, prob=0.5): 66 | self.prob = prob 67 | 68 | def __call__(self, image, target): 69 | if random.random() < self.prob: 70 | image = F.hflip(image) 71 | target = target.transpose(0) 72 | return image, target 73 | 74 | 75 | class ToTensor(object): 76 | def __call__(self, image, target): 77 | return F.to_tensor(image), target 78 | 79 | 80 | class Normalize(object): 81 | def __init__(self, mean, std, to_bgr255=True): 82 | self.mean = mean 83 | self.std = std 84 | self.to_bgr255 = to_bgr255 85 | 86 | def __call__(self, image, target): 87 | if self.to_bgr255: 88 | image = image[[2, 1, 0]] * 255 89 | image = F.normalize(image, mean=self.mean, std=self.std) 90 | return image, target 91 | -------------------------------------------------------------------------------- /strix/utilities/enum.py: -------------------------------------------------------------------------------- 1 | # All enum variables 2 | from enum import Enum 3 | 4 | BUILTIN_TYPES = [dict, list, tuple, str, int, float, bool] 5 | 6 | 7 | def get_enums(enum_class): 8 | return [item.value for item in enum_class.__members__.values()] 9 | 10 | 11 | class Dims(Enum): 12 | TWO = "2D" 13 | THREE = "3D" 14 | 15 | 16 | DIMS = get_enums(Dims) 17 | 18 | 19 | class Phases(Enum): 20 | TRAIN = "train" 21 | VALID = "valid" 22 | TEST_IN = "test" 23 | TEST_EX = "test_wo_label" 24 | 25 | 26 | PHASES = get_enums(Phases) 27 | 28 | 29 | class Norms(Enum): 30 | BATCH = "batch" 31 | INSTANCE = "instance" 32 | LAYER = "layer" 33 | GROUP = "group" 34 | 35 | 36 | NORMS = get_enums(Norms) 37 | 38 | 39 | class Activations(Enum): 40 | RELU = "relu" 41 | LEAKYRELU = "leakyrelu" 42 | PRELU = "prelu" 43 | SELU = "selu" 44 | CELU = "celu" 45 | GELU = "gelu" 46 | SIGMOID = "sigmoid" 47 | TANH = "tanh" 48 | SOFTMAX = "softmax" 49 | LOGSOFTMAX = "logsoftmax" 50 | SWISH = "swish" 51 | MISH = "mish" 52 | 53 | 54 | ACTIVATIONS = get_enums(Activations) 55 | 56 | 57 | class Losses(Enum): 58 | CE = "CE" 59 | WCE = "WCE" 60 | BCE = "BCE" 61 | WBCE = "WBCE" 62 | MSE = "MSE" 63 | DCE = "DCE" 64 | GDL = "GDL" 65 | CE_DCE = "CE-DCE" 66 | WCE_DCE = "WCE-DCE" 67 | FOCAL = "FocalLoss" 68 | DICE_FOCAL = "DiceFocalLoss" 69 | 70 | 71 | LOSSES = get_enums(Losses) 72 | 73 | 74 | class LrSchedule(Enum): 75 | CONST = "const" 76 | POLY = "poly" 77 | STEP = "step" 78 | MULTISTEP = "multistep" 79 | SGDR = "SGDR" 80 | PLATEAU = "plateau" 81 | 82 | 83 | LR_SCHEDULES = get_enums(LrSchedule) 84 | 85 | 86 | class Frameworks(Enum): 87 | SEGMENTATION = "segmentation" 88 | CLASSIFICATION = "classification" 89 | # SIAMESE = "siamese" 90 | SELFLEARNING = "selflearning" 91 | DETECTION = "detection" 92 | MULTITASK = "multitask" 93 | 94 | 95 | FRAMEWORKS = get_enums(Frameworks) 96 | 97 | 98 | class NetworkArgs(Enum): 99 | SPATIAL_DIMS = "spatial_dims" 100 | IN_CHANNELS = "in_channels" 101 | OUT_CHANNELS = "out_channels" 102 | ACT = "act" 103 | NORM = "norm" 104 | N_DEPTH = "n_depth" 105 | N_GROUP = "n_group" 106 | DROP_OUT = "drop_out" 107 | IS_PRUNABLE = "is_prunable" 108 | PRETRAINED = "pretrained" 109 | PRETRAINED_MODEL_PATH = "pretrained_model_path" 110 | 111 | 112 | NETWORK_ARGS = get_enums(NetworkArgs) 113 | 114 | 115 | class LayerOrders(Enum): 116 | CRB = "crb" 117 | CBR = "cbr" 118 | CGR = "cgr" 119 | CBE = "cbe" 120 | ABN = "abn" 121 | 122 | 123 | LAYER_ORDERS = get_enums(LayerOrders) 124 | 125 | 126 | class Optimizers(Enum): 127 | SGD = "sgd" 128 | ADAM = "adam" 129 | ADAMW = "adamw" 130 | RADAM = "radam" 131 | RANGER = "ranger" 132 | 133 | 134 | OPTIMIZERS = get_enums(Optimizers) 135 | 136 | -------------------------------------------------------------------------------- /strix/models/rcnn/modeling/balanced_positive_negative_sampler.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | import torch 3 | 4 | 5 | class BalancedPositiveNegativeSampler(object): 6 | """ 7 | This class samples batches, ensuring that they contain a fixed proportion of positives 8 | """ 9 | 10 | def __init__(self, batch_size_per_image, positive_fraction): 11 | """ 12 | Arguments: 13 | batch_size_per_image (int): number of elements to be selected per image 14 | positive_fraction (float): percentace of positive elements per batch 15 | """ 16 | self.batch_size_per_image = batch_size_per_image 17 | self.positive_fraction = positive_fraction 18 | 19 | def __call__(self, matched_idxs): 20 | """ 21 | Arguments: 22 | matched idxs: list of tensors containing -1, 0 or positive values. 23 | Each tensor corresponds to a specific image. 24 | -1 values are ignored, 0 are considered as negatives and > 0 as 25 | positives. 26 | 27 | Returns: 28 | pos_idx (list[tensor]) 29 | neg_idx (list[tensor]) 30 | 31 | Returns two lists of binary masks for each image. 32 | The first list contains the positive elements that were selected, 33 | and the second list the negative example. 34 | """ 35 | pos_idx = [] 36 | neg_idx = [] 37 | for matched_idxs_per_image in matched_idxs: 38 | positive = torch.nonzero(matched_idxs_per_image >= 1).squeeze(1) 39 | negative = torch.nonzero(matched_idxs_per_image == 0).squeeze(1) 40 | 41 | num_pos = int(self.batch_size_per_image * self.positive_fraction) 42 | # protect against not enough positive examples 43 | num_pos = min(positive.numel(), num_pos) 44 | num_neg = self.batch_size_per_image - num_pos 45 | # protect against not enough negative examples 46 | num_neg = min(negative.numel(), num_neg) 47 | 48 | # randomly select positive and negative examples 49 | perm1 = torch.randperm(positive.numel(), device=positive.device)[:num_pos] 50 | perm2 = torch.randperm(negative.numel(), device=negative.device)[:num_neg] 51 | 52 | pos_idx_per_image = positive[perm1] 53 | neg_idx_per_image = negative[perm2] 54 | 55 | # create binary mask from indices 56 | pos_idx_per_image_mask = torch.zeros_like( 57 | matched_idxs_per_image, dtype=torch.uint8 58 | ) 59 | neg_idx_per_image_mask = torch.zeros_like( 60 | matched_idxs_per_image, dtype=torch.uint8 61 | ) 62 | pos_idx_per_image_mask[pos_idx_per_image] = 1 63 | neg_idx_per_image_mask[neg_idx_per_image] = 1 64 | 65 | pos_idx.append(pos_idx_per_image_mask) 66 | neg_idx.append(neg_idx_per_image_mask) 67 | 68 | return pos_idx, neg_idx 69 | --------------------------------------------------------------------------------