diff --git a/docs/en/_static/image/tools/visualization/pipeline-concat.jpg b/docs/en/_static/image/tools/visualization/pipeline-concat.jpg
deleted file mode 100644
index e5e69974..00000000
Binary files a/docs/en/_static/image/tools/visualization/pipeline-concat.jpg and /dev/null differ
diff --git a/docs/en/_static/image/tools/visualization/pipeline-original.jpg b/docs/en/_static/image/tools/visualization/pipeline-original.jpg
deleted file mode 100644
index fa23a029..00000000
Binary files a/docs/en/_static/image/tools/visualization/pipeline-original.jpg and /dev/null differ
diff --git a/docs/en/_static/image/tools/visualization/pipeline-pipeline.jpg b/docs/en/_static/image/tools/visualization/pipeline-pipeline.jpg
deleted file mode 100644
index aa7df13b..00000000
Binary files a/docs/en/_static/image/tools/visualization/pipeline-pipeline.jpg and /dev/null differ
diff --git a/docs/en/tools/miscellaneous.md b/docs/en/tools/miscellaneous.md
index 0463b525..4e66d91a 100644
--- a/docs/en/tools/miscellaneous.md
+++ b/docs/en/tools/miscellaneous.md
@@ -1,4 +1,4 @@
-# MISCELLANEOUS
+# Miscellaneous
diff --git a/docs/en/tools/visualization.md b/docs/en/tools/visualization.md
index a519b972..f224fe68 100644
--- a/docs/en/tools/visualization.md
+++ b/docs/en/tools/visualization.md
@@ -2,11 +2,10 @@
-- [Visualization](#visualization)
- - [Pipeline Visualization](#pipeline-visualization)
- - [Learning Rate Schedule Visualization](#learning-rate-schedule-visualization)
- - [Class Activation Map Visualization](#class-activation-map-visualization)
- - [FAQs](#faqs)
+- [Pipeline Visualization](#pipeline-visualization)
+- [Learning Rate Schedule Visualization](#learning-rate-schedule-visualization)
+- [Class Activation Map Visualization](#class-activation-map-visualization)
+- [FAQs](#faqs)
## Pipeline Visualization
@@ -14,17 +13,18 @@
```bash
python tools/visualizations/vis_pipeline.py \
${CONFIG_FILE} \
- --output-dir ${OUTPUT_DIR} \
- --phase ${DATASET_PHASE} \
- --number ${BUNBER_IMAGES_DISPLAY} \
- --skip-type ${SKIP_TRANSFORM_TYPE}
- --mode ${DISPLAY_MODE} \
- --show \
- --adaptive \
- --min-edge-length ${MIN_EDGE_LENGTH} \
- --max-edge-length ${MAX_EDGE_LENGTH} \
- --bgr2rgb \
- --window-size ${WINDOW_SIZE}
+ [--output-dir ${OUTPUT_DIR}] \
+ [--phase ${DATASET_PHASE}] \
+ [--number ${BUNBER_IMAGES_DISPLAY}] \
+ [--skip-type ${SKIP_TRANSFORM_TYPE}] \
+ [--mode ${DISPLAY_MODE}] \
+ [--show] \
+ [--adaptive] \
+ [--min-edge-length ${MIN_EDGE_LENGTH}] \
+ [--max-edge-length ${MAX_EDGE_LENGTH}] \
+ [--bgr2rgb] \
+ [--window-size ${WINDOW_SIZE}] \
+ [--cfg-options ${CFG_OPTIONS}]
```
**Description of all arguments**:
@@ -32,48 +32,57 @@ python tools/visualizations/vis_pipeline.py \
- `config` : The path of a model config file.
- `--output-dir`: The output path for visualized images. If not specified, it will be set to `''`, which means not to save.
- `--phase`: Phase of visualizing dataset,must be one of `[train, val, test]`. If not specified, it will be set to `train`.
-- `--number`: The number of samples to visualize. If not specified, display all images in the dataset.
+- `--number`: The number of samples to visualized. If not specified, display all images in the dataset.
- `--skip-type`: The pipelines to be skipped. If not specified, it will be set to `['ToTensor', 'Normalize', 'ImageToTensor', 'Collect']`.
- `--mode`: The display mode, can be one of `[original, pipeline, concat]`. If not specified, it will be set to `concat`.
- `--show`: If set, display pictures in pop-up windows.
-- `--adaptive`: If set, automatically adjust the size of the visualization images.
+- `--adaptive`: If set, adaptively resize images for better visualization.
- `--min-edge-length`: The minimum edge length, used when `--adaptive` is set. When any side of the picture is smaller than `${MIN_EDGE_LENGTH}`, the picture will be enlarged while keeping the aspect ratio unchanged, and the short side will be aligned to `${MIN_EDGE_LENGTH}`. If not specified, it will be set to 200.
- `--max-edge-length`: The maximum edge length, used when `--adaptive` is set. When any side of the picture is larger than `${MAX_EDGE_LENGTH}`, the picture will be reduced while keeping the aspect ratio unchanged, and the long side will be aligned to `${MAX_EDGE_LENGTH}`. If not specified, it will be set to 1000.
- `--bgr2rgb`: If set, flip the color channel order of images.
- `--window-size`: The shape of the display window. If not specified, it will be set to `12*7`. If used, it must be in the format `'W*H'`.
+- `--cfg-options` : Modifications to the configuration file, refer to [Tutorial 1: Learn about Configs](https://mmclassification.readthedocs.io/en/latest/tutorials/config.html).
```{note}
-1. If the `--mode` is not specified, it will be set to `concat` as default, get the pictures stitched together by original pictures and transformed pictures; if the `--mode` is set to `original`, get the original pictures; if the `--mode` is set to `pipeline`, get the transformed pictures.
+1. If the `--mode` is not specified, it will be set to `concat` as default, get the pictures stitched together by original pictures and transformed pictures; if the `--mode` is set to `original`, get the original pictures; if the `--mode` is set to `transformed`, get the transformed pictures; if the `--mode` is set to `pipeline`, get all the intermediate images through the pipeline.
2. When `--adaptive` option is set, images that are too large or too small will be automatically adjusted, you can use `--min-edge-length` and `--max-edge-length` to set the adjust size.
```
**Examples**:
-1. Visualize all the transformed pictures of the `ImageNet` training set and display them in pop-up windows:
+1. In **'original'** mode, visualize 100 original pictures in the `CIFAR100` validation set, then display and save them in the `./tmp` folder:
- ```shell
- python ./tools/visualizations/vis_pipeline.py ./configs/resnet/resnet50_8xb32_in1k.py --show --mode pipeline
- ```
+ ```shell
+ python ./tools/visualizations/vis_pipeline.py configs/resnet/resnet50_8xb16_cifar100.py --phase val --output-dir tmp --mode original --number 100 --show --adaptive --bgr2rgb
+ ```
-

+ 
-2. Visualize 10 comparison pictures in the `ImageNet` train set and save them in the `./tmp` folder:
+2. In **'transformed'** mode, visualize all the transformed pictures of the `ImageNet` training set and display them in pop-up windows:
- ```shell
- python ./tools/visualizations/vis_pipeline.py configs/swin_transformer/swin_base_224_b16x64_300e_imagenet.py --phase train --output-dir tmp --number 10 --adaptive
- ```
+ ```shell
+ python ./tools/visualizations/vis_pipeline.py ./configs/resnet/resnet50_8xb32_in1k.py --show --mode transformed
+ ```
- 
+ 
-3. Visualize 100 original pictures in the `CIFAR100` validation set, then display and save them in the `./tmp` folder:
+3. In **'concat'** mode, visualize 10 pairs of origin and transformed images for comparison in the `ImageNet` train set and save them in the `./tmp` folder:
- ```shell
- python ./tools/visualizations/vis_pipeline.py configs/resnet/resnet50_8xb16_cifar100.py --phase val --output-dir tmp --mode original --number 100 --show --adaptive --bgr2rgb
- ```
+ ```shell
+ python ./tools/visualizations/vis_pipeline.py configs/swin_transformer/swin_base_224_b16x64_300e_imagenet.py --phase train --output-dir tmp --number 10 --adaptive
+ ```
- 
+ 
+
+4. In **'pipeline'** mode, visualize all the intermediate pictures in the `ImageNet` train set through the pipeline:
+
+ ```shell
+ python ./tools/visualizations/vis_pipeline.py configs/swin_transformer/swin_base_224_b16x64_300e_imagenet.py --phase train --adaptive --mode pipeline --show
+ ```
+
+ 
## Learning Rate Schedule Visualization
diff --git a/docs/zh_CN/_static/image/tools/visualization/pipeline-concat.jpg b/docs/zh_CN/_static/image/tools/visualization/pipeline-concat.jpg
deleted file mode 100644
index e5e69974..00000000
Binary files a/docs/zh_CN/_static/image/tools/visualization/pipeline-concat.jpg and /dev/null differ
diff --git a/docs/zh_CN/_static/image/tools/visualization/pipeline-original.jpg b/docs/zh_CN/_static/image/tools/visualization/pipeline-original.jpg
deleted file mode 100644
index fa23a029..00000000
Binary files a/docs/zh_CN/_static/image/tools/visualization/pipeline-original.jpg and /dev/null differ
diff --git a/docs/zh_CN/_static/image/tools/visualization/pipeline-pipeline.jpg b/docs/zh_CN/_static/image/tools/visualization/pipeline-pipeline.jpg
deleted file mode 100644
index aa7df13b..00000000
Binary files a/docs/zh_CN/_static/image/tools/visualization/pipeline-pipeline.jpg and /dev/null differ
diff --git a/docs/zh_CN/tools/visualization.md b/docs/zh_CN/tools/visualization.md
index b236da6b..9caaf24a 100644
--- a/docs/zh_CN/tools/visualization.md
+++ b/docs/zh_CN/tools/visualization.md
@@ -2,11 +2,10 @@
-- [可视化](#可视化)
- - [数据流水线可视化](#数据流水线可视化)
- - [学习率策略可视化](#学习率策略可视化)
- - [类别激活图可视化](#类别激活图可视化)
- - [常见问题](#常见问题)
+- [数据流水线可视化](#数据流水线可视化)
+- [学习率策略可视化](#学习率策略可视化)
+- [类别激活图可视化](#类别激活图可视化)
+- [常见问题](#常见问题)
@@ -15,17 +14,18 @@
```bash
python tools/visualizations/vis_pipeline.py \
${CONFIG_FILE} \
- --output-dir ${OUTPUT_DIR} \
- --phase ${DATASET_PHASE} \
- --number ${BUNBER_IMAGES_DISPLAY} \
- --skip-type ${SKIP_TRANSFORM_TYPE} \
- --mode ${DISPLAY_MODE} \
- --show \
- --adaptive \
- --min-edge-length ${MIN_EDGE_LENGTH} \
- --max-edge-length ${MAX_EDGE_LENGTH} \
- --bgr2rgb \
- --window-size ${WINDOW_SIZE}
+ [--output-dir ${OUTPUT_DIR}] \
+ [--phase ${DATASET_PHASE}] \
+ [--number ${BUNBER_IMAGES_DISPLAY}] \
+ [--skip-type ${SKIP_TRANSFORM_TYPE}] \
+ [--mode ${DISPLAY_MODE}] \
+ [--show] \
+ [--adaptive] \
+ [--min-edge-length ${MIN_EDGE_LENGTH}] \
+ [--max-edge-length ${MAX_EDGE_LENGTH}] \
+ [--bgr2rgb] \
+ [--window-size ${WINDOW_SIZE}] \
+ [--cfg-options ${CFG_OPTIONS}]
```
**所有参数的说明**:
@@ -35,71 +35,80 @@ python tools/visualizations/vis_pipeline.py \
- `--phase`: 可视化数据集的阶段,只能为 `[train, val, test]` 之一,默认为 `train`。
- `--number`: 可视化样本数量。如果没有指定,默认展示数据集的所有图片。
- `--skip-type`: 预设跳过的数据流水线过程。如果没有指定,默认为 `['ToTensor', 'Normalize', 'ImageToTensor', 'Collect']`。
-- `--mode`: 可视化的模式,只能为 `[original, pipeline, concat]` 之一,如果没有指定,默认为 `concat`。
+- `--mode`: 可视化的模式,只能为 `[original, transformed, concat, pipeline]` 之一,如果没有指定,默认为 `concat`。
- `--show`: 将可视化图片以弹窗形式展示。
- `--adaptive`: 自动调节可视化图片的大小。
- `--min-edge-length`: 最短边长度,当使用了 `--adaptive` 时有效。 当图片任意边小于 `${MIN_EDGE_LENGTH}` 时,会保持长宽比不变放大图片,短边对齐至 `${MIN_EDGE_LENGTH}`,默认为200。
- `--max-edge-length`: 最长边长度,当使用了 `--adaptive` 时有效。 当图片任意边大于 `${MAX_EDGE_LENGTH}` 时,会保持长宽比不变缩小图片,短边对齐至 `${MAX_EDGE_LENGTH}`,默认为1000。
- `--bgr2rgb`: 将图片的颜色通道翻转。
- `--window-size`: 可视化窗口大小,如果没有指定,默认为 `12*7`。如果需要指定,按照格式 `'W*H'`。
+- `--cfg-options` : 对配置文件的修改,参考[教程 1:如何编写配置文件](https://mmclassification.readthedocs.io/zh_CN/latest/tutorials/config.html)。
```{note}
-1. 如果不指定 `--mode`,默认设置为 `concat`,获取原始图片和预处理后图片拼接的图片;如果 `--mode` 设置为 `original`,则获取原始图片; 如果 `--mode` 设置为 `pipeline`,则获取预处理后的图片。
+1. 如果不指定 `--mode`,默认设置为 `concat`,获取原始图片和预处理后图片拼接的图片;如果 `--mode` 设置为 `original`,则获取原始图片;如果 `--mode` 设置为 `transformed`,则获取预处理后的图片;如果 `--mode` 设置为 `pipeline`,则获得数据流水线所有中间过程图片。
2. 当指定了 `--adaptive` 选项时,会自动的调整尺寸过大和过小的图片,你可以通过设定 `--min-edge-length` 与 `--max-edge-length` 来指定自动调整的图片尺寸。
```
**示例**:
-1. 可视化 `ImageNet` 训练集的所有经过预处理的图片,并以弹窗形式显示:
+1. **'original'** 模式,可视化 `CIFAR100` 验证集中的100张原始图片,显示并保存在 `./tmp` 文件夹下:
- ```shell
- python ./tools/visualizations/vis_pipeline.py ./configs/resnet/resnet50_8xb32_in1k.py --show --mode pipeline
- ```
+ ```shell
+ python ./tools/visualizations/vis_pipeline.py configs/resnet/resnet50_8xb16_cifar100.py --phase val --output-dir tmp --mode original --number 100 --show --adaptive --bgr2rgb
+ ```
- 
+ 
-2. 可视化 `ImageNet` 训练集的10张原始图片与预处理后图片对比图,保存在 `./tmp` 文件夹下:
+2. **'transformed'** 模式,可视化 `ImageNet` 训练集的所有经过预处理的图片,并以弹窗形式显示:
- ```shell
- python ./tools/visualizations/vis_pipeline.py configs/swin_transformer/swin_base_224_b16x64_300e_imagenet.py --phase train --output-dir tmp --number 10 --adaptive
- ```
+ ```shell
+ python ./tools/visualizations/vis_pipeline.py ./configs/resnet/resnet50_8xb32_in1k.py --show --mode transformed
+ ```
- 
+ 
-3. 可视化 `CIFAR100` 验证集中的100张原始图片,显示并保存在 `./tmp` 文件夹下:
+3. **'concat'** 模式,可视化 `ImageNet` 训练集的10张原始图片与预处理后图片对比图,保存在 `./tmp` 文件夹下:
- ```shell
- python ./tools/visualizations/vis_pipeline.py configs/resnet/resnet50_8xb16_cifar100.py --phase val --output-dir tmp --mode original --number 100 --show --adaptive --bgr2rgb
- ```
+ ```shell
+ python ./tools/visualizations/vis_pipeline.py configs/swin_transformer/swin_base_224_b16x64_300e_imagenet.py --phase train --output-dir tmp --number 10 --adaptive
+ ```
- 
+ 
+
+4. **'pipeline'** 模式,可视化 `ImageNet` 训练集经过数据流水线的过程图像:
+
+ ```shell
+ python ./tools/visualizations/vis_pipeline.py configs/swin_transformer/swin_base_224_b16x64_300e_imagenet.py --phase train --adaptive --mode pipeline --show
+ ```
+
+ 
## 学习率策略可视化
```bash
python tools/visualizations/vis_lr.py \
${CONFIG_FILE} \
- --dataset-size ${Dataset_Size} \
- --ngpus ${NUM_GPUs}
- --save-path ${SAVE_PATH} \
- --title ${TITLE} \
- --style ${STYLE} \
- --window-size ${WINDOW_SIZE}
- --cfg-options
+ [--dataset-size ${Dataset_Size}] \
+ [--ngpus ${NUM_GPUs}] \
+ [--save-path ${SAVE_PATH}] \
+ [--title ${TITLE}] \
+ [--style ${STYLE}] \
+ [--window-size ${WINDOW_SIZE}] \
+ [--cfg-options ${CFG_OPTIONS}] \
```
**所有参数的说明**:
- `config` : 模型配置文件的路径。
-- `dataset-size` : 数据集的大小。如果指定,`build_dataset` 将被跳过并使用这个大小作为数据集大小,默认使用 `build_dataset` 所得数据集的大小。
-- `ngpus` : 使用 GPU 的数量。
-- `save-path` : 保存的可视化图片的路径,默认不保存。
-- `title` : 可视化图片的标题,默认为配置文件名。
-- `style` : 可视化图片的风格,默认为 `whitegrid`。
-- `window-size`: 可视化窗口大小,如果没有指定,默认为 `12*7`。如果需要指定,按照格式 `'W*H'`。
-- `cfg-options` : 对配置文件的修改,参考[教程 1:如何编写配置文件](https://mmclassification.readthedocs.io/zh_CN/latest/tutorials/config.html)。
+- `--dataset-size` : 数据集的大小。如果指定,`build_dataset` 将被跳过并使用这个大小作为数据集大小,默认使用 `build_dataset` 所得数据集的大小。
+- `--ngpus` : 使用 GPU 的数量。
+- `--save-path` : 保存的可视化图片的路径,默认不保存。
+- `--title` : 可视化图片的标题,默认为配置文件名。
+- `--style` : 可视化图片的风格,默认为 `whitegrid`。
+- `--window-size`: 可视化窗口大小,如果没有指定,默认为 `12*7`。如果需要指定,按照格式 `'W*H'`。
+- `--cfg-options` : 对配置文件的修改,参考[教程 1:如何编写配置文件](https://mmclassification.readthedocs.io/zh_CN/latest/tutorials/config.html)。
```{note}
diff --git a/tools/visualizations/vis_pipeline.py b/tools/visualizations/vis_pipeline.py
index ed64802f..ffb9b183 100644
--- a/tools/visualizations/vis_pipeline.py
+++ b/tools/visualizations/vis_pipeline.py
@@ -1,18 +1,27 @@
# Copyright (c) OpenMMLab. All rights reserved.
import argparse
+import copy
import itertools
import os
import re
import sys
+import warnings
from pathlib import Path
+from typing import List
+import cv2
import mmcv
import numpy as np
from mmcv import Config, DictAction, ProgressBar
from mmcls.core import visualization as vis
-from mmcls.datasets.builder import build_dataset
-from mmcls.datasets.pipelines import Compose
+from mmcls.datasets.builder import PIPELINES, build_dataset, build_from_cfg
+from mmcls.models.utils import to_2tuple
+
+# text style
+bright_style, reset_style = '\x1b[1m', '\x1b[0m'
+red_text, blue_text = '\x1b[31m', '\x1b[34m'
+white_background = '\x1b[107m'
def parse_args():
@@ -48,11 +57,12 @@ def parse_args():
'--mode',
default='concat',
type=str,
- choices=['original', 'pipeline', 'concat'],
+ choices=['original', 'transformed', 'concat', 'pipeline'],
help='display mode; display original pictures or transformed pictures'
- ' or comparison pictures. "original" means show images load from disk;'
- ' "pipeline" means to show images after pipeline; "concat" means show '
- 'images stitched by "original" and "pipeline" images. Default concat.')
+ ' or comparison pictures. "original" means show images load from disk'
+ '; "transformed" means to show images after transformed; "concat" '
+ 'means show images stitched by "original" and "output" images. '
+ '"pipeline" means show all the intermediate images. Default concat.')
parser.add_argument(
'--show',
default=False,
@@ -71,7 +81,7 @@ def parse_args():
'"--adaptive" is true. Default 200.')
parser.add_argument(
'--max-edge-length',
- default=1000,
+ default=800,
type=int,
help='the max edge length when visualizing images, used when '
'"--adaptive" is true. Default 1000.')
@@ -130,7 +140,7 @@ def retrieve_data_cfg(config_path, skip_type, cfg_options, phase):
return cfg
-def build_dataset_pipeline(cfg, phase):
+def build_dataset_pipelines(cfg, phase):
"""build dataset and pipeline from config.
Separate the pipeline except 'LoadImageFromFile' step if
@@ -144,43 +154,103 @@ def build_dataset_pipeline(cfg, phase):
origin_pipeline = data_cfg.pipeline
data_cfg.pipeline = loadimage_pipeline
dataset = build_dataset(data_cfg)
- pipeline = Compose(origin_pipeline)
+ pipelines = {
+ pipeline_cfg['type']: build_from_cfg(pipeline_cfg, PIPELINES)
+ for pipeline_cfg in origin_pipeline
+ }
- return dataset, pipeline
+ return dataset, pipelines
-def put_img(board, img, center):
- """put a image into a big board image with the anchor center."""
- center_x, center_y = center
- img_h, img_w, _ = img.shape
- xmin, ymin = int(center_x - img_w // 2), int(center_y - img_h // 2)
- board[ymin:ymin + img_h, xmin:xmin + img_w, :] = img
+def prepare_imgs(args, imgs: List[np.ndarray], steps=None):
+ """prepare the showing picture."""
+ ori_shapes = [img.shape for img in imgs]
+ # adaptive adjustment to rescale pictures
+ if args.adaptive:
+ for i, img in enumerate(imgs):
+ imgs[i] = adaptive_size(img, args.min_edge_length,
+ args.max_edge_length)
+ else:
+ # if src image is too large or too small,
+ # warning a "--adaptive" message.
+ for ori_h, ori_w, _ in ori_shapes:
+ if (args.min_edge_length > ori_h or args.min_edge_length > ori_w
+ or args.max_edge_length < ori_h
+ or args.max_edge_length < ori_w):
+ msg = red_text
+ msg += 'The visualization picture is too small or too large to'
+ msg += ' put text information on it, please add '
+ msg += bright_style + red_text + white_background
+ msg += '"--adaptive"'
+ msg += reset_style + red_text
+ msg += ' to adaptively rescale the showing pictures'
+ msg += reset_style
+ warnings.warn(msg)
+
+ if len(imgs) == 1:
+ return imgs[0]
+ else:
+ return concat_imgs(imgs, steps, ori_shapes)
+
+
+def concat_imgs(imgs, steps, ori_shapes):
+ """Concat list of pictures into a single big picture, align height here."""
+ show_shapes = [img.shape for img in imgs]
+ show_heights = [shape[0] for shape in show_shapes]
+ show_widths = [shape[1] for shape in show_shapes]
+
+ max_height = max(show_heights)
+ text_height = 20
+ font_size = 0.5
+ pic_horizontal_gap = min(show_widths) // 10
+ for i, img in enumerate(imgs):
+ cur_height = show_heights[i]
+ pad_height = max_height - cur_height
+ pad_top, pad_bottom = to_2tuple(pad_height // 2)
+ # handle instance that the pad_height is an odd number
+ if pad_height % 2 == 1:
+ pad_top = pad_top + 1
+ pad_bottom += text_height * 3 # keep pxs to put step information text
+ pad_left, pad_right = to_2tuple(pic_horizontal_gap)
+ # make border
+ img = cv2.copyMakeBorder(
+ img,
+ pad_top,
+ pad_bottom,
+ pad_left,
+ pad_right,
+ cv2.BORDER_CONSTANT,
+ value=(255, 255, 255))
+ # put transform phase information in the bottom
+ imgs[i] = cv2.putText(
+ img=img,
+ text=steps[i],
+ org=(pic_horizontal_gap, max_height + text_height // 2),
+ fontFace=cv2.FONT_HERSHEY_TRIPLEX,
+ fontScale=font_size,
+ color=(255, 0, 0),
+ lineType=1)
+ # put image size information in the bottom
+ imgs[i] = cv2.putText(
+ img=img,
+ text=str(ori_shapes[i]),
+ org=(pic_horizontal_gap, max_height + int(text_height * 1.5)),
+ fontFace=cv2.FONT_HERSHEY_TRIPLEX,
+ fontScale=font_size,
+ color=(255, 0, 0),
+ lineType=1)
+
+ # Height alignment for concatenating
+ board = np.concatenate(imgs, axis=1)
return board
-def concat(left_img, right_img):
- """Concat two pictures into a single big picture, accepts two images with
- diffenert shapes."""
- GAP = 10
- left_h, left_w, _ = left_img.shape
- right_h, right_w, _ = right_img.shape
- # create a big board to contain images with shape (board_h, board_w*2+10)
- board_h, board_w = max(left_h, right_h), max(left_w, right_w)
- board = np.ones([board_h, 2 * board_w + GAP, 3], np.uint8) * 255
-
- put_img(board, left_img, (int(board_w // 2), int(board_h // 2)))
- put_img(board, right_img,
- (int(board_w // 2) + board_w + GAP // 2, int(board_h // 2)))
- return board
-
-
-def adaptive_size(mode, image, min_edge_length, max_edge_length):
- """rescale image if image is too small to put text like cifra."""
+def adaptive_size(image, min_edge_length, max_edge_length, src_shape=None):
+ """rescale image if image is too small to put text like cifar."""
assert min_edge_length >= 0 and max_edge_length >= 0
assert max_edge_length >= min_edge_length
-
- image_h, image_w, *_ = image.shape
- image_w = image_w // 2 if mode == 'concat' else image_w
+ src_shape = image.shape if src_shape is None else src_shape
+ image_h, image_w, _ = src_shape
if image_h < min_edge_length or image_w < min_edge_length:
image = mmcv.imrescale(
@@ -191,49 +261,58 @@ def adaptive_size(mode, image, min_edge_length, max_edge_length):
return image
-def get_display_img(item, pipeline, mode, bgr2rgb):
+def get_display_img(args, item, pipelines):
"""get image to display."""
- if bgr2rgb:
+ # srcs picture could be in RGB or BGR order due to different backends.
+ if args.bgr2rgb:
item['img'] = mmcv.bgr2rgb(item['img'])
src_image = item['img'].copy()
- # get transformed picture
- if mode in ['pipeline', 'concat']:
- item = pipeline(item)
- trans_image = item['img']
- trans_image = np.ascontiguousarray(trans_image, dtype=np.uint8)
+ pipeline_images = [src_image]
+
+ # get intermediate images through pipelines
+ if args.mode in ['transformed', 'concat', 'pipeline']:
+ for pipeline in pipelines.values():
+ item = pipeline(item)
+ trans_image = copy.deepcopy(item['img'])
+ trans_image = np.ascontiguousarray(trans_image, dtype=np.uint8)
+ pipeline_images.append(trans_image)
+
+ # concatenate images to be showed according to mode
+ if args.mode == 'original':
+ image = prepare_imgs(args, [src_image], ['src'])
+ elif args.mode == 'transformed':
+ image = prepare_imgs(args, [pipeline_images[-1]], ['transformed'])
+ elif args.mode == 'concat':
+ steps = ['src', 'transformed']
+ image = prepare_imgs(args, [pipeline_images[0], pipeline_images[-1]],
+ steps)
+ elif args.mode == 'pipeline':
+ steps = ['src'] + list(pipelines.keys())
+ image = prepare_imgs(args, pipeline_images, steps)
- if mode == 'concat':
- image = concat(src_image, trans_image)
- elif mode == 'original':
- image = src_image
- elif mode == 'pipeline':
- image = trans_image
return image
def main():
args = parse_args()
wind_w, wind_h = args.window_size.split('*')
- wind_w, wind_h = int(wind_w), int(wind_h)
+ wind_w, wind_h = int(wind_w), int(wind_h) # showing windows size
cfg = retrieve_data_cfg(args.config, args.skip_type, args.cfg_options,
args.phase)
- dataset, pipeline = build_dataset_pipeline(cfg, args.phase)
+ dataset, pipelines = build_dataset_pipelines(cfg, args.phase)
CLASSES = dataset.CLASSES
display_number = min(args.number, len(dataset))
progressBar = ProgressBar(display_number)
with vis.ImshowInfosContextManager(fig_size=(wind_w, wind_h)) as manager:
for i, item in enumerate(itertools.islice(dataset, display_number)):
- image = get_display_img(item, pipeline, args.mode, args.bgr2rgb)
- if args.adaptive:
- image = adaptive_size(args.mode, image, args.min_edge_length,
- args.max_edge_length)
+ image = get_display_img(args, item, pipelines)
- # dist_path is None as default, means not save pictures
+ # dist_path is None as default, means not saving pictures
dist_path = None
if args.output_dir:
- # some datasets do not have filename, such as cifar, use id
+ # some datasets don't have filenames, such as cifar
src_path = item.get('filename', '{}.jpg'.format(i))
dist_path = os.path.join(args.output_dir, Path(src_path).name)