From 67f14204723363553c86df0e6193fe31be680277 Mon Sep 17 00:00:00 2001 From: Junjun2016 Date: Wed, 13 Oct 2021 21:21:17 +0800 Subject: [PATCH] [Enhancement] Add codespell pre-commit hook and fix typos (#920) * add codespell pre-commit hook and fix typos * Update mmseg/models/decode_heads/dpt_head.py * Update mmseg/models/backbones/vit.py * Update mmseg/models/backbones/vit.py * fix typos * skip formating typo * deprecate formating * skip ipynb * unstage ipynb changes * unstage ipynb changes * fix typos in ipynb * unstage ipynb changes --- .github/ISSUE_TEMPLATE/config.yml | 2 +- .github/ISSUE_TEMPLATE/error-report.md | 2 +- .pre-commit-config.yaml | 4 + README.md | 2 +- docs/tutorials/config.md | 8 +- docs/tutorials/customize_runtime.md | 4 +- docs_zh-CN/tutorials/config.md | 2 +- mmseg/core/evaluation/metrics.py | 14 +- mmseg/datasets/pipelines/__init__.py | 4 +- mmseg/datasets/pipelines/formating.py | 292 +----------------- mmseg/datasets/pipelines/formatting.py | 289 +++++++++++++++++ mmseg/models/backbones/bisenetv2.py | 2 +- mmseg/models/backbones/mit.py | 4 +- mmseg/models/backbones/vit.py | 4 +- mmseg/models/decode_heads/dpt_head.py | 2 +- mmseg/models/losses/utils.py | 2 +- mmseg/models/utils/shape_convert.py | 8 +- setup.cfg | 6 + tests/test_models/test_backbones/test_unet.py | 12 +- tests/test_models/test_utils/test_embed.py | 10 +- tools/model_converters/mit2mmseg.py | 6 +- tools/onnx2tensorrt.py | 4 +- tools/pytorch2torchscript.py | 2 +- 23 files changed, 352 insertions(+), 333 deletions(-) create mode 100644 mmseg/datasets/pipelines/formatting.py diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 6eaae3e0d..aa982e548 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -3,4 +3,4 @@ blank_issues_enabled: false contact_links: - name: MMSegmentation Documentation url: https://mmsegmentation.readthedocs.io - about: Check the docs and FAQ to see if you question is already anwsered. + about: Check the docs and FAQ to see if you question is already answered. diff --git a/.github/ISSUE_TEMPLATE/error-report.md b/.github/ISSUE_TEMPLATE/error-report.md index 73a63b7d1..f977b7deb 100644 --- a/.github/ISSUE_TEMPLATE/error-report.md +++ b/.github/ISSUE_TEMPLATE/error-report.md @@ -30,7 +30,7 @@ A clear and concise description of what the bug is. **Environment** -1. Please run `python mmseg/utils/collect_env.py` to collect necessary environment infomation and paste it here. +1. Please run `python mmseg/utils/collect_env.py` to collect necessary environment information and paste it here. 2. You may add addition that may be helpful for locating the problem, such as - How you installed PyTorch [e.g., pip, conda, source] - Other environment variables that may be related (such as `$PATH`, `$LD_LIBRARY_PATH`, `$PYTHONPATH`, etc.) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fc54a6dbf..1f7b75fae 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,6 +34,10 @@ repos: hooks: - id: markdownlint args: ["-r", "~MD002,~MD013,~MD029,~MD033,~MD034,~MD036"] + - repo: https://github.com/codespell-project/codespell + rev: v2.1.0 + hooks: + - id: codespell - repo: https://github.com/myint/docformatter rev: v1.3.1 hooks: diff --git a/README.md b/README.md index 2efdec875..d42729341 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ Please refer to [get_started.md](docs/get_started.md#installation) for installat Please see [train.md](docs/train.md) and [inference.md](docs/inference.md) for the basic usage of MMSegmentation. There are also tutorials for [customizing dataset](docs/tutorials/customize_datasets.md), [designing data pipeline](docs/tutorials/data_pipeline.md), [customizing modules](docs/tutorials/customize_models.md), and [customizing runtime](docs/tutorials/customize_runtime.md). -We also provide many [training tricks](docs/tutorials/training_tricks.md) for better training and [usefule tools](docs/useful_tools.md) for deployment. +We also provide many [training tricks](docs/tutorials/training_tricks.md) for better training and [useful tools](docs/useful_tools.md) for deployment. A Colab tutorial is also provided. You may preview the notebook [here](demo/MMSegmentation_Tutorial.ipynb) or directly [run](https://colab.research.google.com/github/open-mmlab/mmsegmentation/blob/master/demo/MMSegmentation_Tutorial.ipynb) on Colab. diff --git a/docs/tutorials/config.md b/docs/tutorials/config.md index 65efa04fd..940b4212e 100644 --- a/docs/tutorials/config.md +++ b/docs/tutorials/config.md @@ -67,7 +67,7 @@ model = dict( channels=512, # The intermediate channels of decode head. pool_scales=(1, 2, 3, 6), # The avg pooling scales of PSPHead. Please refer to paper for details. dropout_ratio=0.1, # The dropout ratio before final classification layer. - num_classes=19, # Number of segmentation classs. Usually 19 for cityscapes, 21 for VOC, 150 for ADE20k. + num_classes=19, # Number of segmentation class. Usually 19 for cityscapes, 21 for VOC, 150 for ADE20k. norm_cfg=dict(type='SyncBN', requires_grad=True), # The configuration of norm layer. align_corners=False, # The align_corners argument for resize in decoding. loss_decode=dict( # Config of loss function for the decode_head. @@ -82,7 +82,7 @@ model = dict( num_convs=1, # Number of convs in FCNHead. It is usually 1 in auxiliary head. concat_input=False, # Whether concat output of convs with input before classification layer. dropout_ratio=0.1, # The dropout ratio before final classification layer. - num_classes=19, # Number of segmentation classs. Usually 19 for cityscapes, 21 for VOC, 150 for ADE20k. + num_classes=19, # Number of segmentation class. Usually 19 for cityscapes, 21 for VOC, 150 for ADE20k. norm_cfg=dict(type='SyncBN', requires_grad=True), # The configuration of norm layer. align_corners=False, # The align_corners argument for resize in decoding. loss_decode=dict( # Config of loss function for the decode_head. @@ -132,7 +132,7 @@ test_pipeline = [ flip=False, # Whether to flip images during testing transforms=[ dict(type='Resize', # Use resize augmentation - keep_ratio=True), # Whether to keep the ratio between height and width, the img_scale set here will be supressed by the img_scale set above. + keep_ratio=True), # Whether to keep the ratio between height and width, the img_scale set here will be suppressed by the img_scale set above. dict(type='RandomFlip'), # Thought RandomFlip is added in pipeline, it is not used when flip=False dict( type='Normalize', # Normalization config, the values are from img_norm_cfg @@ -245,7 +245,7 @@ runner = dict( checkpoint_config = dict( # Config to set the checkpoint hook, Refer to https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/hooks/checkpoint.py for implementation. by_epoch=False, # Whether count by epoch or not. interval=4000) # The save interval. -evaluation = dict( # The config to build the evaluation hook. Please refer to mmseg/core/evaulation/eval_hook.py for details. +evaluation = dict( # The config to build the evaluation hook. Please refer to mmseg/core/evaluation/eval_hook.py for details. interval=4000, # The interval of evaluation. metric='mIoU') # The evaluation metric. diff --git a/docs/tutorials/customize_runtime.md b/docs/tutorials/customize_runtime.md index 3b9097b43..dba0edc4a 100644 --- a/docs/tutorials/customize_runtime.md +++ b/docs/tutorials/customize_runtime.md @@ -113,7 +113,7 @@ Tricks not implemented by the optimizer should be implemented through optimizer _delete_=True, grad_clip=dict(max_norm=35, norm_type=2)) ``` - If your config inherits the base config which already sets the `optimizer_config`, you might need `_delete_=True` to overide the unnecessary settings. See the [config documenetation](https://mmsegmentation.readthedocs.io/en/latest/config.html) for more details. + If your config inherits the base config which already sets the `optimizer_config`, you might need `_delete_=True` to override the unnecessary settings. See the [config documentation](https://mmsegmentation.readthedocs.io/en/latest/config.html) for more details. - __Use momentum schedule to accelerate model convergence__: We support momentum scheduler to modify model's momentum according to learning rate, which could make the model converge in a faster way. @@ -198,7 +198,7 @@ custom_hooks = [ ### Modify default runtime hooks -There are some common hooks that are not registerd through `custom_hooks`, they are +There are some common hooks that are not registered through `custom_hooks`, they are - log_config - checkpoint_config diff --git a/docs_zh-CN/tutorials/config.md b/docs_zh-CN/tutorials/config.md index 927037d73..e4deca6b6 100644 --- a/docs_zh-CN/tutorials/config.md +++ b/docs_zh-CN/tutorials/config.md @@ -241,7 +241,7 @@ runner = dict( checkpoint_config = dict( # 设置检查点钩子 (checkpoint hook) 的配置文件。执行时请参考 https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/hooks/checkpoint.py。 by_epoch=False, # 是否按照每个 epoch 去算 runner。 interval=4000) # 保存的间隔 -evaluation = dict( # 构建评估钩 (evaluation hook) 的配置文件。细节请参考 mmseg/core/evaulation/eval_hook.py。 +evaluation = dict( # 构建评估钩 (evaluation hook) 的配置文件。细节请参考 mmseg/core/evaluation/eval_hook.py。 interval=4000, # 评估的间歇点 metric='mIoU') # 评估的指标 diff --git a/mmseg/core/evaluation/metrics.py b/mmseg/core/evaluation/metrics.py index b83a798ea..a1c0908e1 100644 --- a/mmseg/core/evaluation/metrics.py +++ b/mmseg/core/evaluation/metrics.py @@ -7,7 +7,7 @@ import torch def f_score(precision, recall, beta=1): - """calcuate the f-score value. + """calculate the f-score value. Args: precision (float | torch.Tensor): The precision value. @@ -40,7 +40,7 @@ def intersect_and_union(pred_label, ignore_index (int): Index that will be ignored in evaluation. label_map (dict): Mapping old labels to new labels. The parameter will work only when label is str. Default: dict(). - reduce_zero_label (bool): Wether ignore zero label. The parameter will + reduce_zero_label (bool): Whether ignore zero label. The parameter will work only when label is str. Default: False. Returns: @@ -102,7 +102,7 @@ def total_intersect_and_union(results, num_classes (int): Number of categories. ignore_index (int): Index that will be ignored in evaluation. label_map (dict): Mapping old labels to new labels. Default: dict(). - reduce_zero_label (bool): Wether ignore zero label. Default: False. + reduce_zero_label (bool): Whether ignore zero label. Default: False. Returns: ndarray: The intersection of prediction and ground truth histogram @@ -148,7 +148,7 @@ def mean_iou(results, nan_to_num (int, optional): If specified, NaN values will be replaced by the numbers defined by the user. Default: None. label_map (dict): Mapping old labels to new labels. Default: dict(). - reduce_zero_label (bool): Wether ignore zero label. Default: False. + reduce_zero_label (bool): Whether ignore zero label. Default: False. Returns: dict[str, float | ndarray]: @@ -187,7 +187,7 @@ def mean_dice(results, nan_to_num (int, optional): If specified, NaN values will be replaced by the numbers defined by the user. Default: None. label_map (dict): Mapping old labels to new labels. Default: dict(). - reduce_zero_label (bool): Wether ignore zero label. Default: False. + reduce_zero_label (bool): Whether ignore zero label. Default: False. Returns: dict[str, float | ndarray]: Default metrics. @@ -228,7 +228,7 @@ def mean_fscore(results, nan_to_num (int, optional): If specified, NaN values will be replaced by the numbers defined by the user. Default: None. label_map (dict): Mapping old labels to new labels. Default: dict(). - reduce_zero_label (bool): Wether ignore zero label. Default: False. + reduce_zero_label (bool): Whether ignore zero label. Default: False. beta (int): Determines the weight of recall in the combined score. Default: False. @@ -274,7 +274,7 @@ def eval_metrics(results, nan_to_num (int, optional): If specified, NaN values will be replaced by the numbers defined by the user. Default: None. label_map (dict): Mapping old labels to new labels. Default: dict(). - reduce_zero_label (bool): Wether ignore zero label. Default: False. + reduce_zero_label (bool): Whether ignore zero label. Default: False. Returns: float: Overall accuracy on all images. ndarray: Per category accuracy, shape (num_classes, ). diff --git a/mmseg/datasets/pipelines/__init__.py b/mmseg/datasets/pipelines/__init__.py index 660291e25..563ae6280 100644 --- a/mmseg/datasets/pipelines/__init__.py +++ b/mmseg/datasets/pipelines/__init__.py @@ -1,7 +1,7 @@ # Copyright (c) OpenMMLab. All rights reserved. from .compose import Compose -from .formating import (Collect, ImageToTensor, ToDataContainer, ToTensor, - Transpose, to_tensor) +from .formatting import (Collect, ImageToTensor, ToDataContainer, ToTensor, + Transpose, to_tensor) from .loading import LoadAnnotations, LoadImageFromFile from .test_time_aug import MultiScaleFlipAug from .transforms import (CLAHE, AdjustGamma, Normalize, Pad, diff --git a/mmseg/datasets/pipelines/formating.py b/mmseg/datasets/pipelines/formating.py index 4e057c1b8..f6e53bfeb 100644 --- a/mmseg/datasets/pipelines/formating.py +++ b/mmseg/datasets/pipelines/formating.py @@ -1,289 +1,9 @@ # Copyright (c) OpenMMLab. All rights reserved. -from collections.abc import Sequence +# flake8: noqa +import warnings -import mmcv -import numpy as np -import torch -from mmcv.parallel import DataContainer as DC +from .formatting import * -from ..builder import PIPELINES - - -def to_tensor(data): - """Convert objects of various python types to :obj:`torch.Tensor`. - - Supported types are: :class:`numpy.ndarray`, :class:`torch.Tensor`, - :class:`Sequence`, :class:`int` and :class:`float`. - - Args: - data (torch.Tensor | numpy.ndarray | Sequence | int | float): Data to - be converted. - """ - - if isinstance(data, torch.Tensor): - return data - elif isinstance(data, np.ndarray): - return torch.from_numpy(data) - elif isinstance(data, Sequence) and not mmcv.is_str(data): - return torch.tensor(data) - elif isinstance(data, int): - return torch.LongTensor([data]) - elif isinstance(data, float): - return torch.FloatTensor([data]) - else: - raise TypeError(f'type {type(data)} cannot be converted to tensor.') - - -@PIPELINES.register_module() -class ToTensor(object): - """Convert some results to :obj:`torch.Tensor` by given keys. - - Args: - keys (Sequence[str]): Keys that need to be converted to Tensor. - """ - - def __init__(self, keys): - self.keys = keys - - def __call__(self, results): - """Call function to convert data in results to :obj:`torch.Tensor`. - - Args: - results (dict): Result dict contains the data to convert. - - Returns: - dict: The result dict contains the data converted - to :obj:`torch.Tensor`. - """ - - for key in self.keys: - results[key] = to_tensor(results[key]) - return results - - def __repr__(self): - return self.__class__.__name__ + f'(keys={self.keys})' - - -@PIPELINES.register_module() -class ImageToTensor(object): - """Convert image to :obj:`torch.Tensor` by given keys. - - The dimension order of input image is (H, W, C). The pipeline will convert - it to (C, H, W). If only 2 dimension (H, W) is given, the output would be - (1, H, W). - - Args: - keys (Sequence[str]): Key of images to be converted to Tensor. - """ - - def __init__(self, keys): - self.keys = keys - - def __call__(self, results): - """Call function to convert image in results to :obj:`torch.Tensor` and - transpose the channel order. - - Args: - results (dict): Result dict contains the image data to convert. - - Returns: - dict: The result dict contains the image converted - to :obj:`torch.Tensor` and transposed to (C, H, W) order. - """ - - for key in self.keys: - img = results[key] - if len(img.shape) < 3: - img = np.expand_dims(img, -1) - results[key] = to_tensor(img.transpose(2, 0, 1)) - return results - - def __repr__(self): - return self.__class__.__name__ + f'(keys={self.keys})' - - -@PIPELINES.register_module() -class Transpose(object): - """Transpose some results by given keys. - - Args: - keys (Sequence[str]): Keys of results to be transposed. - order (Sequence[int]): Order of transpose. - """ - - def __init__(self, keys, order): - self.keys = keys - self.order = order - - def __call__(self, results): - """Call function to convert image in results to :obj:`torch.Tensor` and - transpose the channel order. - - Args: - results (dict): Result dict contains the image data to convert. - - Returns: - dict: The result dict contains the image converted - to :obj:`torch.Tensor` and transposed to (C, H, W) order. - """ - - for key in self.keys: - results[key] = results[key].transpose(self.order) - return results - - def __repr__(self): - return self.__class__.__name__ + \ - f'(keys={self.keys}, order={self.order})' - - -@PIPELINES.register_module() -class ToDataContainer(object): - """Convert results to :obj:`mmcv.DataContainer` by given fields. - - Args: - fields (Sequence[dict]): Each field is a dict like - ``dict(key='xxx', **kwargs)``. The ``key`` in result will - be converted to :obj:`mmcv.DataContainer` with ``**kwargs``. - Default: ``(dict(key='img', stack=True), - dict(key='gt_semantic_seg'))``. - """ - - def __init__(self, - fields=(dict(key='img', - stack=True), dict(key='gt_semantic_seg'))): - self.fields = fields - - def __call__(self, results): - """Call function to convert data in results to - :obj:`mmcv.DataContainer`. - - Args: - results (dict): Result dict contains the data to convert. - - Returns: - dict: The result dict contains the data converted to - :obj:`mmcv.DataContainer`. - """ - - for field in self.fields: - field = field.copy() - key = field.pop('key') - results[key] = DC(results[key], **field) - return results - - def __repr__(self): - return self.__class__.__name__ + f'(fields={self.fields})' - - -@PIPELINES.register_module() -class DefaultFormatBundle(object): - """Default formatting bundle. - - It simplifies the pipeline of formatting common fields, including "img" - and "gt_semantic_seg". These fields are formatted as follows. - - - img: (1)transpose, (2)to tensor, (3)to DataContainer (stack=True) - - gt_semantic_seg: (1)unsqueeze dim-0 (2)to tensor, - (3)to DataContainer (stack=True) - """ - - def __call__(self, results): - """Call function to transform and format common fields in results. - - Args: - results (dict): Result dict contains the data to convert. - - Returns: - dict: The result dict contains the data that is formatted with - default bundle. - """ - - if 'img' in results: - img = results['img'] - if len(img.shape) < 3: - img = np.expand_dims(img, -1) - img = np.ascontiguousarray(img.transpose(2, 0, 1)) - results['img'] = DC(to_tensor(img), stack=True) - if 'gt_semantic_seg' in results: - # convert to long - results['gt_semantic_seg'] = DC( - to_tensor(results['gt_semantic_seg'][None, - ...].astype(np.int64)), - stack=True) - return results - - def __repr__(self): - return self.__class__.__name__ - - -@PIPELINES.register_module() -class Collect(object): - """Collect data from the loader relevant to the specific task. - - This is usually the last stage of the data loader pipeline. Typically keys - is set to some subset of "img", "gt_semantic_seg". - - The "img_meta" item is always populated. The contents of the "img_meta" - dictionary depends on "meta_keys". By default this includes: - - - "img_shape": shape of the image input to the network as a tuple - (h, w, c). Note that images may be zero padded on the bottom/right - if the batch tensor is larger than this shape. - - - "scale_factor": a float indicating the preprocessing scale - - - "flip": a boolean indicating if image flip transform was used - - - "filename": path to the image file - - - "ori_shape": original shape of the image as a tuple (h, w, c) - - - "pad_shape": image shape after padding - - - "img_norm_cfg": a dict of normalization information: - - mean - per channel mean subtraction - - std - per channel std divisor - - to_rgb - bool indicating if bgr was converted to rgb - - Args: - keys (Sequence[str]): Keys of results to be collected in ``data``. - meta_keys (Sequence[str], optional): Meta keys to be converted to - ``mmcv.DataContainer`` and collected in ``data[img_metas]``. - Default: (``filename``, ``ori_filename``, ``ori_shape``, - ``img_shape``, ``pad_shape``, ``scale_factor``, ``flip``, - ``flip_direction``, ``img_norm_cfg``) - """ - - def __init__(self, - keys, - meta_keys=('filename', 'ori_filename', 'ori_shape', - 'img_shape', 'pad_shape', 'scale_factor', 'flip', - 'flip_direction', 'img_norm_cfg')): - self.keys = keys - self.meta_keys = meta_keys - - def __call__(self, results): - """Call function to collect keys in results. The keys in ``meta_keys`` - will be converted to :obj:mmcv.DataContainer. - - Args: - results (dict): Result dict contains the data to collect. - - Returns: - dict: The result dict contains the following keys - - keys in``self.keys`` - - ``img_metas`` - """ - - data = {} - img_meta = {} - for key in self.meta_keys: - img_meta[key] = results[key] - data['img_metas'] = DC(img_meta, cpu_only=True) - for key in self.keys: - data[key] = results[key] - return data - - def __repr__(self): - return self.__class__.__name__ + \ - f'(keys={self.keys}, meta_keys={self.meta_keys})' +warnings.warn('DeprecationWarning: mmseg.datasets.pipelines.formating will be ' + 'deprecated in 2021, please replace it with ' + 'mmseg.datasets.pipelines.formatting.') diff --git a/mmseg/datasets/pipelines/formatting.py b/mmseg/datasets/pipelines/formatting.py new file mode 100644 index 000000000..4e057c1b8 --- /dev/null +++ b/mmseg/datasets/pipelines/formatting.py @@ -0,0 +1,289 @@ +# Copyright (c) OpenMMLab. All rights reserved. +from collections.abc import Sequence + +import mmcv +import numpy as np +import torch +from mmcv.parallel import DataContainer as DC + +from ..builder import PIPELINES + + +def to_tensor(data): + """Convert objects of various python types to :obj:`torch.Tensor`. + + Supported types are: :class:`numpy.ndarray`, :class:`torch.Tensor`, + :class:`Sequence`, :class:`int` and :class:`float`. + + Args: + data (torch.Tensor | numpy.ndarray | Sequence | int | float): Data to + be converted. + """ + + if isinstance(data, torch.Tensor): + return data + elif isinstance(data, np.ndarray): + return torch.from_numpy(data) + elif isinstance(data, Sequence) and not mmcv.is_str(data): + return torch.tensor(data) + elif isinstance(data, int): + return torch.LongTensor([data]) + elif isinstance(data, float): + return torch.FloatTensor([data]) + else: + raise TypeError(f'type {type(data)} cannot be converted to tensor.') + + +@PIPELINES.register_module() +class ToTensor(object): + """Convert some results to :obj:`torch.Tensor` by given keys. + + Args: + keys (Sequence[str]): Keys that need to be converted to Tensor. + """ + + def __init__(self, keys): + self.keys = keys + + def __call__(self, results): + """Call function to convert data in results to :obj:`torch.Tensor`. + + Args: + results (dict): Result dict contains the data to convert. + + Returns: + dict: The result dict contains the data converted + to :obj:`torch.Tensor`. + """ + + for key in self.keys: + results[key] = to_tensor(results[key]) + return results + + def __repr__(self): + return self.__class__.__name__ + f'(keys={self.keys})' + + +@PIPELINES.register_module() +class ImageToTensor(object): + """Convert image to :obj:`torch.Tensor` by given keys. + + The dimension order of input image is (H, W, C). The pipeline will convert + it to (C, H, W). If only 2 dimension (H, W) is given, the output would be + (1, H, W). + + Args: + keys (Sequence[str]): Key of images to be converted to Tensor. + """ + + def __init__(self, keys): + self.keys = keys + + def __call__(self, results): + """Call function to convert image in results to :obj:`torch.Tensor` and + transpose the channel order. + + Args: + results (dict): Result dict contains the image data to convert. + + Returns: + dict: The result dict contains the image converted + to :obj:`torch.Tensor` and transposed to (C, H, W) order. + """ + + for key in self.keys: + img = results[key] + if len(img.shape) < 3: + img = np.expand_dims(img, -1) + results[key] = to_tensor(img.transpose(2, 0, 1)) + return results + + def __repr__(self): + return self.__class__.__name__ + f'(keys={self.keys})' + + +@PIPELINES.register_module() +class Transpose(object): + """Transpose some results by given keys. + + Args: + keys (Sequence[str]): Keys of results to be transposed. + order (Sequence[int]): Order of transpose. + """ + + def __init__(self, keys, order): + self.keys = keys + self.order = order + + def __call__(self, results): + """Call function to convert image in results to :obj:`torch.Tensor` and + transpose the channel order. + + Args: + results (dict): Result dict contains the image data to convert. + + Returns: + dict: The result dict contains the image converted + to :obj:`torch.Tensor` and transposed to (C, H, W) order. + """ + + for key in self.keys: + results[key] = results[key].transpose(self.order) + return results + + def __repr__(self): + return self.__class__.__name__ + \ + f'(keys={self.keys}, order={self.order})' + + +@PIPELINES.register_module() +class ToDataContainer(object): + """Convert results to :obj:`mmcv.DataContainer` by given fields. + + Args: + fields (Sequence[dict]): Each field is a dict like + ``dict(key='xxx', **kwargs)``. The ``key`` in result will + be converted to :obj:`mmcv.DataContainer` with ``**kwargs``. + Default: ``(dict(key='img', stack=True), + dict(key='gt_semantic_seg'))``. + """ + + def __init__(self, + fields=(dict(key='img', + stack=True), dict(key='gt_semantic_seg'))): + self.fields = fields + + def __call__(self, results): + """Call function to convert data in results to + :obj:`mmcv.DataContainer`. + + Args: + results (dict): Result dict contains the data to convert. + + Returns: + dict: The result dict contains the data converted to + :obj:`mmcv.DataContainer`. + """ + + for field in self.fields: + field = field.copy() + key = field.pop('key') + results[key] = DC(results[key], **field) + return results + + def __repr__(self): + return self.__class__.__name__ + f'(fields={self.fields})' + + +@PIPELINES.register_module() +class DefaultFormatBundle(object): + """Default formatting bundle. + + It simplifies the pipeline of formatting common fields, including "img" + and "gt_semantic_seg". These fields are formatted as follows. + + - img: (1)transpose, (2)to tensor, (3)to DataContainer (stack=True) + - gt_semantic_seg: (1)unsqueeze dim-0 (2)to tensor, + (3)to DataContainer (stack=True) + """ + + def __call__(self, results): + """Call function to transform and format common fields in results. + + Args: + results (dict): Result dict contains the data to convert. + + Returns: + dict: The result dict contains the data that is formatted with + default bundle. + """ + + if 'img' in results: + img = results['img'] + if len(img.shape) < 3: + img = np.expand_dims(img, -1) + img = np.ascontiguousarray(img.transpose(2, 0, 1)) + results['img'] = DC(to_tensor(img), stack=True) + if 'gt_semantic_seg' in results: + # convert to long + results['gt_semantic_seg'] = DC( + to_tensor(results['gt_semantic_seg'][None, + ...].astype(np.int64)), + stack=True) + return results + + def __repr__(self): + return self.__class__.__name__ + + +@PIPELINES.register_module() +class Collect(object): + """Collect data from the loader relevant to the specific task. + + This is usually the last stage of the data loader pipeline. Typically keys + is set to some subset of "img", "gt_semantic_seg". + + The "img_meta" item is always populated. The contents of the "img_meta" + dictionary depends on "meta_keys". By default this includes: + + - "img_shape": shape of the image input to the network as a tuple + (h, w, c). Note that images may be zero padded on the bottom/right + if the batch tensor is larger than this shape. + + - "scale_factor": a float indicating the preprocessing scale + + - "flip": a boolean indicating if image flip transform was used + + - "filename": path to the image file + + - "ori_shape": original shape of the image as a tuple (h, w, c) + + - "pad_shape": image shape after padding + + - "img_norm_cfg": a dict of normalization information: + - mean - per channel mean subtraction + - std - per channel std divisor + - to_rgb - bool indicating if bgr was converted to rgb + + Args: + keys (Sequence[str]): Keys of results to be collected in ``data``. + meta_keys (Sequence[str], optional): Meta keys to be converted to + ``mmcv.DataContainer`` and collected in ``data[img_metas]``. + Default: (``filename``, ``ori_filename``, ``ori_shape``, + ``img_shape``, ``pad_shape``, ``scale_factor``, ``flip``, + ``flip_direction``, ``img_norm_cfg``) + """ + + def __init__(self, + keys, + meta_keys=('filename', 'ori_filename', 'ori_shape', + 'img_shape', 'pad_shape', 'scale_factor', 'flip', + 'flip_direction', 'img_norm_cfg')): + self.keys = keys + self.meta_keys = meta_keys + + def __call__(self, results): + """Call function to collect keys in results. The keys in ``meta_keys`` + will be converted to :obj:mmcv.DataContainer. + + Args: + results (dict): Result dict contains the data to collect. + + Returns: + dict: The result dict contains the following keys + - keys in``self.keys`` + - ``img_metas`` + """ + + data = {} + img_meta = {} + for key in self.meta_keys: + img_meta[key] = results[key] + data['img_metas'] = DC(img_meta, cpu_only=True) + for key in self.keys: + data[key] = results[key] + return data + + def __repr__(self): + return self.__class__.__name__ + \ + f'(keys={self.keys}, meta_keys={self.meta_keys})' diff --git a/mmseg/models/backbones/bisenetv2.py b/mmseg/models/backbones/bisenetv2.py index eb05e10d5..d908b321c 100644 --- a/mmseg/models/backbones/bisenetv2.py +++ b/mmseg/models/backbones/bisenetv2.py @@ -194,7 +194,7 @@ class GELayer(BaseModule): init_cfg (dict or list[dict], optional): Initialization config dict. Default: None. Returns: - x (torch.Tensor): Intermidiate feature map in + x (torch.Tensor): Intermediate feature map in Semantic Branch. """ diff --git a/mmseg/models/backbones/mit.py b/mmseg/models/backbones/mit.py index 54d985660..c58e5637e 100644 --- a/mmseg/models/backbones/mit.py +++ b/mmseg/models/backbones/mit.py @@ -186,7 +186,7 @@ class TransformerEncoderLayer(BaseModule): qkv_bias (bool): enable bias for qkv if True. Default: True. act_cfg (dict): The activation config for FFNs. - Defalut: dict(type='GELU'). + Default: dict(type='GELU'). norm_cfg (dict): Config dict for normalization layer. Default: dict(type='LN'). batch_first (bool): Key, Query and Value are shape of @@ -277,7 +277,7 @@ class MixVisionTransformer(BaseModule): norm_cfg (dict): Config dict for normalization layer. Default: dict(type='LN') act_cfg (dict): The activation config for FFNs. - Defalut: dict(type='GELU'). + Default: dict(type='GELU'). pretrained (str, optional): model pretrained path. Default: None. init_cfg (dict or list[dict], optional): Initialization config dict. Default: None. diff --git a/mmseg/models/backbones/vit.py b/mmseg/models/backbones/vit.py index 593996400..9c099d2ee 100644 --- a/mmseg/models/backbones/vit.py +++ b/mmseg/models/backbones/vit.py @@ -33,7 +33,7 @@ class TransformerEncoderLayer(BaseModule): Default: 2. qkv_bias (bool): enable bias for qkv if True. Default: True act_cfg (dict): The activation config for FFNs. - Defalut: dict(type='GELU'). + Default: dict(type='GELU'). norm_cfg (dict): Config dict for normalization layer. Default: dict(type='LN'). batch_first (bool): Key, Query and Value are shape of @@ -126,7 +126,7 @@ class VisionTransformer(BaseModule): norm_cfg (dict): Config dict for normalization layer. Default: dict(type='LN') act_cfg (dict): The activation config for FFNs. - Defalut: dict(type='GELU'). + Default: dict(type='GELU'). patch_norm (bool): Whether to add a norm in PatchEmbed Block. Default: False. final_norm (bool): Whether to add a additional layer to normalize diff --git a/mmseg/models/decode_heads/dpt_head.py b/mmseg/models/decode_heads/dpt_head.py index 7028f2a23..a63f9d297 100644 --- a/mmseg/models/decode_heads/dpt_head.py +++ b/mmseg/models/decode_heads/dpt_head.py @@ -227,7 +227,7 @@ class DPTHead(BaseDecodeHead): expand_channels (bool): Whether expand the channels in post process block. Default: False. act_cfg (dict): The activation config for residual conv unit. - Defalut dict(type='ReLU'). + Default dict(type='ReLU'). norm_cfg (dict): Config dict for normalization layer. Default: dict(type='BN'). """ diff --git a/mmseg/models/losses/utils.py b/mmseg/models/losses/utils.py index c57e4b18a..c37875fad 100644 --- a/mmseg/models/losses/utils.py +++ b/mmseg/models/losses/utils.py @@ -51,7 +51,7 @@ def weight_reduce_loss(loss, weight=None, reduction='mean', avg_factor=None): loss (Tensor): Element-wise loss. weight (Tensor): Element-wise weights. reduction (str): Same as built-in losses of PyTorch. - avg_factor (float): Avarage factor when computing the mean of losses. + avg_factor (float): Average factor when computing the mean of losses. Returns: Tensor: Processed loss values. diff --git a/mmseg/models/utils/shape_convert.py b/mmseg/models/utils/shape_convert.py index 34c8648c4..0677348c8 100644 --- a/mmseg/models/utils/shape_convert.py +++ b/mmseg/models/utils/shape_convert.py @@ -3,11 +3,11 @@ def nlc_to_nchw(x, hw_shape): """Convert [N, L, C] shape tensor to [N, C, H, W] shape tensor. Args: - x (Tensor): The input tensor of shape [N, L, C] before convertion. + x (Tensor): The input tensor of shape [N, L, C] before conversion. hw_shape (Sequence[int]): The height and width of output feature map. Returns: - Tensor: The output tensor of shape [N, C, H, W] after convertion. + Tensor: The output tensor of shape [N, C, H, W] after conversion. """ H, W = hw_shape assert len(x.shape) == 3 @@ -20,10 +20,10 @@ def nchw_to_nlc(x): """Flatten [N, C, H, W] shape tensor to [N, L, C] shape tensor. Args: - x (Tensor): The input tensor of shape [N, C, H, W] before convertion. + x (Tensor): The input tensor of shape [N, C, H, W] before conversion. Returns: - Tensor: The output tensor of shape [N, L, C] after convertion. + Tensor: The output tensor of shape [N, L, C] after conversion. """ assert len(x.shape) == 4 return x.flatten(2).transpose(1, 2).contiguous() diff --git a/setup.cfg b/setup.cfg index 8605ae939..1045a9a85 100644 --- a/setup.cfg +++ b/setup.cfg @@ -11,3 +11,9 @@ known_first_party = mmseg known_third_party = PIL,cityscapesscripts,cv2,detail,matplotlib,mmcv,numpy,onnxruntime,packaging,prettytable,pytest,pytorch_sphinx_theme,requests,scipy,seaborn,torch,ts no_lines_before = STDLIB,LOCALFOLDER default_section = THIRDPARTY + +[codespell] +skip = *.po,*.ts,*.ipynb +count = +quiet-level = 3 +ignore-words-list = formating,sur,hist diff --git a/tests/test_models/test_backbones/test_unet.py b/tests/test_models/test_backbones/test_unet.py index c4f2faca3..9beb7279a 100644 --- a/tests/test_models/test_backbones/test_unet.py +++ b/tests/test_models/test_backbones/test_unet.py @@ -425,7 +425,7 @@ def test_unet(): unet(x) with pytest.raises(AssertionError): - # Check if num_stages matchs strides, len(strides)=num_stages + # Check if num_stages matches strides, len(strides)=num_stages unet = UNet( in_channels=3, base_channels=4, @@ -440,7 +440,7 @@ def test_unet(): unet(x) with pytest.raises(AssertionError): - # Check if num_stages matchs strides, len(enc_num_convs)=num_stages + # Check if num_stages matches strides, len(enc_num_convs)=num_stages unet = UNet( in_channels=3, base_channels=4, @@ -455,7 +455,7 @@ def test_unet(): unet(x) with pytest.raises(AssertionError): - # Check if num_stages matchs strides, len(dec_num_convs)=num_stages-1 + # Check if num_stages matches strides, len(dec_num_convs)=num_stages-1 unet = UNet( in_channels=3, base_channels=4, @@ -470,7 +470,7 @@ def test_unet(): unet(x) with pytest.raises(AssertionError): - # Check if num_stages matchs strides, len(downsamples)=num_stages-1 + # Check if num_stages matches strides, len(downsamples)=num_stages-1 unet = UNet( in_channels=3, base_channels=4, @@ -485,7 +485,7 @@ def test_unet(): unet(x) with pytest.raises(AssertionError): - # Check if num_stages matchs strides, len(enc_dilations)=num_stages + # Check if num_stages matches strides, len(enc_dilations)=num_stages unet = UNet( in_channels=3, base_channels=4, @@ -500,7 +500,7 @@ def test_unet(): unet(x) with pytest.raises(AssertionError): - # Check if num_stages matchs strides, len(dec_dilations)=num_stages-1 + # Check if num_stages matches strides, len(dec_dilations)=num_stages-1 unet = UNet( in_channels=3, base_channels=4, diff --git a/tests/test_models/test_utils/test_embed.py b/tests/test_models/test_utils/test_embed.py index 2c6857dc7..be20c97b0 100644 --- a/tests/test_models/test_utils/test_embed.py +++ b/tests/test_models/test_utils/test_embed.py @@ -173,7 +173,7 @@ def test_patch_embed(): # test L = out_h * out_w assert shape[0] * shape[1] == x3.shape[1] - # test thte init_out_size with nn.Unfold + # test the init_out_size with nn.Unfold assert patch_merge_3.init_out_size[1] == (input_size[0] - 2 * 4 - 1) // 2 + 1 assert patch_merge_3.init_out_size[0] == (input_size[0] - 2 * 4 - @@ -195,7 +195,7 @@ def test_patch_embed(): _, shape = patch_merge_3(dummy_input) # when input_size equal to real input - # the out_size shoule be equal to `init_out_size` + # the out_size should be equal to `init_out_size` assert shape == patch_merge_3.init_out_size input_size = (H, W) @@ -213,7 +213,7 @@ def test_patch_embed(): _, shape = patch_merge_3(dummy_input) # when input_size equal to real input - # the out_size shoule be equal to `init_out_size` + # the out_size should be equal to `init_out_size` assert shape == patch_merge_3.init_out_size # test adap padding @@ -288,7 +288,7 @@ def test_patch_embed(): assert out_size == (2, 1) assert x_out.size(1) == out_size[0] * out_size[1] - # test different kernel_size with diffrent stride + # test different kernel_size with different stride input_size = (6, 5) kernel_size = (6, 2) stride = (6, 2) @@ -437,7 +437,7 @@ def test_patch_merging(): assert out_size == (2, 1) assert x_out.size(1) == out_size[0] * out_size[1] - # test different kernel_size with diffrent stride + # test different kernel_size with different stride input_size = (6, 5) kernel_size = (6, 2) stride = (6, 2) diff --git a/tools/model_converters/mit2mmseg.py b/tools/model_converters/mit2mmseg.py index 37e9b9476..2eff1f7b7 100644 --- a/tools/model_converters/mit2mmseg.py +++ b/tools/model_converters/mit2mmseg.py @@ -14,14 +14,14 @@ def convert_mit(ckpt): for k, v in ckpt.items(): if k.startswith('head'): continue - # patch embedding convertion + # patch embedding conversion elif k.startswith('patch_embed'): stage_i = int(k.split('.')[0].replace('patch_embed', '')) new_k = k.replace(f'patch_embed{stage_i}', f'layers.{stage_i-1}.0') new_v = v if 'proj.' in new_k: new_k = new_k.replace('proj.', 'projection.') - # transformer encoder layer convertion + # transformer encoder layer conversion elif k.startswith('block'): stage_i = int(k.split('.')[0].replace('block', '')) new_k = k.replace(f'block{stage_i}', f'layers.{stage_i-1}.1') @@ -45,7 +45,7 @@ def convert_mit(ckpt): new_k = new_k.replace('dwconv.dwconv.', '1.') new_k = new_k.replace('fc2.', '4.') string += f'{new_k} {v.shape}-{new_v.shape}' - # norm layer convertion + # norm layer conversion elif k.startswith('norm'): stage_i = int(k.split('.')[0].replace('norm', '')) new_k = k.replace(f'norm{stage_i}', f'layers.{stage_i-1}.2') diff --git a/tools/onnx2tensorrt.py b/tools/onnx2tensorrt.py index 1cda22249..f8a258fc8 100644 --- a/tools/onnx2tensorrt.py +++ b/tools/onnx2tensorrt.py @@ -117,7 +117,7 @@ def onnx2tensorrt(onnx_file: str, import tensorrt as trt min_shape = input_config['min_shape'] max_shape = input_config['max_shape'] - # create trt engine and wraper + # create trt engine and wrapper opt_shape_dict = {'input': [min_shape, min_shape, max_shape]} max_workspace_size = get_GiB(workspace_size) trt_engine = onnx2trt( @@ -254,7 +254,7 @@ if __name__ == '__main__': 'Dataset {} does not found.'.format(args.dataset) for max_value, min_value in zip(args.max_shape, args.min_shape): assert max_value >= min_value, \ - 'max_shape sould be larger than min shape' + 'max_shape should be larger than min shape' input_config = { 'min_shape': args.min_shape, diff --git a/tools/pytorch2torchscript.py b/tools/pytorch2torchscript.py index fad6fd142..d76f5ecb9 100644 --- a/tools/pytorch2torchscript.py +++ b/tools/pytorch2torchscript.py @@ -113,7 +113,7 @@ def pytorch2libtorch(model, imgs = mm_inputs.pop('imgs') - # replace the orginal forword with forward_dummy + # replace the original forword with forward_dummy model.forward = model.forward_dummy model.eval() traced_model = torch.jit.trace(