Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CodeCamp #140 [New] [Feature] Add synapse dataset and data augmentation in dev-1.x. #2432

Merged
merged 41 commits into from
Jan 6, 2023
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f2b8d2f
doc
BLUE-coconut Nov 30, 2022
67b51b7
[Doc]Translate the 1_config.md and modify a wrong statement in 1_conf…
pofengdenihong Dec 2, 2022
4287fd2
Translate the 1_config.md and modify a wrong statement in 1_config.md
pofengdenihong Dec 2, 2022
5668182
modify part of content
BLUE-coconut Dec 3, 2022
ad470a3
Modify some expressions
pofengdenihong Dec 5, 2022
104a24d
changed parts of content
BLUE-coconut Dec 5, 2022
b0e57c6
Apply suggestions from code review
MeowZheng Dec 6, 2022
9750c97
Merge pull request #2371 from pofengdenihong/dev-1.x
MeowZheng Dec 6, 2022
8a3d6cd
[Doc] Add ZN datasets.md in dev-1.x
MengzhangLI Dec 6, 2022
3d1f8b7
modified
BLUE-coconut Dec 7, 2022
addd38d
fix typo
MengzhangLI Dec 7, 2022
372a6ce
Update docs/zh_cn/user_guides/4_train_test.md
BLUE-coconut Dec 7, 2022
dc8aa35
CodeCamp #1562 [Doc] update `overview.md`
tianleiSHI Dec 10, 2022
dddf093
Update overview.md
tianleiSHI Dec 10, 2022
7edb141
Merge pull request #2355 from BLUE-coconut/master
MeowZheng Dec 12, 2022
b770884
Add torch1.13 in CI
xiexinch Dec 12, 2022
02030b1
use mim install mm packages
xiexinch Dec 12, 2022
d755707
Update docs/zh_cn/overview.md
tianleiSHI Dec 12, 2022
c2042f3
Update docs/zh_cn/overview.md
tianleiSHI Dec 12, 2022
fdd1b95
install all requirements
xiexinch Dec 12, 2022
7537987
Merge pull request #2397 from tianleiSHI/dev-1.x
MeowZheng Dec 12, 2022
492313b
install wheel
xiexinch Dec 13, 2022
815b24e
add ref
xiexinch Dec 13, 2022
d7b85aa
Merge pull request #2402 from xiexinch/add-torch1.13-in-ci-1.x
MeowZheng Dec 13, 2022
164fd3f
fix
MengzhangLI Dec 13, 2022
e88489e
fix
MengzhangLI Dec 13, 2022
eeee12e
Merge pull request #2387 from MengzhangLI/zn_datasets_1.x
MeowZheng Dec 13, 2022
f5b4c12
add example project
xiexinch Dec 15, 2022
81da7aa
add ci ignore
xiexinch Dec 15, 2022
532ff5b
DOC
tianleiSHI Dec 17, 2022
ab690bd
Update docs/zh_cn/get_started.md
tianleiSHI Dec 20, 2022
ca68b00
Merge pull request #2417 from tianleiSHI/get_started_doc
MeowZheng Dec 20, 2022
534b27b
add version limits
xiexinch Dec 20, 2022
8539e22
Merge pull request #2412 from xiexinch/mmseg_projects
MeowZheng Dec 20, 2022
c034b34
Recovery Code
Dominic23331 Dec 23, 2022
cd83917
fix pr conflict
MengzhangLI Jan 4, 2023
4e925b0
add docstring
MengzhangLI Jan 4, 2023
1cc26ce
modify docstring
MengzhangLI Jan 5, 2023
694b16d
add docstring
MengzhangLI Jan 5, 2023
d054549
modify docstring
MengzhangLI Jan 6, 2023
b062e9c
fix typo
MengzhangLI Jan 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions configs/_base_/datasets/synapse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
dataset_type = 'SynapseDataset'
data_root = 'data/synapse/'
img_scale = (224, 224)
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations'),
dict(type='Resize', scale=img_scale, keep_ratio=True),
dict(type='RandomRotFlip', rotate_prob=0.5, flip_prob=0.5, degree=20),
dict(type='PackSegInputs')
]
test_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='Resize', scale=img_scale, keep_ratio=True),
dict(type='LoadAnnotations'),
dict(type='PackSegInputs')
]
train_dataloader = dict(
batch_size=6,
num_workers=2,
persistent_workers=True,
sampler=dict(type='InfiniteSampler', shuffle=True),
dataset=dict(
type=dataset_type,
data_root=data_root,
data_prefix=dict(
img_path='img_dir/train', seg_map_path='ann_dir/train'),
pipeline=train_pipeline))
val_dataloader = dict(
batch_size=1,
num_workers=4,
persistent_workers=True,
sampler=dict(type='DefaultSampler', shuffle=False),
dataset=dict(
type=dataset_type,
data_root=data_root,
data_prefix=dict(img_path='img_dir/val', seg_map_path='ann_dir/val'),
pipeline=test_pipeline))
test_dataloader = val_dataloader

val_evaluator = dict(type='IoUMetric', iou_metrics=['mDice'])
test_evaluator = val_evaluator
81 changes: 81 additions & 0 deletions docs/en/user_guides/2_dataset_prepare.md
Original file line number Diff line number Diff line change
Expand Up @@ -414,3 +414,84 @@ The contents of LIP datasets include:
│   │ │ ├── 100034_483681.png
│   │ │ ├── ...
```

## Synapse dataset

This dataset could be download from [this page](https://www.synapse.org/#!Synapse:syn3193805/wiki/)

To follow the data preparation setting of [TransUNet](https://arxiv.org/abs/2102.04306), which splits original training set (30 scans)
into new training (18 scans) and validation set (12 scans). Please run the following command to prepare the dataset.

```shell
unzip RawData.zip
cd ./RawData/Training
```

Then create `train.txt` and `val.txt` to split dataset.

According to TransUnet, the following is the data set division.

train.txt

```none
img0005.nii.gz
img0006.nii.gz
img0007.nii.gz
img0009.nii.gz
img0010.nii.gz
img0021.nii.gz
img0023.nii.gz
img0024.nii.gz
img0026.nii.gz
img0027.nii.gz
img0028.nii.gz
img0030.nii.gz
img0031.nii.gz
img0033.nii.gz
img0034.nii.gz
img0037.nii.gz
img0039.nii.gz
img0040.nii.gz
```

val.txt

```none
img0008.nii.gz
img0022.nii.gz
img0038.nii.gz
img0036.nii.gz
img0032.nii.gz
img0002.nii.gz
img0029.nii.gz
img0003.nii.gz
img0001.nii.gz
img0004.nii.gz
img0025.nii.gz
img0035.nii.gz
```

The contents of synapse datasets include:

```none
├── Training
│ ├── img
│ │ ├── img0001.nii.gz
│ │ ├── img0002.nii.gz
│ │ ├── ...
│ ├── label
│ │ ├── label0001.nii.gz
│ │ ├── label0002.nii.gz
│ │ ├── ...
│ ├── train.txt
│ ├── val.txt
```

Then, use this command to convert synapse dataset.

```shell
python tools/dataset_converters/synapse.py --dataset-path /path/to/synapse
```

Noted that MMSegmentation default evaluation metric (such as mean dice value) is calculated on 2D slice image,
which is not comparable to results of 3D scan in some paper such as [TransUNet](https://arxiv.org/abs/2102.04306).
10 changes: 6 additions & 4 deletions mmseg/datasets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .pascal_context import PascalContextDataset, PascalContextDataset59
from .potsdam import PotsdamDataset
from .stare import STAREDataset
from .synapse import SynapseDataset
# yapf: disable
from .transforms import (CLAHE, AdjustGamma, BioMedical3DPad,
BioMedical3DRandomCrop, BioMedicalGaussianBlur,
Expand All @@ -26,9 +27,9 @@
LoadBiomedicalAnnotation, LoadBiomedicalData,
LoadBiomedicalImageFromFile, LoadImageFromNDArray,
PackSegInputs, PhotoMetricDistortion, RandomCrop,
RandomCutOut, RandomMosaic, RandomRotate, Rerange,
ResizeShortestEdge, ResizeToMultiple, RGB2Gray,
SegRescale)
RandomCutOut, RandomMosaic, RandomRotate,
RandomRotFlip, Rerange, ResizeShortestEdge,
ResizeToMultiple, RGB2Gray, SegRescale)
from .voc import PascalVOCDataset

# yapf: enable
Expand All @@ -46,5 +47,6 @@
'LoadBiomedicalAnnotation', 'LoadBiomedicalData', 'GenerateEdge',
'DecathlonDataset', 'LIPDataset', 'ResizeShortestEdge',
'BioMedicalGaussianNoise', 'BioMedicalGaussianBlur',
'BioMedicalRandomGamma', 'BioMedical3DPad'
'BioMedicalRandomGamma', 'BioMedical3DPad', 'RandomRotFlip',
'SynapseDataset'
]
26 changes: 26 additions & 0 deletions mmseg/datasets/synapse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright (c) OpenMMLab. All rights reserved.
from mmseg.registry import DATASETS
from .basesegdataset import BaseSegDataset


@DATASETS.register_module()
class SynapseDataset(BaseSegDataset):
"""Synapse dataset.

In segmentation map annotation for Synapse, 0 stands for background, which
is not include in 13 categories. The ``img_suffix`` is fixed to '.jpg' and
``seg_map_suffix`` is fixed to '.png'.
"""
METAINFO = dict(
classes=('background', 'aorta', 'gallbladder', 'left_kidney',
'right_kidney', 'liver', 'pancreas', 'spleen', 'stomach'),
palette=[[0, 0, 0], [0, 0, 255], [0, 255, 0], [255, 0, 0],
[0, 255, 255], [255, 0, 255], [255, 255, 0], [60, 255, 255],
[240, 240, 240]])

def __init__(self,
img_suffix='.jpg',
seg_map_suffix='.png',
**kwargs) -> None:
super().__init__(
img_suffix=img_suffix, seg_map_suffix=seg_map_suffix, **kwargs)
8 changes: 4 additions & 4 deletions mmseg/datasets/transforms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
BioMedical3DRandomCrop, BioMedicalGaussianBlur,
BioMedicalGaussianNoise, BioMedicalRandomGamma,
GenerateEdge, PhotoMetricDistortion, RandomCrop,
RandomCutOut, RandomMosaic, RandomRotate, Rerange,
ResizeShortestEdge, ResizeToMultiple, RGB2Gray,
SegRescale)
RandomCutOut, RandomMosaic, RandomRotate,
RandomRotFlip, Rerange, ResizeShortestEdge,
ResizeToMultiple, RGB2Gray, SegRescale)

# yapf: enable
__all__ = [
Expand All @@ -20,5 +20,5 @@
'ResizeToMultiple', 'LoadImageFromNDArray', 'LoadBiomedicalImageFromFile',
'LoadBiomedicalAnnotation', 'LoadBiomedicalData', 'GenerateEdge',
'ResizeShortestEdge', 'BioMedicalGaussianNoise', 'BioMedicalGaussianBlur',
'BioMedicalRandomGamma', 'BioMedical3DPad'
'BioMedicalRandomGamma', 'BioMedical3DPad', 'RandomRotFlip'
]
78 changes: 78 additions & 0 deletions mmseg/datasets/transforms/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,84 @@ def __repr__(self):
return repr_str


@TRANSFORMS.register_module()
class RandomRotFlip(BaseTransform):
"""Rotate and flip the image & seg or just rotate the image & seg.

Required Keys:

- img
- gt_seg_map

Modified Keys:

- img
- gt_seg_map

Args:
rotate_prob (float): The probability of rotate image.
flip_prob (float): The probability of rotate&flip image.
degree (float, tuple[float]): Range of degrees to select from. If
degree is a number instead of tuple like (min, max),
the range of degree will be (``-degree``, ``+degree``)
"""

def __init__(self, rotate_prob=0.5, flip_prob=0.5, degree=(-20, 20)):
self.rotate_prob = rotate_prob
self.flip_prob = flip_prob
assert 0 <= rotate_prob <= 1 and 0 <= flip_prob <= 1
if isinstance(degree, (float, int)):
assert degree > 0, f'degree {degree} should be positive'
self.degree = (-degree, degree)
else:
self.degree = degree
assert len(self.degree) == 2, f'degree {self.degree} should be a ' \
f'tuple of (min, max)'

def random_rot_flip(self, results: dict) -> dict:
k = np.random.randint(0, 4)
results['img'] = np.rot90(results['img'], k)
for key in results.get('seg_fields', []):
results[key] = np.rot90(results[key], k)
axis = np.random.randint(0, 2)
results['img'] = np.flip(results['img'], axis=axis).copy()
for key in results.get('seg_fields', []):
results[key] = np.flip(results[key], axis=axis).copy()
return results

def random_rotate(self, results: dict) -> dict:
angle = np.random.uniform(min(*self.degree), max(*self.degree))
results['img'] = mmcv.imrotate(results['img'], angle=angle)
for key in results.get('seg_fields', []):
results[key] = mmcv.imrotate(results[key], angle=angle)
return results

def transform(self, results: dict) -> dict:
"""Call function to rotate or rotate & flip image, semantic
segmentation maps.

Args:
results (dict): Result dict from loading pipeline.

Returns:
dict: Rotated or rotated & flipped results.
"""
rotate_flag = 0
if random.random() < self.rotate_prob:
results = self.random_rotate(results)
rotate_flag = 1
if random.random() < self.flip_prob and rotate_flag == 0:
results = self.random_rot_flip(results)
return results

def __repr__(self):
repr_str = self.__class__.__name__
repr_str += f'(rotate_prob={self.rotate_prob}, ' \
f'flip_prob={self.flip_prob}, ' \
f'degree={self.degree})'
return repr_str


@TRANSFORMS.register_module()
class RandomMosaic(BaseTransform):
"""Mosaic augmentation. Given 4 images, mosaic transform combines them into
Expand Down
6 changes: 3 additions & 3 deletions mmseg/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
get_palette, isaid_classes, isaid_palette,
loveda_classes, loveda_palette, potsdam_classes,
potsdam_palette, stare_classes, stare_palette,
vaihingen_classes, vaihingen_palette, voc_classes,
voc_palette)
synapse_classes, synapse_palette, vaihingen_classes,
vaihingen_palette, voc_classes, voc_palette)
# yapf: enable
from .collect_env import collect_env
from .io import datafrombytes
Expand All @@ -27,5 +27,5 @@
'cityscapes_palette', 'ade_palette', 'voc_palette', 'cocostuff_palette',
'loveda_palette', 'potsdam_palette', 'vaihingen_palette', 'isaid_palette',
'stare_palette', 'dataset_aliases', 'get_classes', 'get_palette',
'datafrombytes'
'datafrombytes', 'synapse_palette', 'synapse_classes'
]
14 changes: 14 additions & 0 deletions mmseg/utils/class_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,20 @@ def stare_palette():
return [[120, 120, 120], [6, 230, 230]]


def synapse_palette():
"""Synapse palette for external use."""
return [[0, 0, 0], [0, 0, 255], [0, 255, 0], [255, 0, 0], [0, 255, 255],
[255, 0, 255], [255, 255, 0], [60, 255, 255], [240, 240, 240]]


def synapse_classes():
"""Synapse class names for external use."""
return [
'background', 'aorta', 'gallbladder', 'left_kidney', 'right_kidney',
'liver', 'pancreas', 'spleen', 'stomach'
]


def lip_classes():
"""LIP class names for external use."""
return [
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 14 additions & 1 deletion tests/test_datasets/test_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from mmseg.datasets import (ADE20KDataset, BaseSegDataset, CityscapesDataset,
COCOStuffDataset, DecathlonDataset, ISPRSDataset,
LIPDataset, LoveDADataset, PascalVOCDataset,
PotsdamDataset, iSAIDDataset)
PotsdamDataset, SynapseDataset, iSAIDDataset)
from mmseg.registry import DATASETS
from mmseg.utils import get_classes, get_palette

Expand Down Expand Up @@ -220,6 +220,19 @@ def test_vaihingen():
assert len(test_dataset) == 1


def test_synapse():
test_dataset = SynapseDataset(
pipeline=[],
data_prefix=dict(
img_path=osp.join(
osp.dirname(__file__),
'../data/pseudo_synapse_dataset/img_dir'),
seg_map_path=osp.join(
osp.dirname(__file__),
'../data/pseudo_synapse_dataset/ann_dir')))
assert len(test_dataset) == 2


def test_isaid():
test_dataset = iSAIDDataset(
pipeline=[],
Expand Down
Loading