diff --git a/.gitignore b/.gitignore index 36bd124..e9d27c2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,14 +3,12 @@ *.pt *.pkl *.ckpt -*.png *.DS_Store *__pycache__* *.cache* *.bin *.idea *.csv -#*.txt build dist dev diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..065dd42 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,25 @@ + repos: + - repo: https://github.com/pycqa/flake8.git + rev: 4.0.0 + hooks: + - id: flake8 + args: ['--max-line-length=120', '--per-file-ignores=__init__.py:F401'] + - repo: https://github.com/PyCQA/isort.git + rev: 4.3.21 + hooks: + - id: isort + - repo: https://github.com/pre-commit/mirrors-yapf.git + rev: v0.30.0 + hooks: + - id: yapf + - repo: https://github.com/pre-commit/pre-commit-hooks.git + rev: v3.1.0 + hooks: + - id: trailing-whitespace + - id: check-yaml + - id: end-of-file-fixer + - id: requirements-txt-fixer + - id: double-quote-string-fixer + - id: check-merge-conflict + - id: fix-encoding-pragma + - id: mixed-line-ending diff --git a/asset/images/flower.jpg b/asset/images/flower.jpg new file mode 100644 index 0000000..bc8d1e5 Binary files /dev/null and b/asset/images/flower.jpg differ diff --git a/asset/images/pose_source.png b/asset/images/pose_source.png new file mode 100644 index 0000000..15776a3 Binary files /dev/null and b/asset/images/pose_source.png differ diff --git a/asset/images/sunflower.jpeg b/asset/images/sunflower.jpeg new file mode 100644 index 0000000..9bed15e Binary files /dev/null and b/asset/images/sunflower.jpeg differ diff --git a/docs/en/scepter/utils/utils.md b/docs/en/scepter/utils/utils.md index 96e0cec..ef99523 100644 --- a/docs/en/scepter/utils/utils.md +++ b/docs/en/scepter/utils/utils.md @@ -356,7 +356,7 @@ Used to instantiate a standard logging instance for printing information. ```python from scepter.utils.logger import get_logger, init_logger -std_logger = get_logger(name="std_torch") +std_logger = get_logger(name="scepter") init_logger(std_logger, log_file="", dist_launcher="pytorch") ```
diff --git a/docs/zh_cn/scepter/utils/utils.md b/docs/zh_cn/scepter/utils/utils.md index 1efa161..be8917a 100644 --- a/docs/zh_cn/scepter/utils/utils.md +++ b/docs/zh_cn/scepter/utils/utils.md @@ -358,7 +358,7 @@ input_type 一一对应。 ```python from scepter.utils.logger import get_logger, init_logger -std_logger = get_logger(name="std_torch") +std_logger = get_logger(name="scepter") init_logger(std_logger, log_file="", dist_launcher="pytorch") ```
diff --git a/readme.md b/readme.md index afbd005..375a2be 100644 --- a/readme.md +++ b/readme.md @@ -3,14 +3,18 @@

+ +

## 📖 Table of Contents - [Introduction](#-introduction) - [News](#-news) -- [Installation](#-installation) +- [Installation](#-Installation) - [Getting Started](#-getting-started) +- [SCEPTER Studio](#-scepter-studio) +- [Features](#-features) - [Learn More](#-learn-more) - [License](#license) @@ -20,14 +24,17 @@ SCEPTER is an open-source code repository dedicated to generative training, fine Main Feature: -- Training: - - distribute: DDP / FSDP / FairScale -- Inference - - text-to-image generation - - controllable image synthesis (TODO) -- Deploy-Gradio (TODO) - - fine-tuning - - inference +- Task: + - Text-to-image generation + - Controllable image synthesis + - Image editing (TODO) +- Training / Inference: + - Distribute: DDP / FSDP / FairScale / Xformers + - File system: Local / Http / OSS / Modelscope +- Deploy: + - Data management + - Training + - Inference Currently supported approches (and counting): @@ -36,6 +43,8 @@ Currently supported approches (and counting): 3. Res-Tuning(TODO): [Res-Tuning: A Flexible and Efficient Tuning Paradigm via Unbinding Tuner from Backbone](https://arxiv.org/abs/2310.19859) [![Arxiv link](https://img.shields.io/static/v1?label=arXiv&message=ResTuning&color=red&logo=arxiv)](https://arxiv.org/abs/2310.19859) [![Page link](https://img.shields.io/badge/Page-ResTuning-Gree)](https://res-tuning.github.io/) ## 🎉 News +- [2024.01]: We release **SCEPTER Studio**, an integrated toolkit for data management, model training and inference based on [Gradio](https://www.gradio.app/). +- [2024.01]: [SCEdit](https://arxiv.org/abs/2312.11392) support controllable image synthesis for training and inference. - [2023.12]: We propose [SCEdit](https://arxiv.org/abs/2312.11392), an efficient and controllable generation framework. - [2023.12]: We release [🪄SCEPTER](https://github.com/modelscope/scepter/) library. @@ -51,14 +60,15 @@ conda activate scepter - Install SCEPTER by the `pip` command: ```shell -pip install -e . +pip install scepter ``` +- PS: We recommend installing PyTorch follwing [official documentation](https://pytorch.org/get-started/locally/) ## 🚀 Getting Started ### Dataset -#### Text-to-Image generation +#### Modelscope Format We use a [custom-stylized dataset](https://modelscope.cn/datasets/damo/style_custom_dataset/summary), which included classes 3D, anime, flat illustration, oil painting, sketch, and watercolor, each with 30 image-text pairs. @@ -69,54 +79,148 @@ ms_train_dataset = MsDataset.load('style_custom_dataset', namespace='damo', subs print(next(iter(ms_train_dataset))) ``` +#### CSV Format + +For the data format used by SCEPTER Studio, please refer to [3D_example_csv.zip](https://modelscope.cn/api/v1/models/damo/scepter/repo?Revision=master&FilePath=datasets/3D_example_csv.zip). + +#### TXT Format + +To facilitate starting training in command-line mode, you can use a dataset in text format, please refer to [3D_example_txt.zip](https://modelscope.cn/api/v1/models/damo/scepter/repo?Revision=master&FilePath=datasets/3D_example_txt.zip) + +```shell +mkdir -p cache/dataset/ && wget 'https://modelscope.cn/api/v1/models/damo/scepter_scedit/repo?Revision=master&FilePath=dataset/3D_example_txt.zip' -O cache/dataset/3D_example_txt.zip && unzip cache/dataset/3D_example_txt.zip -d cache/dataset/ && rm cache/dataset/3D_example_txt.zip +``` + ### Training -#### Text-to-Image generation +We provide a framework for training and inference, so the script below is just for illustration purposes. To achieve better results, you can modify the corresponding parameters as needed. + +#### Text-to-Image Generation + +- SCEdit +```python +python scepter/tools/run_train.py --cfg scepter/methods/scedit/t2i/sd15_512_sce_t2i.yaml # SD v1.5 +python scepter/tools/run_train.py --cfg scepter/methods/scedit/t2i/sd21_768_sce_t2i.yaml # SD v2.1 +python scepter/tools/run_train.py --cfg scepter/methods/scedit/t2i/sdxl_1024_sce_t2i.yaml # SD XL +``` + +- Existing Tuning Strategies +```python +python scepter/tools/run_train.py --cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml # fully-tuning on SD v1.5 +python scepter/tools/run_train.py --cfg scepter/methods/examples/generation/stable_diffusion_2.1_768_lora.yaml # lora-tuning on SD v2.1 +``` + +- Data Text Format +```python +# Download the 3D_example_txt.zip as previously mentioned +python scepter/tools/run_train.py --cfg scepter/methods/scedit/t2i/sdxl_1024_sce_t2i_datatxt.yaml +``` + +#### Controllable Image Synthesis - SCEdit +The YAML configuration can be modified to combine different base models and conditions. The following is provided as an example. ```python -# SD v1.5 -python scepter/tools/run_train.py --cfg scepter/methods/SCEdit/t2i_sd15_512_sce.yaml -# SD v2.1 -python scepter/tools/run_train.py --cfg scepter/methods/SCEdit/t2i_sd21_768_sce.yaml -# SD XL -python scepter/tools/run_train.py --cfg scepter/methods/SCEdit/t2i_sdxl_1024_sce.yaml +python scepter/tools/run_train.py --cfg scepter/methods/scedit/ctr/sd15_512_sce_ctr_hed.yaml # SD v1.5 + hed +python scepter/tools/run_train.py --cfg scepter/methods/scedit/ctr/sd21_768_sce_ctr_canny.yaml # SD v2.1 + canny +python scepter/tools/run_train.py --cfg scepter/methods/scedit/ctr/sd21_768_sce_ctr_pose.yaml # SD v2.1 + pose +python scepter/tools/run_train.py --cfg scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_depth.yaml # SD XL + depth +python scepter/tools/run_train.py --cfg scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_color.yaml # SD XL + color ``` -- Existing strategies +- Data Text Format ```python -# fully-tuning on SD v1.5 -python scepter/tools/run_train.py --cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml -# lora-tuning on SD v2.1 -python scepter/tools/run_train.py --cfg scepter/methods/examples/generation/stable_diffusion_2.1_768_lora.yaml +# Download the 3D_example_txt.zip as previously mentioned +python scepter/tools/run_train.py --cfg scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_color_datatxt.yaml ``` -#### Controllable Image Synthesis - -TODO ### Inference +#### Base Model Inference + ```python -# generation on SD v1.5 -python scepter/tools/run_inference.py --cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml --prompt 'a cute dog' --save_folder 'inference' -# generation on SD v2.1 -python scepter/tools/run_inference.py --cfg scepter/methods/examples/generation/stable_diffusion_2.1_768.yaml --prompt 'a cute dog' --save_folder 'inference' -# generation on SD XL -python scepter/tools/run_inference.py --cfg scepter/methods/examples/generation/stable_diffusion_xl_1024.yaml --prompt 'a cute dog' --save_folder 'inference' +python scepter/tools/run_inference.py --cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml --prompt 'a cute dog' --save_folder 'inference' # generation on SD v1.5 +python scepter/tools/run_inference.py --cfg scepter/methods/examples/generation/stable_diffusion_2.1_768.yaml --prompt 'a cute dog' --save_folder 'inference' # generation on SD v2.1 +python scepter/tools/run_inference.py --cfg scepter/methods/examples/generation/stable_diffusion_xl_1024.yaml --prompt 'a cute dog' --save_folder 'inference' # generation on SD XL +``` + +#### Fine-tuned Model Inference + +```python +python scepter/tools/run_inference.py --cfg scepter/methods/scedit/t2i/sd15_512_sce_t2i_swift.yaml --pretrained_model 'cache/save_data/sd15_512_sce_t2i_swift/checkpoints/ldm_step-100.pth' --prompt 'A close up of a small rabbit wearing a hat and scarf' --save_folder 'trained_test_prompt_rabbit' +``` + +#### Controllable Image Synthesis Inference + +- SCEdit +```python +python scepter/tools/run_inference.py --cfg scepter/methods/scedit/ctr/sd21_768_sce_ctr_canny.yaml --num_samples 1 --prompt 'a single flower is shown in front of a tree' --save_folder 'test_flower_canny' --image_size 768 --task control --image 'asset/images/flower.jpg' --control_mode canny --pretrained_model ms://damo/scepter_scedit@controllable_model/SD2.1/canny_control/0_SwiftSCETuning/pytorch_model.bin # canny +python scepter/tools/run_inference.py --cfg scepter/methods/scedit/ctr/sd21_768_sce_ctr_pose.yaml --num_samples 1 --prompt 'super mario' --save_folder 'test_mario_pose' --image_size 768 --task control --image 'asset/images/pose_source.png' --control_mode source --pretrained_model ms://damo/scepter_scedit@controllable_model/SD2.1/pose_control/0_SwiftSCETuning/pytorch_model.bin # pose ``` +## 🖥️ SCEPTER Studio + +### Launch + +To fully experience **SCEPTER Studio**, you can launch the following command line: + +```shell +PYTHONPATH=. python scepter/tools/webui.py --cfg scepter/methods/studio/scepter_ui.yaml +``` + +### Modelscope Studio + +We deploy a work studio on Modelscope that includes only the inference tab, please refer to [ms_scepter_studio](https://www.modelscope.cn/studios/damo/scepter_studio/summary) + +## ✨ Features + +### Text-to-Image Generation + +| **Model** | **SCEdit** | **Full** | **LoRA** | +|:---------:|:----------:|:--------:|:--------:| +| SD 1.5 | 🪄 | ✅ | ✅ | +| SD 2.1 | 🪄 | ✅ | ✅ | +| SD XL | 🪄 | ✅ | ✅ | + +### Controllable Image Synthesis +- SCEdit + +| **Model** | **Canny** | **HED** | **Depth** | **Pose** | **Color** | +|:---------:|:---------:|:-------:|:---------:|:--------:|:---------:| +| SD 1.5 | ✅ | ✅ | ✅ | ✅ | ✅ | +| SD 2.1 | 🪄 | ✅ | ✅ | 🪄 | 🪄 | +| SD XL | ✅ | ✅ | ✅ | ✅ | ✅ | + +### Model URL + +- ✅ indicates support for both training and inference. +- 🪄 denotes that the model has been published. +- More models will be released in the future. + +| Model | URL | +|--------|-------------------------------------------------------------------------------------| +| SCEdit | [ModelCard](https://modelscope.cn/models/damo/scepter_scedit/summary) | + +PS: Scripts running within the SCEPTER framework will automatically fetch and load models based on the required dependency files, eliminating the need for manual downloads. + + ## 🔍 Learn More -- [ModelScope library](https://github.com/modelscope/modelscope/) - - ModelScope Library is the model library of ModelScope project, which contains a large number of popular models. - - [Alibaba TongYi Vision Intelligence Lab](https://github.com/damo-vilab) Discover more about open-source projects on image generation, video generation, and editing tasks. +- [ModelScope library](https://github.com/modelscope/modelscope/) + + ModelScope Library is the model library of ModelScope project, which contains a large number of popular models. + +- [SWIFT library](https://github.com/modelscope/swift/) + + SWIFT (Scalable lightWeight Infrastructure for Fine-Tuning) is an extensible framwork designed to faciliate lightweight model fine-tuning and inference. + + ## License This project is licensed under the [Apache License (Version 2.0)](https://github.com/modelscope/modelscope/blob/master/LICENSE). diff --git a/requirements.txt b/requirements.txt index 0832e6a..f3e0809 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ -r requirements/framework.txt +-r requirements/scepter_studio.txt diff --git a/requirements/framework.txt b/requirements/framework.txt index d595846..3e7a72e 100644 --- a/requirements/framework.txt +++ b/requirements/framework.txt @@ -1,12 +1,11 @@ einops modelscope -ms_swift==1.5.2 +ms-swift>=1.5.2 numpy open_clip_torch opencv-python opencv_transforms>=0.0.6 oss2>=2.15.0 pyyaml>=5.3.1 -torchvision==0.15.2 transformers xformers>=0.0.21 diff --git a/requirements/scepter_studio.txt b/requirements/scepter_studio.txt new file mode 100644 index 0000000..e083847 --- /dev/null +++ b/requirements/scepter_studio.txt @@ -0,0 +1,2 @@ +gradio==3.50.2 +imagehash diff --git a/scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml b/scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml index 0d70b10..7918211 100644 --- a/scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml +++ b/scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml @@ -15,7 +15,7 @@ SOLVER: ACCU_STEP: 1 EVAL_INTERVAL: 100 # - WORK_DIR: ./cache/sd15_512_full + WORK_DIR: ./cache/save_data/sd15_512_full LOG_FILE: std_log.txt # FILE_SYSTEM: diff --git a/scepter/methods/examples/generation/stable_diffusion_1.5_512_lora.yaml b/scepter/methods/examples/generation/stable_diffusion_1.5_512_lora.yaml index 57b23f8..4df6747 100644 --- a/scepter/methods/examples/generation/stable_diffusion_1.5_512_lora.yaml +++ b/scepter/methods/examples/generation/stable_diffusion_1.5_512_lora.yaml @@ -15,13 +15,13 @@ SOLVER: ACCU_STEP: 1 EVAL_INTERVAL: 100 # - WORK_DIR: ./cache/sd15_512_lora + WORK_DIR: ./cache/save_data/sd15_512_lora LOG_FILE: std_log.txt # FILE_SYSTEM: NAME: "ModelscopeFs" TEMP_DIR: "./cache/data" - TUNER: + TUNER: - NAME: SwiftLoRA R: 64 diff --git a/scepter/methods/examples/generation/stable_diffusion_2.1_768.yaml b/scepter/methods/examples/generation/stable_diffusion_2.1_768.yaml index ad0fc9f..0d9a1cf 100644 --- a/scepter/methods/examples/generation/stable_diffusion_2.1_768.yaml +++ b/scepter/methods/examples/generation/stable_diffusion_2.1_768.yaml @@ -15,7 +15,7 @@ SOLVER: ACCU_STEP: 1 EVAL_INTERVAL: 100 # - WORK_DIR: ./cache/sd21_768_full + WORK_DIR: ./cache/save_data/sd21_768_full LOG_FILE: std_log.txt # FILE_SYSTEM: diff --git a/scepter/methods/examples/generation/stable_diffusion_2.1_768_lora.yaml b/scepter/methods/examples/generation/stable_diffusion_2.1_768_lora.yaml index 4dd1cb5..90becb2 100644 --- a/scepter/methods/examples/generation/stable_diffusion_2.1_768_lora.yaml +++ b/scepter/methods/examples/generation/stable_diffusion_2.1_768_lora.yaml @@ -15,14 +15,14 @@ SOLVER: ACCU_STEP: 1 EVAL_INTERVAL: 100 # - WORK_DIR: ./cache/sd21_768_lora + WORK_DIR: ./cache/save_data/sd21_768_lora LOG_FILE: std_log.txt # FILE_SYSTEM: NAME: "ModelscopeFs" TEMP_DIR: "./cache/data" # - TUNER: + TUNER: - NAME: SwiftLoRA R: 64 diff --git a/scepter/methods/examples/generation/stable_diffusion_xl_1024.yaml b/scepter/methods/examples/generation/stable_diffusion_xl_1024.yaml index 6ac3f4d..48b4566 100644 --- a/scepter/methods/examples/generation/stable_diffusion_xl_1024.yaml +++ b/scepter/methods/examples/generation/stable_diffusion_xl_1024.yaml @@ -15,7 +15,7 @@ SOLVER: ACCU_STEP: 1 EVAL_INTERVAL: 100 # - WORK_DIR: ./cache/sdxl_1024_full + WORK_DIR: ./cache/save_data/sdxl_1024_full LOG_FILE: std_log.txt # FILE_SYSTEM: @@ -120,7 +120,7 @@ SOLVER: UCG_RATE: 0.0 INPUT_KEYS: [ "prompt" ] LEGACY_UCG_VALUE: - - + - NAME: FrozenOpenCLIPEmbedder2 ARCH: ViT-bigG-14 PRETRAINED_MODEL: @@ -133,21 +133,21 @@ SOLVER: UCG_RATE: 0.0 INPUT_KEYS: [ "prompt" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False UCG_RATE: 0.0 INPUT_KEYS: [ "original_size_as_tuple" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False UCG_RATE: 0.0 INPUT_KEYS: [ "crop_coords_top_left" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False @@ -200,21 +200,21 @@ SOLVER: UCG_RATE: 0.0 INPUT_KEYS: [ "prompt" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False UCG_RATE: 0.0 INPUT_KEYS: [ "original_size_as_tuple" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False UCG_RATE: 0.0 INPUT_KEYS: [ "crop_coords_top_left" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False @@ -287,8 +287,8 @@ SOLVER: KEYS: [ 'img', 'prompt', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] META_KEYS: [ 'data_key', 'img_path' ] - NAME: Rename - IN_KEYS: [ 'img', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] - OUT_KEYS: [ 'image', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left' ] + INPUT_KEY: [ 'img', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] + OUTPUT_KEY: [ 'image', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left' ] # EVAL_DATA: NAME: ImageTextPairMSDataset diff --git a/scepter/methods/examples/generation/stable_diffusion_xl_1024_lora.yaml b/scepter/methods/examples/generation/stable_diffusion_xl_1024_lora.yaml index 2f1d315..5f6522e 100644 --- a/scepter/methods/examples/generation/stable_diffusion_xl_1024_lora.yaml +++ b/scepter/methods/examples/generation/stable_diffusion_xl_1024_lora.yaml @@ -15,14 +15,14 @@ SOLVER: ACCU_STEP: 1 EVAL_INTERVAL: 100 # - WORK_DIR: ./cache/sdxl_1024_lora + WORK_DIR: ./cache/save_data/sdxl_1024_lora LOG_FILE: std_log.txt # FILE_SYSTEM: NAME: "ModelscopeFs" TEMP_DIR: "./cache/data" - # - TUNER: + # + TUNER: - NAME: SwiftLoRA R: 64 @@ -129,7 +129,7 @@ SOLVER: UCG_RATE: 0.0 INPUT_KEYS: [ "prompt" ] LEGACY_UCG_VALUE: - - + - NAME: FrozenOpenCLIPEmbedder2 ARCH: ViT-bigG-14 PRETRAINED_MODEL: @@ -142,21 +142,21 @@ SOLVER: UCG_RATE: 0.0 INPUT_KEYS: [ "prompt" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False UCG_RATE: 0.0 INPUT_KEYS: [ "original_size_as_tuple" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False UCG_RATE: 0.0 INPUT_KEYS: [ "crop_coords_top_left" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False @@ -209,21 +209,21 @@ SOLVER: UCG_RATE: 0.0 INPUT_KEYS: [ "prompt" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False UCG_RATE: 0.0 INPUT_KEYS: [ "original_size_as_tuple" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False UCG_RATE: 0.0 INPUT_KEYS: [ "crop_coords_top_left" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False @@ -296,8 +296,8 @@ SOLVER: KEYS: [ 'img', 'prompt', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] META_KEYS: [ 'data_key', 'img_path' ] - NAME: Rename - IN_KEYS: [ 'img', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] - OUT_KEYS: [ 'image', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left' ] + INPUT_KEY: [ 'img', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] + OUTPUT_KEY: [ 'image', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left' ] # EVAL_DATA: NAME: ImageTextPairMSDataset @@ -334,4 +334,4 @@ SOLVER: # EVAL_HOOKS: - NAME: ProbeDataHook - PROB_INTERVAL: 100 \ No newline at end of file + PROB_INTERVAL: 100 diff --git a/scepter/methods/scedit/ctr/sd15_512_sce_ctr_hed.yaml b/scepter/methods/scedit/ctr/sd15_512_sce_ctr_hed.yaml new file mode 100644 index 0000000..ddb9a86 --- /dev/null +++ b/scepter/methods/scedit/ctr/sd15_512_sce_ctr_hed.yaml @@ -0,0 +1,265 @@ +ENV: + BACKEND: nccl +SOLVER: + NAME: LatentDiffusionSolver + RESUME_FROM: + LOAD_MODEL_ONLY: True + USE_FSDP: False + SHARDING_STRATEGY: + USE_AMP: True + DTYPE: float16 + CHANNELS_LAST: True + MAX_STEPS: 200 + MAX_EPOCHS: -1 + NUM_FOLDS: 1 + ACCU_STEP: 1 + EVAL_INTERVAL: 100 + # + WORK_DIR: ./cache/save_data/sd15_512_sce_ctr_hed + LOG_FILE: std_log.txt + # + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + FREEZE: + FREEZE_PART: [ "first_stage_model", "cond_stage_model", "model" ] + TRAIN_PART: [ "control_blocks" ] + # + MODEL: + NAME: LatentDiffusionSCEControl + PARAMETERIZATION: eps + TIMESTEPS: 1000 + MIN_SNR_GAMMA: + ZERO_TERMINAL_SNR: False + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-v1-5@v1-5-pruned-emaonly.safetensors + IGNORE_KEYS: [ ] + SCALE_FACTOR: 0.18215 + SIZE_FACTOR: 8 + DEFAULT_N_PROMPT: + SCHEDULE_ARGS: + "NAME": "scaled_linear" + "BETA_MIN": 0.00085 + "BETA_MAX": 0.012 + USE_EMA: False + # + DIFFUSION_MODEL: + NAME: DiffusionUNet + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + MODEL_CHANNELS: 320 + NUM_HEADS: 8 + NUM_RES_BLOCKS: 2 + ATTENTION_RESOLUTIONS: [ 4, 2, 1 ] + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + USE_CHECKPOINT: False + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 1 + CONTEXT_DIM: 768 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: False + PRETRAINED_MODEL: + IGNORE_KEYS: [] + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + PRETRAINED_MODEL: + IGNORE_KEYS: [] + BATCH_SIZE: 4 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + TOKENIZER: + NAME: ClipTokenizer + PRETRAINED_PATH: ms://AI-ModelScope/clip-vit-large-patch14 + LENGTH: 77 + CLEAN: True + # + COND_STAGE_MODEL: + NAME: FrozenCLIPEmbedder + FREEZE: True + LAYER: last + PRETRAINED_MODEL: ms://AI-ModelScope/clip-vit-large-patch14 + # + LOSS: + NAME: ReconstructLoss + LOSS_TYPE: l2 + # + CONTROL_MODEL: + NAME: CSCTuners + PRE_HINT_IN_CHANNELS: 3 + PRE_HINT_OUT_CHANNELS: 256 + DENSE_HINT_KERNAL: 3 + SCALE: 1.0 + SC_TUNER_CFG: + NAME: SCTuner + TUNER_NAME: SCEAdapter + DOWN_RATIO: 1.0 + CONTROL_ANNO: + NAME: HedAnnotator + PRETRAINED_MODEL: ms://damo/scepter_scedit@annotator/ckpts/ControlNetHED.pth + # + SAMPLE_ARGS: + SAMPLER: ddim + SAMPLE_STEPS: 50 + SEED: 2023 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 + DISCRETIZATION: trailing + IMAGE_SIZE: [512, 512] + RUN_TRAIN_N: False + # + OPTIMIZER: + NAME: AdamW + LEARNING_RATE: 0.064 + BETAS: [ 0.9, 0.999 ] + EPS: 1e-8 + WEIGHT_DECAY: 1e-2 + AMSGRAD: False + # + TRAIN_DATA: + NAME: ImageTextPairMSDataset + MODE: train + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train_short + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 1 + NUM_WORKERS: 4 + SAMPLER: + NAME: LoopSampler + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: Resize + SIZE: 768 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: CenterCrop + SIZE: 768 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ToNumpy + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image_preprocess' ] + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: torchvision + - NAME: Rename + INPUT_KEY: [ 'img', 'image_preprocess' ] + OUTPUT_KEY: [ 'image', 'image_preprocess' ] + - NAME: Select + KEYS: [ 'image', 'prompt', 'image_preprocess' ] + META_KEYS: [ 'data_key' ] + # + EVAL_DATA: + NAME: ImageTextPairMSDataset + MODE: eval + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train_short + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 10 + NUM_WORKERS: 4 + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: Resize + SIZE: 768 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: CenterCrop + SIZE: 768 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ToNumpy + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image_preprocess' ] + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: torchvision + - NAME: Rename + INPUT_KEY: [ 'img', 'image_preprocess' ] + OUTPUT_KEY: [ 'image', 'image_preprocess' ] + - NAME: Select + KEYS: [ 'image', 'prompt', 'image_preprocess' ] + META_KEYS: [ 'data_key' ] + # + TRAIN_HOOKS: + - + NAME: BackwardHook + PRIORITY: 0 + - + NAME: LogHook + LOG_INTERVAL: 50 + - + NAME: CheckpointHook + INTERVAL: 100 + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 + # + EVAL_HOOKS: + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 diff --git a/scepter/methods/scedit/ctr/sd21_768_sce_ctr_canny.yaml b/scepter/methods/scedit/ctr/sd21_768_sce_ctr_canny.yaml new file mode 100644 index 0000000..a40cb3e --- /dev/null +++ b/scepter/methods/scedit/ctr/sd21_768_sce_ctr_canny.yaml @@ -0,0 +1,264 @@ +ENV: + BACKEND: nccl +SOLVER: + NAME: LatentDiffusionSolver + RESUME_FROM: + LOAD_MODEL_ONLY: True + USE_FSDP: False + SHARDING_STRATEGY: + USE_AMP: True + DTYPE: float16 + CHANNELS_LAST: True + MAX_STEPS: 200 + MAX_EPOCHS: -1 + NUM_FOLDS: 1 + ACCU_STEP: 1 + EVAL_INTERVAL: 100 + # + WORK_DIR: ./cache/save_data/sd21_768_sce_ctr_canny + LOG_FILE: std_log.txt + # + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + FREEZE: + FREEZE_PART: [ "first_stage_model", "cond_stage_model", "model" ] + TRAIN_PART: [ "control_blocks" ] + # + MODEL: + NAME: LatentDiffusionSCEControl + PARAMETERIZATION: v + TIMESTEPS: 1000 + MIN_SNR_GAMMA: + ZERO_TERMINAL_SNR: True + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-2-1@v2-1_768-ema-pruned.safetensors + IGNORE_KEYS: [ ] + SCALE_FACTOR: 0.18215 + SIZE_FACTOR: 8 + DEFAULT_N_PROMPT: + SCHEDULE_ARGS: + "NAME": "scaled_linear" + "BETA_MIN": 0.00085 + "BETA_MAX": 0.012 + USE_EMA: False + # + DIFFUSION_MODEL: + NAME: DiffusionUNet + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + MODEL_CHANNELS: 320 + NUM_HEADS_CHANNELS: 64 + NUM_RES_BLOCKS: 2 + ATTENTION_RESOLUTIONS: [ 4, 2, 1 ] + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + USE_CHECKPOINT: False + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 1 + CONTEXT_DIM: 1024 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + PRETRAINED_MODEL: + IGNORE_KEYS: [] + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + PRETRAINED_MODEL: + IGNORE_KEYS: [ ] + BATCH_SIZE: 4 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + TOKENIZER: + NAME: OpenClipTokenizer + LENGTH: 77 + # + COND_STAGE_MODEL: + NAME: FrozenOpenCLIPEmbedder + ARCH: ViT-H-14 + PRETRAINED_MODEL: + LAYER: penultimate + # + LOSS: + NAME: ReconstructLoss + LOSS_TYPE: l2 + # + CONTROL_MODEL: + NAME: CSCTuners + PRE_HINT_IN_CHANNELS: 3 + PRE_HINT_OUT_CHANNELS: 256 + DENSE_HINT_KERNAL: 3 + SCALE: 1.0 + SC_TUNER_CFG: + NAME: SCTuner + TUNER_NAME: SCEAdapter + DOWN_RATIO: 1.0 + CONTROL_ANNO: + NAME: CannyAnnotator + LOW_THRESHOLD: 100 + HIGH_THRESHOLD: 200 + # + SAMPLE_ARGS: + SAMPLER: ddim + SAMPLE_STEPS: 50 + SEED: 2023 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 + DISCRETIZATION: trailing + IMAGE_SIZE: [768, 768] + RUN_TRAIN_N: False + # + OPTIMIZER: + NAME: AdamW + LEARNING_RATE: 0.064 + BETAS: [ 0.9, 0.999 ] + EPS: 1e-8 + WEIGHT_DECAY: 1e-2 + AMSGRAD: False + # + TRAIN_DATA: + NAME: ImageTextPairMSDataset + MODE: train + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train_short + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 1 + NUM_WORKERS: 4 + SAMPLER: + NAME: LoopSampler + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: Resize + SIZE: 768 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: CenterCrop + SIZE: 768 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ToNumpy + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image_preprocess' ] + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: torchvision + - NAME: Rename + INPUT_KEY: [ 'img', 'image_preprocess' ] + OUTPUT_KEY: [ 'image', 'image_preprocess' ] + - NAME: Select + KEYS: [ 'image', 'prompt', 'image_preprocess' ] + META_KEYS: [ 'data_key' ] + # + EVAL_DATA: + NAME: ImageTextPairMSDataset + MODE: eval + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train_short + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 10 + NUM_WORKERS: 4 + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: Resize + SIZE: 768 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: CenterCrop + SIZE: 768 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ToNumpy + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image_preprocess' ] + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: torchvision + - NAME: Rename + INPUT_KEY: [ 'img', 'image_preprocess' ] + OUTPUT_KEY: [ 'image', 'image_preprocess' ] + - NAME: Select + KEYS: [ 'image', 'prompt', 'image_preprocess' ] + META_KEYS: [ 'data_key' ] + # + TRAIN_HOOKS: + - + NAME: BackwardHook + PRIORITY: 0 + - + NAME: LogHook + LOG_INTERVAL: 50 + - + NAME: CheckpointHook + INTERVAL: 100 + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 + # + EVAL_HOOKS: + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 diff --git a/scepter/methods/scedit/ctr/sd21_768_sce_ctr_pose.yaml b/scepter/methods/scedit/ctr/sd21_768_sce_ctr_pose.yaml new file mode 100644 index 0000000..932e22f --- /dev/null +++ b/scepter/methods/scedit/ctr/sd21_768_sce_ctr_pose.yaml @@ -0,0 +1,264 @@ +ENV: + BACKEND: nccl +SOLVER: + NAME: LatentDiffusionSolver + RESUME_FROM: + LOAD_MODEL_ONLY: True + USE_FSDP: False + SHARDING_STRATEGY: + USE_AMP: True + DTYPE: float16 + CHANNELS_LAST: True + MAX_STEPS: 200 + MAX_EPOCHS: -1 + NUM_FOLDS: 1 + ACCU_STEP: 1 + EVAL_INTERVAL: 100 + # + WORK_DIR: ./cache/save_data/sd21_768_sce_ctr_pose + LOG_FILE: std_log.txt + # + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + FREEZE: + FREEZE_PART: [ "first_stage_model", "cond_stage_model", "model" ] + TRAIN_PART: [ "control_blocks" ] + # + MODEL: + NAME: LatentDiffusionSCEControl + PARAMETERIZATION: v + TIMESTEPS: 1000 + MIN_SNR_GAMMA: + ZERO_TERMINAL_SNR: True + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-2-1@v2-1_768-ema-pruned.safetensors + IGNORE_KEYS: [ ] + SCALE_FACTOR: 0.18215 + SIZE_FACTOR: 8 + DEFAULT_N_PROMPT: + SCHEDULE_ARGS: + "NAME": "scaled_linear" + "BETA_MIN": 0.00085 + "BETA_MAX": 0.012 + USE_EMA: False + # + DIFFUSION_MODEL: + NAME: DiffusionUNet + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + MODEL_CHANNELS: 320 + NUM_HEADS_CHANNELS: 64 + NUM_RES_BLOCKS: 2 + ATTENTION_RESOLUTIONS: [ 4, 2, 1 ] + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + USE_CHECKPOINT: False + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 1 + CONTEXT_DIM: 1024 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + PRETRAINED_MODEL: + IGNORE_KEYS: [] + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + PRETRAINED_MODEL: + IGNORE_KEYS: [ ] + BATCH_SIZE: 4 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + TOKENIZER: + NAME: OpenClipTokenizer + LENGTH: 77 + # + COND_STAGE_MODEL: + NAME: FrozenOpenCLIPEmbedder + ARCH: ViT-H-14 + PRETRAINED_MODEL: + LAYER: penultimate + # + LOSS: + NAME: ReconstructLoss + LOSS_TYPE: l2 + # + CONTROL_MODEL: + NAME: CSCTuners + PRE_HINT_IN_CHANNELS: 3 + PRE_HINT_OUT_CHANNELS: 256 + DENSE_HINT_KERNAL: 3 + SCALE: 1.0 + SC_TUNER_CFG: + NAME: SCTuner + TUNER_NAME: SCEAdapter + DOWN_RATIO: 1.0 + CONTROL_ANNO: + NAME: OpenposeAnnotator + BODY_MODEL_PATH: ms://damo/scepter_scedit@annotator/ckpts/body_pose_model.pth + HAND_MODEL_PATH: ms://damo/scepter_scedit@annotator/ckpts/hand_pose_model.pth + # + SAMPLE_ARGS: + SAMPLER: ddim + SAMPLE_STEPS: 50 + SEED: 2023 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 + DISCRETIZATION: trailing + IMAGE_SIZE: [768, 768] + RUN_TRAIN_N: False + # + OPTIMIZER: + NAME: AdamW + LEARNING_RATE: 0.064 + BETAS: [ 0.9, 0.999 ] + EPS: 1e-8 + WEIGHT_DECAY: 1e-2 + AMSGRAD: False + # + TRAIN_DATA: + NAME: ImageTextPairMSDataset + MODE: train + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train_short + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 1 + NUM_WORKERS: 4 + SAMPLER: + NAME: LoopSampler + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: Resize + SIZE: 768 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: CenterCrop + SIZE: 768 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ToNumpy + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image_preprocess' ] + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: torchvision + - NAME: Rename + INPUT_KEY: [ 'img', 'image_preprocess' ] + OUTPUT_KEY: [ 'image', 'image_preprocess' ] + - NAME: Select + KEYS: [ 'image', 'prompt', 'image_preprocess' ] + META_KEYS: [ 'data_key' ] + # + EVAL_DATA: + NAME: ImageTextPairMSDataset + MODE: eval + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train_short + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 10 + NUM_WORKERS: 4 + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: Resize + SIZE: 768 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: CenterCrop + SIZE: 768 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ToNumpy + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image_preprocess' ] + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: torchvision + - NAME: Rename + INPUT_KEY: [ 'img', 'image_preprocess' ] + OUTPUT_KEY: [ 'image', 'image_preprocess' ] + - NAME: Select + KEYS: [ 'image', 'prompt', 'image_preprocess' ] + META_KEYS: [ 'data_key' ] + # + TRAIN_HOOKS: + - + NAME: BackwardHook + PRIORITY: 0 + - + NAME: LogHook + LOG_INTERVAL: 50 + - + NAME: CheckpointHook + INTERVAL: 100 + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 + # + EVAL_HOOKS: + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 diff --git a/scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_color.yaml b/scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_color.yaml new file mode 100644 index 0000000..cdf7fa3 --- /dev/null +++ b/scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_color.yaml @@ -0,0 +1,378 @@ +ENV: + BACKEND: nccl +SOLVER: + NAME: LatentDiffusionSolver + RESUME_FROM: + LOAD_MODEL_ONLY: True + USE_FSDP: False + SHARDING_STRATEGY: + USE_AMP: True + DTYPE: float16 + CHANNELS_LAST: True + MAX_STEPS: 200 + MAX_EPOCHS: -1 + NUM_FOLDS: 1 + ACCU_STEP: 1 + EVAL_INTERVAL: 100 + # + WORK_DIR: ./cache/save_data/sdxl_1024_sce_ctr_color + LOG_FILE: std_log.txt + # + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + FREEZE: + FREEZE_PART: [ "first_stage_model", "cond_stage_model", "model" ] + TRAIN_PART: [ "control_blocks" ] + # + MODEL: + NAME: LatentDiffusionXLSCEControl + PARAMETERIZATION: eps + TIMESTEPS: 1000 + MIN_SNR_GAMMA: + ZERO_TERMINAL_SNR: False + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-xl-base-1.0@sd_xl_base_1.0.safetensors + IGNORE_KEYS: [ ] + SCALE_FACTOR: 0.13025 + SIZE_FACTOR: 8 + DEFAULT_N_PROMPT: + SCHEDULE_ARGS: + "NAME": "scaled_linear" + "BETA_MIN": 0.00085 + "BETA_MAX": 0.0120 + USE_EMA: False + LOAD_REFINER: False + # + DIFFUSION_MODEL: + NAME: DiffusionUNetXL + PRETRAINED_MODEL: + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + NUM_RES_BLOCKS: 2 + MODEL_CHANNELS: 320 + ATTENTION_RESOLUTIONS: [ 4, 2 ] + DROPOUT: 0 + CHANNEL_MULT: [ 1, 2, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + NUM_CLASSES: sequential + USE_CHECKPOINT: False + NUM_HEADS: -1 + NUM_HEADS_CHANNELS: 64 + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_NEW_ATTENTION_ORDER: True + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: [ 1, 2, 10 ] + CONTEXT_DIM: 2048 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + ADM_IN_CHANNELS: 2816 + USE_SENTENCE_EMB: False + USE_WORD_MAPPING: False + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + PRETRAINED_MODEL: + IGNORE_KEYS: [] + BATCH_SIZE: 1 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + COND_STAGE_MODEL: + NAME: GeneralConditioner + PRETRAINED_MODEL: + EMBEDDERS: + - + NAME: FrozenCLIPEmbedder + PRETRAINED_MODEL: ms://AI-ModelScope/clip-vit-large-patch14 + TOKENIZER_PATH: ms://AI-ModelScope/clip-vit-large-patch14 + MAX_LENGTH: 77 + FREEZE: True + LAYER: hidden + LAYER_IDX: 11 + USE_FINAL_LAYER_NORM: False + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: FrozenOpenCLIPEmbedder2 + ARCH: ViT-bigG-14 + PRETRAINED_MODEL: + MAX_LENGTH: 77 + FREEZE: True + ALWAYS_RETURN_POOLED: True + LEGACY: False + LAYER: penultimate + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "original_size_as_tuple" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "crop_coords_top_left" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "target_size_as_tuple" ] + LEGACY_UCG_VALUE: + # + REFINER_MODEL: + NAME: DiffusionUNetXL + PRETRAINED_MODEL: + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + NUM_RES_BLOCKS: 2 + MODEL_CHANNELS: 384 + ATTENTION_RESOLUTIONS: [ 4, 2 ] + DROPOUT: 0 + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + NUM_CLASSES: sequential + USE_CHECKPOINT: False + NUM_HEADS: -1 + NUM_HEADS_CHANNELS: 64 + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_NEW_ATTENTION_ORDER: True + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 4 + CONTEXT_DIM: [ 1280, 1280, 1280, 1280 ] + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + ADM_IN_CHANNELS: 2560 + USE_SENTENCE_EMB: False + USE_WORD_MAPPING: False + REFINER_COND_MODEL: + NAME: GeneralConditioner + PRETRAINED_MODEL: + EMBEDDERS: + - + NAME: FrozenOpenCLIPEmbedder2 + ARCH: ViT-bigG-14 + PRETRAINED_MODEL: + MAX_LENGTH: 77 + FREEZE: True + ALWAYS_RETURN_POOLED: True + LEGACY: False + LAYER: penultimate + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "original_size_as_tuple" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "crop_coords_top_left" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "aesthetic_score" ] + LEGACY_UCG_VALUE: + # + LOSS: + NAME: ReconstructLoss + LOSS_TYPE: l2 + # + CONTROL_MODEL: + NAME: CSCTuners + PRE_HINT_IN_CHANNELS: 3 + PRE_HINT_OUT_CHANNELS: 256 + DENSE_HINT_KERNAL: 3 + SCALE: 1.0 + SC_TUNER_CFG: + NAME: SCTuner + TUNER_NAME: SCEAdapter + DOWN_RATIO: 1.0 + CONTROL_ANNO: + NAME: ColorAnnotator + RATIO: 64 + # + SAMPLE_ARGS: + SAMPLER: ddim + SAMPLE_STEPS: 50 + SEED: 2023 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 + DISCRETIZATION: trailing + IMAGE_SIZE: [1024, 1024] + RUN_TRAIN_N: False + # + OPTIMIZER: + NAME: AdamW + LEARNING_RATE: 0.064 + BETAS: [ 0.9, 0.999 ] + EPS: 1e-8 + WEIGHT_DECAY: 1e-2 + AMSGRAD: False + # + TRAIN_DATA: + NAME: ImageTextPairMSDataset + MODE: train + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train_short + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 1 + NUM_WORKERS: 4 + SAMPLER: + NAME: LoopSampler + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: FlexibleResize + SIZE: 1024 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: FlexibleCropXL + SIZE: 1024 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ToNumpy + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image_preprocess' ] + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: torchvision + - NAME: Rename + INPUT_KEY: [ 'img', 'image_preprocess', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] + OUTPUT_KEY: [ 'image', 'image_preprocess', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left' ] + - NAME: Select + KEYS: [ 'image', 'prompt', 'image_preprocess', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left' ] + META_KEYS: [ 'data_key' ] + # + EVAL_DATA: + NAME: ImageTextPairMSDataset + MODE: eval + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train_short + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 10 + NUM_WORKERS: 4 + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: Resize + SIZE: 1024 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: CenterCrop + SIZE: 1024 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ToNumpy + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image_preprocess' ] + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: torchvision + - NAME: Rename + INPUT_KEY: [ 'img', 'image_preprocess' ] + OUTPUT_KEY: [ 'image', 'image_preprocess' ] + - NAME: Select + KEYS: [ 'image', 'prompt', 'image_preprocess' ] + META_KEYS: [ 'data_key' ] + # + TRAIN_HOOKS: + - + NAME: BackwardHook + PRIORITY: 0 + - + NAME: LogHook + LOG_INTERVAL: 50 + - + NAME: CheckpointHook + INTERVAL: 100 + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 + # + EVAL_HOOKS: + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 diff --git a/scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_color_datatxt.yaml b/scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_color_datatxt.yaml new file mode 100644 index 0000000..4a15c00 --- /dev/null +++ b/scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_color_datatxt.yaml @@ -0,0 +1,404 @@ +ENV: + BACKEND: nccl +SOLVER: + NAME: LatentDiffusionSolver + RESUME_FROM: + LOAD_MODEL_ONLY: True + USE_FSDP: False + SHARDING_STRATEGY: + USE_AMP: True + DTYPE: float16 + CHANNELS_LAST: True + MAX_STEPS: 200 + MAX_EPOCHS: -1 + NUM_FOLDS: 1 + ACCU_STEP: 1 + EVAL_INTERVAL: 100 + # + WORK_DIR: ./cache/save_data/sdxl_1024_sce_ctr_color_datatxt + LOG_FILE: std_log.txt + # + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + FREEZE: + FREEZE_PART: [ "first_stage_model", "cond_stage_model", "model" ] + TRAIN_PART: [ "control_blocks" ] + # + MODEL: + NAME: LatentDiffusionXLSCEControl + PARAMETERIZATION: eps + TIMESTEPS: 1000 + MIN_SNR_GAMMA: + ZERO_TERMINAL_SNR: False + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-xl-base-1.0@sd_xl_base_1.0.safetensors + IGNORE_KEYS: [ ] + SCALE_FACTOR: 0.13025 + SIZE_FACTOR: 8 + DEFAULT_N_PROMPT: + SCHEDULE_ARGS: + "NAME": "scaled_linear" + "BETA_MIN": 0.00085 + "BETA_MAX": 0.0120 + USE_EMA: False + LOAD_REFINER: False + # + DIFFUSION_MODEL: + NAME: DiffusionUNetXL + PRETRAINED_MODEL: + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + NUM_RES_BLOCKS: 2 + MODEL_CHANNELS: 320 + ATTENTION_RESOLUTIONS: [ 4, 2 ] + DROPOUT: 0 + CHANNEL_MULT: [ 1, 2, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + NUM_CLASSES: sequential + USE_CHECKPOINT: False + NUM_HEADS: -1 + NUM_HEADS_CHANNELS: 64 + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_NEW_ATTENTION_ORDER: True + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: [ 1, 2, 10 ] + CONTEXT_DIM: 2048 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + ADM_IN_CHANNELS: 2816 + USE_SENTENCE_EMB: False + USE_WORD_MAPPING: False + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + PRETRAINED_MODEL: + IGNORE_KEYS: [] + BATCH_SIZE: 1 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + COND_STAGE_MODEL: + NAME: GeneralConditioner + PRETRAINED_MODEL: + EMBEDDERS: + - + NAME: FrozenCLIPEmbedder + PRETRAINED_MODEL: ms://AI-ModelScope/clip-vit-large-patch14 + TOKENIZER_PATH: ms://AI-ModelScope/clip-vit-large-patch14 + MAX_LENGTH: 77 + FREEZE: True + LAYER: hidden + LAYER_IDX: 11 + USE_FINAL_LAYER_NORM: False + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: FrozenOpenCLIPEmbedder2 + ARCH: ViT-bigG-14 + PRETRAINED_MODEL: + MAX_LENGTH: 77 + FREEZE: True + ALWAYS_RETURN_POOLED: True + LEGACY: False + LAYER: penultimate + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "original_size_as_tuple" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "crop_coords_top_left" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "target_size_as_tuple" ] + LEGACY_UCG_VALUE: + # + REFINER_MODEL: + NAME: DiffusionUNetXL + PRETRAINED_MODEL: + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + NUM_RES_BLOCKS: 2 + MODEL_CHANNELS: 384 + ATTENTION_RESOLUTIONS: [ 4, 2 ] + DROPOUT: 0 + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + NUM_CLASSES: sequential + USE_CHECKPOINT: False + NUM_HEADS: -1 + NUM_HEADS_CHANNELS: 64 + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_NEW_ATTENTION_ORDER: True + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 4 + CONTEXT_DIM: [ 1280, 1280, 1280, 1280 ] + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + ADM_IN_CHANNELS: 2560 + USE_SENTENCE_EMB: False + USE_WORD_MAPPING: False + REFINER_COND_MODEL: + NAME: GeneralConditioner + PRETRAINED_MODEL: + EMBEDDERS: + - + NAME: FrozenOpenCLIPEmbedder2 + ARCH: ViT-bigG-14 + PRETRAINED_MODEL: + MAX_LENGTH: 77 + FREEZE: True + ALWAYS_RETURN_POOLED: True + LEGACY: False + LAYER: penultimate + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "original_size_as_tuple" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "crop_coords_top_left" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "aesthetic_score" ] + LEGACY_UCG_VALUE: + # + LOSS: + NAME: ReconstructLoss + LOSS_TYPE: l2 + # + CONTROL_MODEL: + NAME: CSCTuners + PRE_HINT_IN_CHANNELS: 3 + PRE_HINT_OUT_CHANNELS: 256 + DENSE_HINT_KERNAL: 3 + SCALE: 1.0 + SC_TUNER_CFG: + NAME: SCTuner + TUNER_NAME: SCEAdapter + DOWN_RATIO: 1.0 + CONTROL_ANNO: + NAME: ColorAnnotator + RATIO: 64 + # + SAMPLE_ARGS: + SAMPLER: ddim + SAMPLE_STEPS: 50 + SEED: 2023 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 + DISCRETIZATION: trailing + IMAGE_SIZE: [1024, 1024] + RUN_TRAIN_N: False + # + OPTIMIZER: + NAME: AdamW + LEARNING_RATE: 0.064 + BETAS: [ 0.9, 0.999 ] + EPS: 1e-8 + WEIGHT_DECAY: 1e-2 + AMSGRAD: False + # + TRAIN_DATA: + NAME: ImageTextPairDataset + MODE: train + P_ZERO: 0.1 + PIN_MEMORY: True + BATCH_SIZE: 4 + NUM_WORKERS: 4 + FILE_SYSTEM: + NAME: LocalFs + AUTO_CLEAN: False + SAMPLER: + NAME: MixtureOfSamplers + SUB_SAMPLERS: + - + NAME: MultiLevelBatchSampler + PROB: 1.0 + IMAGE_SIZE: [ 1024, 1024 ] + FIELDS: ["img_path", "width", "height", "prompt"] + DELIMITER: '#;#' + PATH_PREFIX: cache/datasets/3D_example_txt + PROMPT_PREFIX: '' + INDEX_FILE: cache/datasets/3D_example_txt/train.txt + # + TRANSFORMS: + - + NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - + NAME: FlexibleResize + INTERPOLATION: bilinear + SIZE: 1024 + INPUT_KEY: ['img'] + OUTPUT_KEY: ['img'] + BACKEND: pillow + - + NAME: FlexibleCropXL + INPUT_KEY: ['img'] + OUTPUT_KEY: ['img'] + BACKEND: pillow + - + NAME: ToNumpy + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image_preprocess' ] + - + NAME: ImageToTensor + INPUT_KEY: ['img'] + OUTPUT_KEY: ['img'] + BACKEND: pillow + - + NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: ['img'] + OUTPUT_KEY: ['img'] + BACKEND: torchvision + - + NAME: Select + KEYS: ['img', 'prompt', 'image_preprocess', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left'] + META_KEYS: [ 'img_path' ] + - + NAME: Rename + INPUT_KEY: ['img', 'image_preprocess', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left'] + OUTPUT_KEY: ['image', 'image_preprocess', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left'] + # + EVAL_DATA: + NAME: Text2ImageDataset + MODE: eval + PROMPT_FILE: cache/datasets/3D_example_txt/train.txt + PATH_PREFIX: cache/datasets/3D_example_txt + IMAGE_SIZE: [ 1024, 1024 ] + FIELDS: ["img_path", "width", "height", "prompt"] + DELIMITER: '#;#' + PROMPT_PREFIX: '' + USE_NUM: 8 + PIN_MEMORY: True + BATCH_SIZE: 4 + NUM_WORKERS: 4 + FILE_SYSTEM: + NAME: LocalFs + AUTO_CLEAN: False + # + TRANSFORMS: + - + NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - + NAME: FlexibleResize + INTERPOLATION: bilinear + SIZE: 1024 + INPUT_KEY: ['img'] + OUTPUT_KEY: ['img'] + BACKEND: pillow + - + NAME: FlexibleCenterCrop + INPUT_KEY: ['img'] + OUTPUT_KEY: ['img'] + BACKEND: pillow + - + NAME: ToNumpy + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image_preprocess' ] + - + NAME: ImageToTensor + INPUT_KEY: ['img'] + OUTPUT_KEY: ['img'] + BACKEND: pillow + - + NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: ['img'] + OUTPUT_KEY: ['img'] + BACKEND: torchvision + - + NAME: Rename + INPUT_KEY: [ 'img', 'image_preprocess' ] + OUTPUT_KEY: [ 'image', 'image_preprocess' ] + - + NAME: Select + KEYS: [ 'image', 'prompt', 'image_preprocess' ] + META_KEYS: [ ] + # + TRAIN_HOOKS: + - + NAME: BackwardHook + PRIORITY: 0 + - + NAME: LogHook + LOG_INTERVAL: 50 + - + NAME: CheckpointHook + INTERVAL: 100 + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 + # + EVAL_HOOKS: + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 diff --git a/scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_depth.yaml b/scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_depth.yaml new file mode 100644 index 0000000..e4b33ab --- /dev/null +++ b/scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_depth.yaml @@ -0,0 +1,378 @@ +ENV: + BACKEND: nccl +SOLVER: + NAME: LatentDiffusionSolver + RESUME_FROM: + LOAD_MODEL_ONLY: True + USE_FSDP: False + SHARDING_STRATEGY: + USE_AMP: True + DTYPE: float16 + CHANNELS_LAST: True + MAX_STEPS: 200 + MAX_EPOCHS: -1 + NUM_FOLDS: 1 + ACCU_STEP: 1 + EVAL_INTERVAL: 100 + # + WORK_DIR: ./cache/save_data/sdxl_1024_sce_ctr_depth + LOG_FILE: std_log.txt + # + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + FREEZE: + FREEZE_PART: [ "first_stage_model", "cond_stage_model", "model" ] + TRAIN_PART: [ "control_blocks" ] + # + MODEL: + NAME: LatentDiffusionXLSCEControl + PARAMETERIZATION: eps + TIMESTEPS: 1000 + MIN_SNR_GAMMA: + ZERO_TERMINAL_SNR: False + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-xl-base-1.0@sd_xl_base_1.0.safetensors + IGNORE_KEYS: [ ] + SCALE_FACTOR: 0.13025 + SIZE_FACTOR: 8 + DEFAULT_N_PROMPT: + SCHEDULE_ARGS: + "NAME": "scaled_linear" + "BETA_MIN": 0.00085 + "BETA_MAX": 0.0120 + USE_EMA: False + LOAD_REFINER: False + # + DIFFUSION_MODEL: + NAME: DiffusionUNetXL + PRETRAINED_MODEL: + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + NUM_RES_BLOCKS: 2 + MODEL_CHANNELS: 320 + ATTENTION_RESOLUTIONS: [ 4, 2 ] + DROPOUT: 0 + CHANNEL_MULT: [ 1, 2, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + NUM_CLASSES: sequential + USE_CHECKPOINT: False + NUM_HEADS: -1 + NUM_HEADS_CHANNELS: 64 + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_NEW_ATTENTION_ORDER: True + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: [ 1, 2, 10 ] + CONTEXT_DIM: 2048 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + ADM_IN_CHANNELS: 2816 + USE_SENTENCE_EMB: False + USE_WORD_MAPPING: False + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + PRETRAINED_MODEL: + IGNORE_KEYS: [] + BATCH_SIZE: 1 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + COND_STAGE_MODEL: + NAME: GeneralConditioner + PRETRAINED_MODEL: + EMBEDDERS: + - + NAME: FrozenCLIPEmbedder + PRETRAINED_MODEL: ms://AI-ModelScope/clip-vit-large-patch14 + TOKENIZER_PATH: ms://AI-ModelScope/clip-vit-large-patch14 + MAX_LENGTH: 77 + FREEZE: True + LAYER: hidden + LAYER_IDX: 11 + USE_FINAL_LAYER_NORM: False + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: FrozenOpenCLIPEmbedder2 + ARCH: ViT-bigG-14 + PRETRAINED_MODEL: + MAX_LENGTH: 77 + FREEZE: True + ALWAYS_RETURN_POOLED: True + LEGACY: False + LAYER: penultimate + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "original_size_as_tuple" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "crop_coords_top_left" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "target_size_as_tuple" ] + LEGACY_UCG_VALUE: + # + REFINER_MODEL: + NAME: DiffusionUNetXL + PRETRAINED_MODEL: + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + NUM_RES_BLOCKS: 2 + MODEL_CHANNELS: 384 + ATTENTION_RESOLUTIONS: [ 4, 2 ] + DROPOUT: 0 + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + NUM_CLASSES: sequential + USE_CHECKPOINT: False + NUM_HEADS: -1 + NUM_HEADS_CHANNELS: 64 + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_NEW_ATTENTION_ORDER: True + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 4 + CONTEXT_DIM: [ 1280, 1280, 1280, 1280 ] + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + ADM_IN_CHANNELS: 2560 + USE_SENTENCE_EMB: False + USE_WORD_MAPPING: False + REFINER_COND_MODEL: + NAME: GeneralConditioner + PRETRAINED_MODEL: + EMBEDDERS: + - + NAME: FrozenOpenCLIPEmbedder2 + ARCH: ViT-bigG-14 + PRETRAINED_MODEL: + MAX_LENGTH: 77 + FREEZE: True + ALWAYS_RETURN_POOLED: True + LEGACY: False + LAYER: penultimate + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "original_size_as_tuple" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "crop_coords_top_left" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "aesthetic_score" ] + LEGACY_UCG_VALUE: + # + LOSS: + NAME: ReconstructLoss + LOSS_TYPE: l2 + # + CONTROL_MODEL: + NAME: CSCTuners + PRE_HINT_IN_CHANNELS: 3 + PRE_HINT_OUT_CHANNELS: 256 + DENSE_HINT_KERNAL: 3 + SCALE: 1.0 + SC_TUNER_CFG: + NAME: SCTuner + TUNER_NAME: SCEAdapter + DOWN_RATIO: 1.0 + CONTROL_ANNO: + NAME: MidasDetector + PRETRAINED_MODEL: ms://damo/scepter_scedit@annotator/ckpts/dpt_hybrid-midas-501f0c75.pt + # + SAMPLE_ARGS: + SAMPLER: ddim + SAMPLE_STEPS: 50 + SEED: 2023 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 + DISCRETIZATION: trailing + IMAGE_SIZE: [1024, 1024] + RUN_TRAIN_N: False + # + OPTIMIZER: + NAME: AdamW + LEARNING_RATE: 0.064 + BETAS: [ 0.9, 0.999 ] + EPS: 1e-8 + WEIGHT_DECAY: 1e-2 + AMSGRAD: False + # + TRAIN_DATA: + NAME: ImageTextPairMSDataset + MODE: train + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train_short + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 1 + NUM_WORKERS: 4 + SAMPLER: + NAME: LoopSampler + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: FlexibleResize + SIZE: 1024 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: FlexibleCropXL + SIZE: 1024 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ToNumpy + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image_preprocess' ] + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: torchvision + - NAME: Rename + INPUT_KEY: [ 'img', 'image_preprocess', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] + OUTPUT_KEY: [ 'image', 'image_preprocess', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left' ] + - NAME: Select + KEYS: [ 'image', 'prompt', 'image_preprocess', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left' ] + META_KEYS: [ 'data_key' ] + # + EVAL_DATA: + NAME: ImageTextPairMSDataset + MODE: eval + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train_short + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 10 + NUM_WORKERS: 4 + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: Resize + SIZE: 1024 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: CenterCrop + SIZE: 1024 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ToNumpy + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image_preprocess' ] + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: torchvision + - NAME: Rename + INPUT_KEY: [ 'img', 'image_preprocess' ] + OUTPUT_KEY: [ 'image', 'image_preprocess' ] + - NAME: Select + KEYS: [ 'image', 'prompt', 'image_preprocess' ] + META_KEYS: [ 'data_key' ] + # + TRAIN_HOOKS: + - + NAME: BackwardHook + PRIORITY: 0 + - + NAME: LogHook + LOG_INTERVAL: 50 + - + NAME: CheckpointHook + INTERVAL: 100 + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 + # + EVAL_HOOKS: + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 diff --git a/scepter/methods/scedit/t2i/sd15_512_sce_t2i.yaml b/scepter/methods/scedit/t2i/sd15_512_sce_t2i.yaml new file mode 100644 index 0000000..dc4115b --- /dev/null +++ b/scepter/methods/scedit/t2i/sd15_512_sce_t2i.yaml @@ -0,0 +1,228 @@ +ENV: + BACKEND: nccl +SOLVER: + NAME: LatentDiffusionSolver + RESUME_FROM: + LOAD_MODEL_ONLY: True + USE_FSDP: False + SHARDING_STRATEGY: + USE_AMP: True + DTYPE: float16 + CHANNELS_LAST: True + MAX_STEPS: 2000 + MAX_EPOCHS: -1 + NUM_FOLDS: 1 + ACCU_STEP: 1 + EVAL_INTERVAL: 100 + # + WORK_DIR: ./cache/save_data/sd15_512_sce_t2i + LOG_FILE: std_log.txt + # + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + FREEZE: + FREEZE_PART: [ "first_stage_model", "cond_stage_model", "model" ] + TRAIN_PART: [ "lsc_identity" ] + # + MODEL: + NAME: LatentDiffusionSCETuning + PARAMETERIZATION: eps + TIMESTEPS: 1000 + MIN_SNR_GAMMA: + ZERO_TERMINAL_SNR: False + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-v1-5@v1-5-pruned-emaonly.safetensors + IGNORE_KEYS: [ ] + SCALE_FACTOR: 0.18215 + SIZE_FACTOR: 8 + # DEFAULT_N_PROMPT: 'lowres, error, worst quality, low quality, jpeg artifacts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, dehydrated, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck, username, watermark, signature' + DEFAULT_N_PROMPT: + SCHEDULE_ARGS: + "NAME": "scaled_linear" + "BETA_MIN": 0.00085 + "BETA_MAX": 0.012 + USE_EMA: False + # + DIFFUSION_MODEL: + NAME: DiffusionUNet + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + MODEL_CHANNELS: 320 + NUM_HEADS: 8 + NUM_RES_BLOCKS: 2 + ATTENTION_RESOLUTIONS: [ 4, 2, 1 ] + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + USE_CHECKPOINT: False + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 1 + CONTEXT_DIM: 768 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: False + PRETRAINED_MODEL: + IGNORE_KEYS: [] + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + PRETRAINED_MODEL: + IGNORE_KEYS: [] + BATCH_SIZE: 4 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + TOKENIZER: + NAME: ClipTokenizer + PRETRAINED_PATH: ms://AI-ModelScope/clip-vit-large-patch14 + LENGTH: 77 + CLEAN: True + # + COND_STAGE_MODEL: + NAME: FrozenCLIPEmbedder + FREEZE: True + LAYER: last + PRETRAINED_MODEL: ms://AI-ModelScope/clip-vit-large-patch14 + # + LOSS: + NAME: ReconstructLoss + LOSS_TYPE: l2 + # + TUNER_MODEL: + SC_TUNER_CFG: + NAME: SCTuner + TUNER_NAME: SCEAdapter + DOWN_RATIO: 1.0 + # + SAMPLE_ARGS: + SAMPLER: ddim + SAMPLE_STEPS: 50 + SEED: 2023 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 + DISCRETIZATION: trailing + IMAGE_SIZE: [512, 512] + RUN_TRAIN_N: False + # + OPTIMIZER: + NAME: AdamW + LEARNING_RATE: 0.064 + BETAS: [ 0.9, 0.999 ] + EPS: 1e-8 + WEIGHT_DECAY: 1e-2 + AMSGRAD: False + # + TRAIN_DATA: + NAME: ImageTextPairMSDataset + MODE: train + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train_short + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 1 + NUM_WORKERS: 4 + SAMPLER: + NAME: LoopSampler + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: Resize + SIZE: 512 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: CenterCrop + SIZE: 512 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image' ] + BACKEND: torchvision + - NAME: Select + KEYS: [ 'image', 'prompt' ] + META_KEYS: [ 'data_key' ] + # + EVAL_DATA: + NAME: ImageTextPairMSDataset + MODE: eval + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_REMAP_KEYS: { 'Image': 'Target:FILE' } + MS_DATASET_SPLIT: test_short + OUTPUT_SIZE: [512, 512] + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 4 + NUM_WORKERS: 4 + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + TRANSFORMS: + - + NAME: Select + KEYS: ['prompt'] + META_KEYS: ['image_size'] + # + TRAIN_HOOKS: + - + NAME: BackwardHook + PRIORITY: 0 + - + NAME: LogHook + LOG_INTERVAL: 50 + - + NAME: CheckpointHook + INTERVAL: 1000 + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 + # + EVAL_HOOKS: + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 diff --git a/scepter/methods/SCEdit/t2i_sd15_512_sce.yaml b/scepter/methods/scedit/t2i/sd15_512_sce_t2i_swift.yaml similarity index 98% rename from scepter/methods/SCEdit/t2i_sd15_512_sce.yaml rename to scepter/methods/scedit/t2i/sd15_512_sce_t2i_swift.yaml index defb3b4..088a3f3 100644 --- a/scepter/methods/SCEdit/t2i_sd15_512_sce.yaml +++ b/scepter/methods/scedit/t2i/sd15_512_sce_t2i_swift.yaml @@ -15,14 +15,14 @@ SOLVER: ACCU_STEP: 1 EVAL_INTERVAL: 100 # - WORK_DIR: ./cache/t2i_sd15_512_sce + WORK_DIR: ./cache/save_data/sd15_512_sce_t2i_swift LOG_FILE: std_log.txt # FILE_SYSTEM: NAME: "ModelscopeFs" TEMP_DIR: "./cache/data" # - TUNER: + TUNER: - NAME: SwiftSCETuning DIMS: [1280, 1280, 1280, 1280, 1280, 640, 640, 640, 320, 320, 320, 320] @@ -125,7 +125,7 @@ SOLVER: SAMPLE_STEPS: 50 SEED: 2023 GUIDE_SCALE: 7.5 - GUIDE_RESCALE: + GUIDE_RESCALE: 0.5 DISCRETIZATION: trailing IMAGE_SIZE: [512, 512] RUN_TRAIN_N: False diff --git a/scepter/methods/scedit/t2i/sd21_768_sce_t2i.yaml b/scepter/methods/scedit/t2i/sd21_768_sce_t2i.yaml new file mode 100644 index 0000000..3a30df4 --- /dev/null +++ b/scepter/methods/scedit/t2i/sd21_768_sce_t2i.yaml @@ -0,0 +1,224 @@ +ENV: + BACKEND: nccl +SOLVER: + NAME: LatentDiffusionSolver + RESUME_FROM: + LOAD_MODEL_ONLY: True + USE_FSDP: False + SHARDING_STRATEGY: + USE_AMP: True + DTYPE: float16 + CHANNELS_LAST: True + MAX_STEPS: 2000 + MAX_EPOCHS: -1 + NUM_FOLDS: 1 + ACCU_STEP: 1 + EVAL_INTERVAL: 100 + # + WORK_DIR: ./cache/save_data/sd21_768_sce_t2i + LOG_FILE: std_log.txt + # + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + FREEZE: + FREEZE_PART: [ "first_stage_model", "cond_stage_model", "model" ] + TRAIN_PART: [ "lsc_identity" ] + # + MODEL: + NAME: LatentDiffusionSCETuning + PARAMETERIZATION: v + TIMESTEPS: 1000 + MIN_SNR_GAMMA: + ZERO_TERMINAL_SNR: False + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-2-1@v2-1_768-ema-pruned.safetensors + IGNORE_KEYS: [ ] + SCALE_FACTOR: 0.18215 + SIZE_FACTOR: 8 + DEFAULT_N_PROMPT: + SCHEDULE_ARGS: + "NAME": "scaled_linear" + "BETA_MIN": 0.00085 + "BETA_MAX": 0.012 + USE_EMA: False + # + DIFFUSION_MODEL: + NAME: DiffusionUNet + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + MODEL_CHANNELS: 320 + NUM_HEADS_CHANNELS: 64 + NUM_RES_BLOCKS: 2 + ATTENTION_RESOLUTIONS: [ 4, 2, 1 ] + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + USE_CHECKPOINT: False + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 1 + CONTEXT_DIM: 1024 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + PRETRAINED_MODEL: + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + PRETRAINED_MODEL: + IGNORE_KEYS: [ ] + BATCH_SIZE: 4 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + TOKENIZER: + NAME: OpenClipTokenizer + LENGTH: 77 + # + COND_STAGE_MODEL: + NAME: FrozenOpenCLIPEmbedder + ARCH: ViT-H-14 + PRETRAINED_MODEL: + LAYER: penultimate + # + LOSS: + NAME: ReconstructLoss + LOSS_TYPE: l2 + # + TUNER_MODEL: + SC_TUNER_CFG: + NAME: SCTuner + TUNER_NAME: SCEAdapter + DOWN_RATIO: 1.0 + # + SAMPLE_ARGS: + SAMPLER: ddim + SAMPLE_STEPS: 50 + SEED: 2023 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 + DISCRETIZATION: trailing + IMAGE_SIZE: [768, 768] + RUN_TRAIN_N: False + # + OPTIMIZER: + NAME: AdamW + LEARNING_RATE: 0.064 + BETAS: [ 0.9, 0.999 ] + EPS: 1e-8 + WEIGHT_DECAY: 1e-2 + AMSGRAD: False + # + TRAIN_DATA: + NAME: ImageTextPairMSDataset + MODE: train + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train_short + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 1 + NUM_WORKERS: 4 + SAMPLER: + NAME: LoopSampler + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: Resize + SIZE: 768 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: CenterCrop + SIZE: 768 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image' ] + BACKEND: torchvision + - NAME: Select + KEYS: [ 'image', 'prompt' ] + META_KEYS: [ 'data_key' ] + # + EVAL_DATA: + NAME: ImageTextPairMSDataset + MODE: eval + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_REMAP_KEYS: { 'Image': 'Target:FILE' } + MS_DATASET_SPLIT: test_short + OUTPUT_SIZE: [768, 768] + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 4 + NUM_WORKERS: 4 + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + TRANSFORMS: + - + NAME: Select + KEYS: ['prompt'] + META_KEYS: ['image_size'] + # + TRAIN_HOOKS: + - + NAME: BackwardHook + PRIORITY: 0 + - + NAME: LogHook + LOG_INTERVAL: 50 + - + NAME: CheckpointHook + INTERVAL: 1000 + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 + # + EVAL_HOOKS: + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 diff --git a/scepter/methods/SCEdit/t2i_sd21_768_sce.yaml b/scepter/methods/scedit/t2i/sd21_768_sce_t2i_swift.yaml similarity index 98% rename from scepter/methods/SCEdit/t2i_sd21_768_sce.yaml rename to scepter/methods/scedit/t2i/sd21_768_sce_t2i_swift.yaml index 96b15c8..304c83c 100644 --- a/scepter/methods/SCEdit/t2i_sd21_768_sce.yaml +++ b/scepter/methods/scedit/t2i/sd21_768_sce_t2i_swift.yaml @@ -15,14 +15,14 @@ SOLVER: ACCU_STEP: 1 EVAL_INTERVAL: 100 # - WORK_DIR: ./cache/t2i_sd21_768_sce + WORK_DIR: ./cache/save_data/sd21_768_sce_t2i_swift LOG_FILE: std_log.txt # FILE_SYSTEM: NAME: "ModelscopeFs" TEMP_DIR: "./cache/data" # - TUNER: + TUNER: - NAME: SwiftSCETuning DIMS: [1280, 1280, 1280, 1280, 1280, 640, 640, 640, 320, 320, 320, 320] @@ -121,7 +121,7 @@ SOLVER: SAMPLE_STEPS: 50 SEED: 2023 GUIDE_SCALE: 7.5 - GUIDE_RESCALE: + GUIDE_RESCALE: 0.5 DISCRETIZATION: trailing IMAGE_SIZE: [768, 768] RUN_TRAIN_N: False diff --git a/scepter/methods/scedit/t2i/sdxl_1024_sce_t2i.yaml b/scepter/methods/scedit/t2i/sdxl_1024_sce_t2i.yaml new file mode 100644 index 0000000..2980236 --- /dev/null +++ b/scepter/methods/scedit/t2i/sdxl_1024_sce_t2i.yaml @@ -0,0 +1,342 @@ +ENV: + BACKEND: nccl +SOLVER: + NAME: LatentDiffusionSolver + RESUME_FROM: + LOAD_MODEL_ONLY: True + USE_FSDP: False + SHARDING_STRATEGY: + USE_AMP: True + DTYPE: float16 + CHANNELS_LAST: True + MAX_STEPS: 2000 + MAX_EPOCHS: -1 + NUM_FOLDS: 1 + ACCU_STEP: 1 + EVAL_INTERVAL: 100 + # + WORK_DIR: ./cache/save_data/sdxl_1024_sce_t2i + LOG_FILE: std_log.txt + # + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + FREEZE: + FREEZE_PART: [ "first_stage_model", "cond_stage_model", "model" ] + TRAIN_PART: [ "lsc_identity" ] + # + MODEL: + NAME: LatentDiffusionXLSCETuning + PARAMETERIZATION: eps + TIMESTEPS: 1000 + MIN_SNR_GAMMA: + ZERO_TERMINAL_SNR: False + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-xl-base-1.0@sd_xl_base_1.0.safetensors + IGNORE_KEYS: [ ] + SCALE_FACTOR: 0.13025 + SIZE_FACTOR: 8 + # DEFAULT_N_PROMPT: 'lowres, error, worst quality, low quality, jpeg artifacts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, dehydrated, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck, username, watermark, signature' + DEFAULT_N_PROMPT: + SCHEDULE_ARGS: + "NAME": "scaled_linear" + "BETA_MIN": 0.00085 + "BETA_MAX": 0.0120 + USE_EMA: False + LOAD_REFINER: False + # + DIFFUSION_MODEL: + NAME: DiffusionUNetXL + PRETRAINED_MODEL: + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + NUM_RES_BLOCKS: 2 + MODEL_CHANNELS: 320 + ATTENTION_RESOLUTIONS: [ 4, 2 ] + DROPOUT: 0 + CHANNEL_MULT: [ 1, 2, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + NUM_CLASSES: sequential + USE_CHECKPOINT: False + NUM_HEADS: -1 + NUM_HEADS_CHANNELS: 64 + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_NEW_ATTENTION_ORDER: True + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: [ 1, 2, 10 ] + CONTEXT_DIM: 2048 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + ADM_IN_CHANNELS: 2816 + USE_SENTENCE_EMB: False + USE_WORD_MAPPING: False + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + PRETRAINED_MODEL: + IGNORE_KEYS: [] + BATCH_SIZE: 1 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + COND_STAGE_MODEL: + NAME: GeneralConditioner + PRETRAINED_MODEL: + EMBEDDERS: + - + NAME: FrozenCLIPEmbedder + PRETRAINED_MODEL: ms://AI-ModelScope/clip-vit-large-patch14 + TOKENIZER_PATH: ms://AI-ModelScope/clip-vit-large-patch14 + MAX_LENGTH: 77 + FREEZE: True + LAYER: hidden + LAYER_IDX: 11 + USE_FINAL_LAYER_NORM: False + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: FrozenOpenCLIPEmbedder2 + ARCH: ViT-bigG-14 + PRETRAINED_MODEL: + MAX_LENGTH: 77 + FREEZE: True + ALWAYS_RETURN_POOLED: True + LEGACY: False + LAYER: penultimate + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "original_size_as_tuple" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "crop_coords_top_left" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "target_size_as_tuple" ] + LEGACY_UCG_VALUE: + # + REFINER_MODEL: + NAME: DiffusionUNetXL + PRETRAINED_MODEL: + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + NUM_RES_BLOCKS: 2 + MODEL_CHANNELS: 384 + ATTENTION_RESOLUTIONS: [ 4, 2 ] + DROPOUT: 0 + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + NUM_CLASSES: sequential + USE_CHECKPOINT: False + NUM_HEADS: -1 + NUM_HEADS_CHANNELS: 64 + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_NEW_ATTENTION_ORDER: True + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 4 + CONTEXT_DIM: [ 1280, 1280, 1280, 1280 ] + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + ADM_IN_CHANNELS: 2560 + USE_SENTENCE_EMB: False + USE_WORD_MAPPING: False + REFINER_COND_MODEL: + NAME: GeneralConditioner + PRETRAINED_MODEL: + EMBEDDERS: + - + NAME: FrozenOpenCLIPEmbedder2 + ARCH: ViT-bigG-14 + PRETRAINED_MODEL: + MAX_LENGTH: 77 + FREEZE: True + ALWAYS_RETURN_POOLED: True + LEGACY: False + LAYER: penultimate + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "original_size_as_tuple" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "crop_coords_top_left" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "aesthetic_score" ] + LEGACY_UCG_VALUE: + # + LOSS: + NAME: ReconstructLoss + LOSS_TYPE: l2 + # + TUNER_MODEL: + SC_TUNER_CFG: + NAME: SCTuner + TUNER_NAME: SCEAdapter + DOWN_RATIO: 1.0 + # + SAMPLE_ARGS: + SAMPLER: ddim + SAMPLE_STEPS: 50 + SEED: 2023 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 + DISCRETIZATION: trailing + IMAGE_SIZE: [1024, 1024] + RUN_TRAIN_N: False + # + OPTIMIZER: + NAME: AdamW + LEARNING_RATE: 0.064 + BETAS: [ 0.9, 0.999 ] + EPS: 1e-8 + WEIGHT_DECAY: 1e-2 + AMSGRAD: False + # + TRAIN_DATA: + NAME: ImageTextPairMSDataset + MODE: train + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train_short + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 1 + NUM_WORKERS: 4 + SAMPLER: + NAME: LoopSampler + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: FlexibleResize + INTERPOLATION: bicubic + SIZE: 1024 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: FlexibleCropXL + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: torchvision + - NAME: Select + KEYS: [ 'img', 'prompt', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] + META_KEYS: [ 'data_key', 'img_path' ] + - NAME: Rename + INPUT_KEY: [ 'img', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] + OUTPUT_KEY: [ 'image', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left' ] + # + EVAL_DATA: + NAME: ImageTextPairMSDataset + MODE: eval + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_REMAP_KEYS: { 'Image': 'Target:FILE' } + MS_DATASET_SPLIT: test_short + OUTPUT_SIZE: [ 1024, 1024 ] + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 4 + NUM_WORKERS: 4 + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + TRANSFORMS: + - NAME: Select + KEYS: [ 'prompt' ] + META_KEYS: [ 'image_size' ] + # + TRAIN_HOOKS: + - + NAME: BackwardHook + PRIORITY: 0 + - + NAME: LogHook + LOG_INTERVAL: 50 + - + NAME: CheckpointHook + INTERVAL: 1000 + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 + # + EVAL_HOOKS: + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 diff --git a/scepter/methods/scedit/t2i/sdxl_1024_sce_t2i_datatxt.yaml b/scepter/methods/scedit/t2i/sdxl_1024_sce_t2i_datatxt.yaml new file mode 100644 index 0000000..49cca0b --- /dev/null +++ b/scepter/methods/scedit/t2i/sdxl_1024_sce_t2i_datatxt.yaml @@ -0,0 +1,355 @@ +ENV: + BACKEND: nccl +SOLVER: + NAME: LatentDiffusionSolver + RESUME_FROM: + LOAD_MODEL_ONLY: True + USE_FSDP: False + SHARDING_STRATEGY: + USE_AMP: True + DTYPE: float16 + CHANNELS_LAST: True + MAX_STEPS: 2000 + MAX_EPOCHS: -1 + NUM_FOLDS: 1 + ACCU_STEP: 1 + EVAL_INTERVAL: 100 + # + WORK_DIR: ./cache/save_data/sdxl_1024_sce_t2i_datatxt + LOG_FILE: std_log.txt + # + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + FREEZE: + FREEZE_PART: [ "first_stage_model", "cond_stage_model", "model" ] + TRAIN_PART: [ "lsc_identity" ] + # + MODEL: + NAME: LatentDiffusionXLSCETuning + PARAMETERIZATION: eps + TIMESTEPS: 1000 + MIN_SNR_GAMMA: + ZERO_TERMINAL_SNR: False + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-xl-base-1.0@sd_xl_base_1.0.safetensors + IGNORE_KEYS: [ ] + SCALE_FACTOR: 0.13025 + SIZE_FACTOR: 8 + # DEFAULT_N_PROMPT: 'lowres, error, worst quality, low quality, jpeg artifacts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, dehydrated, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck, username, watermark, signature' + DEFAULT_N_PROMPT: + SCHEDULE_ARGS: + "NAME": "scaled_linear" + "BETA_MIN": 0.00085 + "BETA_MAX": 0.0120 + USE_EMA: False + LOAD_REFINER: False + # + DIFFUSION_MODEL: + NAME: DiffusionUNetXL + PRETRAINED_MODEL: + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + NUM_RES_BLOCKS: 2 + MODEL_CHANNELS: 320 + ATTENTION_RESOLUTIONS: [ 4, 2 ] + DROPOUT: 0 + CHANNEL_MULT: [ 1, 2, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + NUM_CLASSES: sequential + USE_CHECKPOINT: False + NUM_HEADS: -1 + NUM_HEADS_CHANNELS: 64 + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_NEW_ATTENTION_ORDER: True + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: [ 1, 2, 10 ] + CONTEXT_DIM: 2048 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + ADM_IN_CHANNELS: 2816 + USE_SENTENCE_EMB: False + USE_WORD_MAPPING: False + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + PRETRAINED_MODEL: + IGNORE_KEYS: [] + BATCH_SIZE: 1 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + COND_STAGE_MODEL: + NAME: GeneralConditioner + PRETRAINED_MODEL: + EMBEDDERS: + - + NAME: FrozenCLIPEmbedder + PRETRAINED_MODEL: ms://AI-ModelScope/clip-vit-large-patch14 + TOKENIZER_PATH: ms://AI-ModelScope/clip-vit-large-patch14 + MAX_LENGTH: 77 + FREEZE: True + LAYER: hidden + LAYER_IDX: 11 + USE_FINAL_LAYER_NORM: False + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: FrozenOpenCLIPEmbedder2 + ARCH: ViT-bigG-14 + PRETRAINED_MODEL: + MAX_LENGTH: 77 + FREEZE: True + ALWAYS_RETURN_POOLED: True + LEGACY: False + LAYER: penultimate + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "original_size_as_tuple" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "crop_coords_top_left" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "target_size_as_tuple" ] + LEGACY_UCG_VALUE: + # + REFINER_MODEL: + NAME: DiffusionUNetXL + PRETRAINED_MODEL: + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + NUM_RES_BLOCKS: 2 + MODEL_CHANNELS: 384 + ATTENTION_RESOLUTIONS: [ 4, 2 ] + DROPOUT: 0 + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + NUM_CLASSES: sequential + USE_CHECKPOINT: False + NUM_HEADS: -1 + NUM_HEADS_CHANNELS: 64 + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_NEW_ATTENTION_ORDER: True + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 4 + CONTEXT_DIM: [ 1280, 1280, 1280, 1280 ] + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + ADM_IN_CHANNELS: 2560 + USE_SENTENCE_EMB: False + USE_WORD_MAPPING: False + REFINER_COND_MODEL: + NAME: GeneralConditioner + PRETRAINED_MODEL: + EMBEDDERS: + - + NAME: FrozenOpenCLIPEmbedder2 + ARCH: ViT-bigG-14 + PRETRAINED_MODEL: + MAX_LENGTH: 77 + FREEZE: True + ALWAYS_RETURN_POOLED: True + LEGACY: False + LAYER: penultimate + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "prompt" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "original_size_as_tuple" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "crop_coords_top_left" ] + LEGACY_UCG_VALUE: + - + NAME: ConcatTimestepEmbedderND + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: [ "aesthetic_score" ] + LEGACY_UCG_VALUE: + # + LOSS: + NAME: ReconstructLoss + LOSS_TYPE: l2 + # + TUNER_MODEL: + SC_TUNER_CFG: + NAME: SCTuner + TUNER_NAME: SCEAdapter + DOWN_RATIO: 1.0 + # + SAMPLE_ARGS: + SAMPLER: ddim + SAMPLE_STEPS: 50 + SEED: 2023 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 + DISCRETIZATION: trailing + IMAGE_SIZE: [1024, 1024] + RUN_TRAIN_N: False + # + OPTIMIZER: + NAME: AdamW + LEARNING_RATE: 0.064 + BETAS: [ 0.9, 0.999 ] + EPS: 1e-8 + WEIGHT_DECAY: 1e-2 + AMSGRAD: False + # + TRAIN_DATA: + NAME: ImageTextPairDataset + MODE: train + P_ZERO: 0.0 + PIN_MEMORY: True + BATCH_SIZE: 4 + NUM_WORKERS: 4 + FILE_SYSTEM: + NAME: LocalFs + AUTO_CLEAN: False + SAMPLER: + NAME: MixtureOfSamplers + SUB_SAMPLERS: + - + NAME: MultiLevelBatchSampler + PROB: 1.0 + IMAGE_SIZE: [ 1024, 1024 ] + FIELDS: ["img_path", "width", "height", "prompt"] + DELIMITER: '#;#' + PATH_PREFIX: cache/datasets/3D_example_txt + PROMPT_PREFIX: ' ' + INDEX_FILE: cache/datasets/3D_example_txt/train.txt + # + TRANSFORMS: + - + NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - + NAME: FlexibleResize + INTERPOLATION: bilinear + SIZE: 1024 + INPUT_KEY: ['img'] + OUTPUT_KEY: ['img'] + BACKEND: pillow + - + NAME: FlexibleCropXL + INPUT_KEY: ['img'] + OUTPUT_KEY: ['img'] + BACKEND: pillow + - + NAME: ImageToTensor + INPUT_KEY: ['img'] + OUTPUT_KEY: ['img'] + BACKEND: pillow + - + NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: ['img'] + OUTPUT_KEY: ['img'] + BACKEND: torchvision + - + NAME: Select + KEYS: ['img', 'prompt', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left'] + META_KEYS: [ 'img_path' ] + - + NAME: Rename + INPUT_KEY: ['img', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left'] + OUTPUT_KEY: ['image', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left'] + # + EVAL_DATA: + NAME: Text2ImageDataset + MODE: eval + PROMPT_FILE: cache/datasets/3D_example_txt/test.txt + IMAGE_SIZE: [ 1024, 1024 ] + FIELDS: ["prompt"] + DELIMITER: '#;#' + PROMPT_PREFIX: ' ' + PIN_MEMORY: True + BATCH_SIZE: 4 + NUM_WORKERS: 4 + FILE_SYSTEM: + NAME: LocalFs + AUTO_CLEAN: False + # + TRANSFORMS: + - + NAME: Select + KEYS: ['index', 'prompt'] + META_KEYS: ['image_size'] + # + TRAIN_HOOKS: + - + NAME: BackwardHook + PRIORITY: 0 + - + NAME: LogHook + LOG_INTERVAL: 50 + - + NAME: CheckpointHook + INTERVAL: 1000 + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 + # + EVAL_HOOKS: + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 diff --git a/scepter/methods/SCEdit/t2i_sdxl_1024_sce.yaml b/scepter/methods/scedit/t2i/sdxl_1024_sce_t2i_swift.yaml similarity index 93% rename from scepter/methods/SCEdit/t2i_sdxl_1024_sce.yaml rename to scepter/methods/scedit/t2i/sdxl_1024_sce_t2i_swift.yaml index b167c5e..dd38b0d 100644 --- a/scepter/methods/SCEdit/t2i_sdxl_1024_sce.yaml +++ b/scepter/methods/scedit/t2i/sdxl_1024_sce_t2i_swift.yaml @@ -15,14 +15,14 @@ SOLVER: ACCU_STEP: 1 EVAL_INTERVAL: 100 # - WORK_DIR: ./cache/t2i_sdxl_1024_sce + WORK_DIR: ./cache/save_data/sdxl_1024_sce_t2i_swift LOG_FILE: std_log.txt # FILE_SYSTEM: NAME: "ModelscopeFs" TEMP_DIR: "./cache/data" - # - TUNER: + # + TUNER: - NAME: SwiftSCETuning DIMS: [1280, 1280, 640, 640, 640, 320, 320, 320, 320] @@ -128,7 +128,7 @@ SOLVER: UCG_RATE: 0.0 INPUT_KEYS: [ "prompt" ] LEGACY_UCG_VALUE: - - + - NAME: FrozenOpenCLIPEmbedder2 ARCH: ViT-bigG-14 PRETRAINED_MODEL: @@ -141,21 +141,21 @@ SOLVER: UCG_RATE: 0.0 INPUT_KEYS: [ "prompt" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False UCG_RATE: 0.0 INPUT_KEYS: [ "original_size_as_tuple" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False UCG_RATE: 0.0 INPUT_KEYS: [ "crop_coords_top_left" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False @@ -207,21 +207,21 @@ SOLVER: UCG_RATE: 0.0 INPUT_KEYS: [ "prompt" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False UCG_RATE: 0.0 INPUT_KEYS: [ "original_size_as_tuple" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False UCG_RATE: 0.0 INPUT_KEYS: [ "crop_coords_top_left" ] LEGACY_UCG_VALUE: - - + - NAME: ConcatTimestepEmbedderND OUT_DIM: 256 IS_TRAINABLE: False @@ -237,8 +237,8 @@ SOLVER: SAMPLER: ddim SAMPLE_STEPS: 50 SEED: 2023 - GUIDE_SCALE: 5.0 - GUIDE_RESCALE: + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 DISCRETIZATION: trailing IMAGE_SIZE: [1024, 1024] RUN_TRAIN_N: False @@ -294,8 +294,8 @@ SOLVER: KEYS: [ 'img', 'prompt', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] META_KEYS: [ 'data_key', 'img_path' ] - NAME: Rename - IN_KEYS: [ 'img', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] - OUT_KEYS: [ 'image', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left' ] + INPUT_KEY: [ 'img', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] + OUTPUT_KEY: [ 'image', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left' ] # EVAL_DATA: NAME: ImageTextPairMSDataset @@ -321,15 +321,20 @@ SOLVER: META_KEYS: [ 'image_size' ] # TRAIN_HOOKS: - - NAME: BackwardHook + - + NAME: BackwardHook PRIORITY: 0 - - NAME: LogHook + - + NAME: LogHook LOG_INTERVAL: 50 - - NAME: CheckpointHook + - + NAME: CheckpointHook INTERVAL: 1000 - - NAME: ProbeDataHook + - + NAME: ProbeDataHook PROB_INTERVAL: 100 # EVAL_HOOKS: - - NAME: ProbeDataHook - PROB_INTERVAL: 100 \ No newline at end of file + - + NAME: ProbeDataHook + PROB_INTERVAL: 100 diff --git a/scepter/methods/studio/extensions/controllers/official_controllers.yaml b/scepter/methods/studio/extensions/controllers/official_controllers.yaml new file mode 100644 index 0000000..63a8c8d --- /dev/null +++ b/scepter/methods/studio/extensions/controllers/official_controllers.yaml @@ -0,0 +1,19 @@ +CONTROLLERS: + - NAME: canny + NAME_ZH: + DESCRIPTION: + BASE_MODEL: SD2.1 + TYPE: Canny + MODEL_PATH: ms://damo/scepter_scedit@controllable_model/SD2.1/canny_control/0_SwiftSCETuning + - NAME: openpose + NAME_ZH: + DESCRIPTION: + BASE_MODEL: SD2.1 + TYPE: Openpose + MODEL_PATH: ms://damo/scepter_scedit@controllable_model/SD2.1/pose_control/0_SwiftSCETuning + - NAME: color + NAME_ZH: + DESCRIPTION: + BASE_MODEL: SD2.1 + TYPE: Color + MODEL_PATH: ms://damo/scepter_scedit@controllable_model/SD2.1/color_control/0_SwiftSCETuning diff --git a/scepter/methods/studio/extensions/mantra_book/mantra_book.yaml b/scepter/methods/studio/extensions/mantra_book/mantra_book.yaml new file mode 100644 index 0000000..bc3ce95 --- /dev/null +++ b/scepter/methods/studio/extensions/mantra_book/mantra_book.yaml @@ -0,0 +1,6409 @@ +MANTRAS: + - + NAME: cinematic-diva + NAME_ZH: 电影歌星画风 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: UHD, 8K, ultra detailed, a cinematic photograph of {prompt}, beautiful lighting, great composition + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, NSFW + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/967b1852ea26dcf41360fc5542a0df6b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Abstract Expressionism + NAME_ZH: 抽象表现主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Abstract Expressionism Art, {prompt}, High contrast, minimalistic, colorful, stark, dramatic, expressionism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/11667c7a085b53a6ffbb76b83788f8b5.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Academia + NAME_ZH: 学院风 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Academia, {prompt}, preppy Ivy League style, stark, dramatic, chic boarding school, academia + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, grunge, sloppy, unkempt + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/c95197ef78312e2bbd45883bfbfa095a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Action Figure + NAME_ZH: 动作人偶 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Action Figure, {prompt}, plastic collectable action figure, collectable toy action figure + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/24ac67fe21833fc1300fba09d5de6090.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Adorable 3D Character + NAME_ZH: 可爱的3D角色 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Adorable 3D Character, {prompt}, 3D render, adorable character, 3D art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, grunge, sloppy, unkempt, photograph, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/31a0ffbfc93b5b336a3bedc0a9985a02.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Adorable Kawaii + NAME_ZH: 可爱卡哇伊风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Adorable Kawaii, {prompt}, pretty, cute, adorable, kawaii + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, gothic, dark, moody, monochromatic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/82624c429d504c8290d4c9147be64029.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Art Deco + NAME_ZH: 艺术装饰风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Art Deco, {prompt}, sleek, geometric forms, art deco style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/c60ef3e7ada8774c92bb6e73c570f819.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Art Nouveau + NAME_ZH: 新艺术风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Art Nouveau, beautiful art, {prompt}, sleek, organic forms, long, sinuous, art nouveau style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, industrial, mechanical + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/153d83e71fbf145d0aa5c41ecab0a505.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Astral Aura + NAME_ZH: 星体光环 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Astral Aura, {prompt}, astral, colorful aura, vibrant energy + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/e093c9d0f81037002e88f2a6c3f38a55.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Avant-garde + NAME_ZH: 先锋派 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Avant-garde, {prompt}, unusual, experimental, avant-garde art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/9921d1944893466edfc6a060faf4070e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Baroque + NAME_ZH: 巴洛克风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Baroque, {prompt}, dramatic, exuberant, grandeur, baroque art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/d8279be4bb34e5cb00a95919412154a4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Bauhaus-Style Poster + NAME_ZH: 包豪斯风格海报 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Bauhaus-Style Poster, {prompt}, simple geometric shapes, clean lines, primary colors, Bauhaus-Style Poster + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/4bd18b32c23e13b9e4fc7f65a1916eab.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Blueprint Schematic Drawing + NAME_ZH: 蓝图原理图绘制 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Blueprint Schematic Drawing, {prompt}, technical drawing, blueprint, schematic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/62392c3715267f7162a37a8ff1caa3a1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Caricature + NAME_ZH: 漫画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Caricature, {prompt}, exaggerated, comical, caricature + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/894f40ed44b37c3372e6a22b8ae577a4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Cel Shaded Art + NAME_ZH: 单色阴影艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Cel Shaded Art, {prompt}, 2D, flat color, toon shading, cel shaded style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/71c2e8a2cd1031b2bfae1640f7b72c88.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Character Design Sheet + NAME_ZH: 角色设计图 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Character Design Sheet, {prompt}, character reference sheet, character turn around + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/eacf2134aa51d4b4a6f2f35cc170f315.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Classicism Art + NAME_ZH: 古典主义艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Classicism Art, {prompt}, inspired by Roman and Greek culture, clarity, harmonious, classicism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/10025b4f3a09e6134086e3cdec4ef2c8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Color Field Painting + NAME_ZH: 色域绘画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Color Field Painting, {prompt}, abstract, simple, geometic, color field painting style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/80e5b4075c572c04cbb4e48c37b8366b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Colored Pencil Art + NAME_ZH: 彩色铅笔艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Colored Pencil Art, {prompt}, colored pencil strokes, light color, visible paper texture, colored pencil art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/9ae235d7f1a7c2a4edab52a5e9f9cbae.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Conceptual Art + NAME_ZH: 概念艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Conceptual Art, {prompt}, concept art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/cf2e6781997c6842a16155fdff911ef8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Constructivism + NAME_ZH: 结构主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Constructivism Art, {prompt}, minimalistic, geometric forms, constructivism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/d07feccabcadfd3310464bedba858bd1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Cubism + NAME_ZH: 立体主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Cubism Art, {prompt}, flat geometric forms, cubism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/aa8313f6c3cb9cafb9a7ec07db78df1c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dadaism + NAME_ZH: 达达主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Dadaism Art, {prompt}, satirical, nonsensical, dadaism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/db27030369cb3ccb042b8aea6bf635e2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dark Fantasy + NAME_ZH: 黑暗幻想 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Dark Fantasy Art, {prompt}, dark, moody, dark fantasy style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, bright, sunny + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/c88b6e641c707afc0c8d278ba7e1ac19.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dark Moody Atmosphere + NAME_ZH: 暗色忧郁氛围 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Dark Moody Atmosphere, {prompt}, dramatic, mysterious, dark moody atmosphere + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, vibrant, colorful, bright + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/3da915da2f5cedaf243e57e08163f35b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: DMT Art Style + NAME_ZH: DMT艺术风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: DMT Art Style, {prompt}, bright colors, surreal visuals, swirling patterns, DMT art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/d4a823d2bfa912ca4bb56d96f722f08f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Doodle Art + NAME_ZH: 涂鸦艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Doodle Art Style, {prompt}, drawing, freeform, swirling patterns, doodle art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/8e1e21745c149b9634d3ce96fc7d505f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Double Exposure + NAME_ZH: 双重曝光 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Double Exposure Style, {prompt}, double image ghost effect, image combination, double exposure style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/efd7aea4af1c4ede99fdfac17350e264.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dripping Paint Splatter Art + NAME_ZH: 滴漆溅画艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Dripping Paint Splatter Art, {prompt}, dramatic, paint drips, splatters, dripping paint + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/69fd81f5983107acc3d334af62915851.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Expressionism + NAME_ZH: 表现主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Expressionism Art Style, {prompt}, movement, contrast, emotional, exaggerated forms, expressionism art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/3dfa862bd1c80cec237e4a5717cea2bd.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Faded Polaroid Photo + NAME_ZH: 褪色的宝丽来照片 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Faded Polaroid Photo, {prompt}, analog, old faded photo, old polaroid + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, vibrant, colorful + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/f152edb4b3ca6248758b48115258ddfa.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fauvism + NAME_ZH: 野兽派 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Fauvism Art, {prompt}, painterly, bold colors, textured brushwork, fauvism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/0506b350cadcf8fca42da764cd6fd5bf.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Flat 2D Art + NAME_ZH: 扁平2D艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Flat 2D Art, {prompt}, simple flat color, 2-dimensional, Flat 2D Art Style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, 3D, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/940cfd34155634cf051e1b2942cca426.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fortnite Art Style + NAME_ZH: 堡垒之夜艺术风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Fortnite Art Style, {prompt}, 3D cartoon, colorful, Fortnite Art Style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/156f8d943ff6d283f7a34f265daaa46c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Futurism + NAME_ZH: 未来主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Futurism Art Style, {prompt}, dynamic, dramatic, Futurism Art Style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/855283cc2ab6283b627ef32d06a1ae0f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Glitchcore + NAME_ZH: 故障核心 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Glitchcore Art Style, {prompt}, dynamic, dramatic, distorted, vibrant colors, glitchcore art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/9af62376402a85774179e82cf7e0dc59.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Glo-fi + NAME_ZH: 光环音乐风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Glo-fi Art Style, {prompt}, dynamic, dramatic, vibrant colors, glo-fi art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/275a6e2a3297cec57f9b5a4a17b0f749.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Googie Art Style + NAME_ZH: 古奇艺术风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Googie Art Style, {prompt}, dynamic, dramatic, 1950's futurism, bold boomerang angles, Googie art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/08ee77586d7bec3f6bad7d60cee3c540.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Graffiti Art + NAME_ZH: 涂鸦艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Graffiti Art Style, {prompt}, dynamic, dramatic, vibrant colors, graffiti art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/57b751b11564cb22cd49ef21f2004a5f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Harlem Renaissance Art + NAME_ZH: 哈莱姆文艺复兴艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Harlem Renaissance Art Style, {prompt}, dynamic, dramatic, 1920s African American culture, Harlem Renaissance art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/d09ea3dadcd0a15d8fa247ee74a75e6b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: High Fashion + NAME_ZH: 高级时装 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: High Fashion, {prompt}, dynamic, dramatic, haute couture, elegant, ornate clothing, High Fashion + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/868f752bbb5ef992a0be36d7d13de3be.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Idyllic + NAME_ZH: 田园诗般的 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Idyllic, {prompt}, peaceful, happy, pleasant, happy, harmonious, picturesque, charming + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/55bab29eeb628e7a9ae018e45e7e24db.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Impressionism + NAME_ZH: 印象主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Impressionism, {prompt}, painterly, small brushstrokes, visible brushstrokes, impressionistic style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/0312b673dc6858a9864d7f45f0c5c1fc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Infographic Drawing + NAME_ZH: 信息图表绘制 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Infographic Drawing, {prompt}, diagram, infographic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/b09151f6e0883d26056b80fcc9d398bb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Ink Dripping Drawing + NAME_ZH: 墨水滴画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Ink Dripping Drawing, {prompt}, ink drawing, dripping ink + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, colorful, vibrant + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/5f09912a07e915250a96b2023db15821.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Japanese Ink Drawing + NAME_ZH: 日本墨画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Japanese Ink Drawing, {prompt}, ink drawing, inkwash, Japanese Ink Drawing + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, colorful, vibrant + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/633ad971ff30fe4717782fc6b5f92fda.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Knolling Photography + NAME_ZH: 秩序拍摄 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Knolling Photography, {prompt}, flat lay photography, object arrangment, knolling photography + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/89a205be3a276349ecddf0eeca43ed80.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Light Cheery Atmosphere + NAME_ZH: 轻快愉快的氛围 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Light Cheery Atmosphere, {prompt}, happy, joyful, cheerful, carefree, gleeful, lighthearted, pleasant atmosphere + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, monochromatic, dark, moody + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/0913ac9815f892411f8327a630f51ae4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Logo Design + NAME_ZH: 标志设计 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Logo Design, {prompt}, dynamic graphic art, vector art, minimalist, professional logo design + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/9aa040b0c60d289da9610c91ad9b7c7e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Luxurious Elegance + NAME_ZH: 奢华优雅 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Luxurious Elegance, {prompt}, extravagant, ornate, designer, opulent, picturesque, lavish + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/e796e84ed745150f0d4e28e0ac99b4cf.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Macro Photography + NAME_ZH: 微距摄影 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Macro Photography, {prompt}, close-up, macro 100mm, macro photography + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/92e8b84379828f38e3d01c7272f41b0b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Mandola Art + NAME_ZH: 曼陀罗艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Mandola art style, {prompt}, complex, circular design, mandola + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/dbf5ca944d9213c3181348666cf337ac.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Marker Drawing + NAME_ZH: 马克笔绘图 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Marker Drawing, {prompt}, bold marker lines, visibile paper texture, marker drawing + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photograph, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/c558745f7a4b77d7ca9a428d8874efe4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Medievalism + NAME_ZH: 中世纪主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Medievalism, {prompt}, inspired by The Middle Ages, medieval art, elaborate patterns and decoration, Medievalism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/26aa6244359a4fd87f6438a341057901.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Minimalism + NAME_ZH: 极简主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Minimalism, {prompt}, abstract, simple geometic shapes, hard edges, sleek contours, Minimalism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/dce92a90da6299339cf8e9ebc6596ea2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Baroque + NAME_ZH: 新巴洛克 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Neo-Baroque, {prompt}, ornate and elaborate, dynaimc, Neo-Baroque + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/9b6cd8751b18c65b259769b44cfac351.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Byzantine + NAME_ZH: 新拜占庭 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Neo-Byzantine, {prompt}, grand decorative religious style, Orthodox Christian inspired, Neo-Byzantine + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/99c67768869b546bf527ef0b1735c0d5.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Futurism + NAME_ZH: 新未来主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Neo-Futurism, {prompt}, high-tech, curves, spirals, flowing lines, idealistic future, Neo-Futurism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/bada1534f7a60187f584febcc92f40d1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Impressionism + NAME_ZH: 新印象主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Neo-Impressionism, {prompt}, tiny dabs of color, Pointillism, painterly, Neo-Impressionism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photograph, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/6bafeac67ce2679b64a86ee1023b53c9.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Rococo + NAME_ZH: 新洛可可 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Neo-Rococo, {prompt}, curved forms, naturalistic ornamentation, elaborate, decorative, gaudy, Neo-Rococo + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/9ab0ad2b88e03933ea479357ff1e4435.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neoclassicism + NAME_ZH: 新古典主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Neoclassicism, {prompt}, ancient Rome and Greece inspired, idealic, sober colors, Neoclassicism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/83a4e3a2ca577400b05a81b5b2b8650e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Op Art + NAME_ZH: 视觉艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Op Art, {prompt}, optical illusion, abstract, geometric pattern, impression of movement, Op Art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/5f11132803dff2de5213293b91d407d7.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Ornate and Intricate + NAME_ZH: 华丽复杂 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Ornate and Intricate, {prompt}, decorative, highly detailed, elaborate, ornate, intricate + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/24b895dca946c8765ad9fa38f720f671.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Pencil Sketch Drawing + NAME_ZH: 铅笔素描 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Pencil Sketch Drawing, {prompt}, black and white drawing, graphite drawing + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/a9056e1eac85e5e4fe96a93917d4cce4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Pop Art 2 + NAME_ZH: 流行艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Pop Art, {prompt}, vivid colors, flat color, 2D, strong lines, Pop Art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/83c4c06c70a48da6558ff970ece247b6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Rococo + NAME_ZH: 洛可可 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Rococo, {prompt}, flamboyant, pastel colors, curved lines, elaborate detail, Rococo + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/4850170f410e10bc833b7d00324dff18.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Silhouette Art + NAME_ZH: 剪影艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Silhouette Art, {prompt}, high contrast, well defined, Silhouette Art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/568777f447fc02510b618152726d5002.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Simple Vector Art + NAME_ZH: 简单矢量艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Simple Vector Art, {prompt}, 2D flat, simple shapes, minimalistic, professional graphic, flat color, high contrast, Simple Vector Art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, 3D, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/24d2ab1fd175bf4e9ef3a8327651dd4b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Sketchup + NAME_ZH: 草图大师 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Sketchup, {prompt}, CAD, professional design, Sketchup + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photo, photograph + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/337dca7ac49cf7820c85ede096ebde9c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Steampunk 2 + NAME_ZH: 蒸汽朋克 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Steampunk, {prompt}, retrofuturistic science fantasy, steam-powered tech, vintage industry, gears, neo-victorian, steampunk + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/07d7b27cd73f2d43684003563511c15b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Surrealism + NAME_ZH: 超现实主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Surrealism, {prompt}, expressive, dramatic, organic lines and forms, dreamlike and mysterious, Surrealism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/38bae70377b323d1a5f5756d7e04886d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Suprematism + NAME_ZH: 至上主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Suprematism, {prompt}, abstract, limited color palette, geometric forms, Suprematism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/c48fbd8cedee84d06b4d875d566f1bb8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Terragen + NAME_ZH: 地形生成 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Terragen, {prompt}, beautiful massive landscape, epic scenery, Terragen + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/8974cd8e0f38fb7aac117cf0983fc36d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Tranquil Relaxing Atmosphere + NAME_ZH: 宁静放松的氛围 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Tranquil Relaxing Atmosphere, {prompt}, calming style, soothing colors, peaceful, idealic, Tranquil Relaxing Atmosphere + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, oversaturated + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/69170d8443a67be4210af8d5558779c2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Sticker Designs + NAME_ZH: 贴纸设计 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Vector Art Stickers, {prompt}, professional vector design, sticker designs, Sticker Sheet + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/2d1e9867058db2c57f2fe47530de3243.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Vibrant Rim Light + NAME_ZH: 生动的边缘光 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Vibrant Rim Light, {prompt}, bright rim light, high contrast, bold edge light + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/bb08936ca184daba2b30b4a9efb308f2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Volumetric Lighting + NAME_ZH: 体积光照明 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Volumetric Lighting, {prompt}, light depth, dramatic atmospheric lighting, Volumetric Lighting + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/bbad7964a2ae70b66c72804273f11e74.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Watercolor 2 + NAME_ZH: 水彩 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Watercolor style painting, {prompt}, visible paper texture, colorwash, watercolor + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/8859d532ae5901cc8457d6118fb9b7da.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Whimsical and Playful + NAME_ZH: 异想天开和俏皮 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + PROMPT: Whimsical and Playful, {prompt}, imaginative, fantastical, bight colors, stylized, happy, Whimsical and Playful + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, drab, boring, moody + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/af2267f1942e870be957c37cd73d4359.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Enhance + NAME_ZH: 焦点增强 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD_XL1.0 + PROMPT: { + "prompt": null +} + + NEGATIVE_PROMPT: (worst quality, low quality, normal quality, lowres, low details, oversaturated, undersaturated, overexposed, underexposed, grayscale, bw, bad photo, bad photography, bad art:1.4), (watermark, signature, text font, username, error, logo, words, letters, digits, autograph, trademark, name:1.2), (blur, blurry, grainy), morbid, ugly, asymmetrical, mutated malformed, mutilated, poorly lit, bad shadow, draft, cropped, out of frame, cut off, censored, jpeg artifacts, out of focus, glitch, duplicate, (airbrushed, cartoon, anime, semi-realistic, cgi, render, blender, digital art, manga, amateur:1.3), (3D ,3D Game, 3D Game Scene, 3D Character:1.1), (bad hands, bad anatomy, bad body, bad face, bad teeth, bad arms, bad legs, deformities:1.3) + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/e501823a21bbda56592055c9613c1dbb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Sharp + NAME_ZH: 焦点锐化 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD_XL1.0 + PROMPT: cinematic still {prompt} . emotional, harmonious, vignette, 4k epic detailed, shot on kodak, 35mm photo, sharp focus, high budget, cinemascope, moody, epic, gorgeous, film grain, grainy + NEGATIVE_PROMPT: anime, cartoon, graphic, (blur, blurry, bokeh), text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/393fb7aab57992a1c3af7cbad01c1001.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Masterpiece + NAME_ZH: 焦点杰作 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD_XL1.0 + PROMPT: (masterpiece), (best quality), (ultra-detailed), {prompt}, illustration, disheveled hair, detailed eyes, perfect composition, moist skin, intricate details, earrings, by wlop + NEGATIVE_PROMPT: longbody, lowres, bad anatomy, bad hands, missing fingers, pubic hair,extra digit, fewer digits, cropped, worst quality, low quality + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/9e27c3d1475dacae0ee45cea783aaaf5.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Photograph + NAME_ZH: 焦点摄影 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD_XL1.0 + PROMPT: photograph {prompt}, 50mm . cinematic 4k epic detailed 4k epic detailed photograph shot on kodak detailed cinematic hbo dark moody, 35mm photo, grainy, vignette, vintage, Kodachrome, Lomography, stained, highly detailed, found footage + NEGATIVE_PROMPT: Brad Pitt, bokeh, depth of field, blurry, cropped, regular face, saturated, contrast, deformed iris, deformed pupils, semi-realistic, cgi, 3d, render, sketch, cartoon, drawing, anime, text, cropped, out of frame, worst quality, low quality, jpeg artifacts, ugly, duplicate, morbid, mutilated, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, dehydrated, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/8b2ea41ec15bf1a16d6a837d46dbc2ac.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Negative + NAME_ZH: 焦点底片 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD_XL1.0 + PROMPT: { + "prompt": null +} + + NEGATIVE_PROMPT: deformed, bad anatomy, disfigured, poorly drawn face, mutated, extra limb, ugly, poorly drawn hands, missing limb, floating limbs, disconnected limbs, disconnected head, malformed hands, long neck, mutated hands and fingers, bad hands, missing fingers, cropped, worst quality, low quality, mutation, poorly drawn, huge calf, bad hands, fused hand, missing hand, disappearing arms, disappearing thigh, disappearing calf, disappearing legs, missing fingers, fused fingers, abnormal eye proportion, Abnormal hands, abnormal legs, abnormal feet, abnormal fingers, drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly, anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/daaec2962291137532189b8a31012532.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Cinematic + NAME_ZH: 焦点电影 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD_XL1.0 + PROMPT: cinematic still {prompt} . emotional, harmonious, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy + NEGATIVE_PROMPT: anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/adc4d52aa5b0afca0593a475ddc9d055.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-cinematic-dynamic + NAME_ZH: MRE电影动态 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: epic cinematic shot of dynamic {prompt} in motion. main subject of high budget action movie. raw photo, motion blur. best quality, high resolution + NEGATIVE_PROMPT: static, still, motionless, sluggish. drawing, painting, illustration, rendered. low budget. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/bd2470068e09d9f1b7d0a690c879b3ce.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-spontaneous-picture + NAME_ZH: MRE自发图片 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: spontaneous picture of {prompt}, taken by talented amateur. best quality, high resolution. magical moment, natural look. simple but good looking + NEGATIVE_PROMPT: overthinked. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/19ad6082cee5516ce330641b515467ef.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-artistic-vision + NAME_ZH: MRE艺术视觉 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: powerful artistic vision of {prompt}. breathtaking masterpiece made by great artist. best quality, high resolution + NEGATIVE_PROMPT: insignificant, flawed, made by bad artist. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/95af94e50bcb91ae8fd2914a3bf13f1e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-dark-dream + NAME_ZH: MRE黑暗梦境 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: dark and unsettling dream showing {prompt}. best quality, high resolution. created by genius but depressed mad artist. grim beauty + NEGATIVE_PROMPT: naive, cheerful. comfortable, casual, boring, cliche. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/572c8c26cc20ac0ee66684e3c5ee4e8c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-gloomy-art + NAME_ZH: MRE忧郁艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: astonishing gloomy art made mainly of shadows and lighting, forming {prompt}. masterful usage of lighting, shadows and chiaroscuro. made by black-hearted artist, drawing from darkness. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/66cbdf819e930f7580bd66a41bde7dfe.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-bad-dream + NAME_ZH: MRE恶梦 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: picture from really bad dream about terrifying {prompt}, true horror. bone-chilling vision. mad world that shouldn't exist. best quality, high resolution + NEGATIVE_PROMPT: nice dream, pleasant experience. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/b92b2bbfc400db9204fe8249354132b4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-underground + NAME_ZH: MRE地下 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: uncanny caliginous vision of {prompt}, created by remarkable underground artist. best quality, high resolution. raw and brutal art, careless but impressive style. inspired by darkness and chaos + NEGATIVE_PROMPT: photography, mainstream, civilized. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/8d46eca558d791a1f2b41b0ed7bba4d2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-surreal-painting + NAME_ZH: MRE超现实绘画 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: surreal painting representing strange vision of {prompt}. harmonious madness, synergy with chance. unique artstyle, mindbending art, magical surrealism. best quality, high resolution + NEGATIVE_PROMPT: photography, illustration, drawing. realistic, possible. logical, sane. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/58858425832b10d233f7887af4a2022f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-dynamic-illustration + NAME_ZH: MRE动态插画 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: insanely dynamic illustration of {prompt}. best quality, high resolution. crazy artstyle, careless brushstrokes, emotional and fun + NEGATIVE_PROMPT: photography, realistic. static, still, slow, boring. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/8bf9861d4d3fadcdb98ceec88a941582.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-undead-art + NAME_ZH: MRE不死艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: long forgotten art created by undead artist illustrating {prompt}, tribute to the death and decay. miserable art of the damned. wretched and decaying world. best quality, high resolution + NEGATIVE_PROMPT: alive, playful, living. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/fada50979ca180006eba9a45a00f3675.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-elemental-art + NAME_ZH: MRE元素艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: art illustrating insane amounts of raging elemental energy turning into {prompt}, avatar of elements. magical surrealism, wizardry. best quality, high resolution + NEGATIVE_PROMPT: photography, realistic, real. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/5895d78cf58c1ca05178991f37cc48ff.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-space-art + NAME_ZH: MRE太空艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: winner of inter-galactic art contest illustrating {prompt}, symbol of the interstellar singularity. best quality, high resolution. artstyle previously unseen in the whole galaxy + NEGATIVE_PROMPT: created by human race, low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/e9815495587895a21d970728474c8be6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-ancient-illustration + NAME_ZH: MRE古代插画 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: sublime ancient illustration of {prompt}, predating human civilization. crude and simple, but also surprisingly beautiful artwork, made by genius primeval artist. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/151e07c17a89ebaf7688905ea0199862.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-brave-art + NAME_ZH: MRE勇敢艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: brave, shocking, and brutally true art showing {prompt}. inspired by courage and unlimited creativity. truth found in chaos. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/1a068f2728327d21ebb99285c2ce1370.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-heroic-fantasy + NAME_ZH: MRE英雄幻想 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: heroic fantasy painting of {prompt}, in the dangerous fantasy world. airbrush over oil on canvas. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/78d05472067e0b86c8270fa5476fcb8e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-dark-cyberpunk + NAME_ZH: MRE黑暗赛博朋克 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: dark cyberpunk illustration of brutal {prompt} in a world without hope, ruled by ruthless criminal corporations. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/a9f50e3162958fd783872d6955ad7d0b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-lyrical-geometry + NAME_ZH: MRE抒情几何 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: geometric and lyrical abstraction painting presenting {prompt}. oil on metal. best quality, high resolution + NEGATIVE_PROMPT: photography, realistic, drawing, rendered. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/dfabd41d3042ced804bc97ae35e3a7cb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-sumi-e-symbolic + NAME_ZH: MRE墨绘象征 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: big long brushstrokes of deep black sumi-e turning into symbolic painting of {prompt}. master level raw art. best quality, high resolution + NEGATIVE_PROMPT: photography, rendered. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/695b1ba687544eaeec9fb5f871917aeb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-sumi-e-detailed + NAME_ZH: MRE墨绘精细 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: highly detailed black sumi-e painting of {prompt}. in-depth study of perfection, created by a master. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/16eb95e180385b88794e368b28da1812.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-manga + NAME_ZH: MRE漫画 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: manga artwork presenting {prompt}. created by japanese manga artist. highly emotional. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/ebec631bf467937f82d05958ae59f9dc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-anime + NAME_ZH: MRE动漫 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: anime artwork illustrating {prompt}. created by japanese anime studio. highly emotional. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/a08149bc8e50f6bc65c0010d4cd416f8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-comic + NAME_ZH: MRE漫画书 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + PROMPT: breathtaking illustration from adult comic book presenting {prompt}. fabulous artwork. best quality, high resolution + NEGATIVE_PROMPT: deformed, ugly, low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/48c65cebf1fa4284d7b8feb619412e65.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-3d-model + NAME_ZH: SAI三维模型 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: professional 3d model {prompt} . octane render, highly detailed, volumetric, dramatic lighting + NEGATIVE_PROMPT: ugly, deformed, noisy, low poly, blurry, painting + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/c1a765ac089fdfb3c1d11b33c75d2afd.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-analog film + NAME_ZH: SAI模拟胶片 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: analog film photo {prompt} . faded film, desaturated, 35mm photo, grainy, vignette, vintage, Kodachrome, Lomography, stained, highly detailed, found footage + NEGATIVE_PROMPT: painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/3c46d19957efd7fb78f4ab2bdada5468.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-anime + NAME_ZH: SAI动漫 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: anime artwork {prompt} . anime style, key visual, vibrant, studio anime, highly detailed + NEGATIVE_PROMPT: photo, deformed, black and white, realism, disfigured, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/c030e72561eda96abcf738f1370d36ff.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-cinematic + NAME_ZH: SAI电影 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: cinematic film still {prompt} . shallow depth of field, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy + NEGATIVE_PROMPT: anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/d9161c0d5cbf2133b2bfc1021c0c5e2a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-comic book + NAME_ZH: SAI漫画书 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: comic {prompt} . graphic illustration, comic art, graphic novel art, vibrant, highly detailed + NEGATIVE_PROMPT: photograph, deformed, glitch, noisy, realistic, stock photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/6759ecb831037367e64c4b36d802be87.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-craft clay + NAME_ZH: SAI手工粘土 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: play-doh style {prompt} . sculpture, clay art, centered composition, Claymation + NEGATIVE_PROMPT: sloppy, messy, grainy, highly detailed, ultra textured, photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/8fc51113f725f27326c4398a7457cd6d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-digital art + NAME_ZH: SAI数字艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: concept art {prompt} . digital artwork, illustrative, painterly, matte painting, highly detailed + NEGATIVE_PROMPT: photo, photorealistic, realism, ugly + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/d29adb44458700c4a45ee6edaa04bfb6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-enhance + NAME_ZH: SAI增强 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: breathtaking {prompt} . award-winning, professional, highly detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, distorted, grainy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/2be0de541ff65f8da80ddc24a65c98d8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-fantasy art + NAME_ZH: SAI幻想艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: ethereal fantasy concept art of {prompt} . magnificent, celestial, ethereal, painterly, epic, majestic, magical, fantasy art, cover art, dreamy + NEGATIVE_PROMPT: photographic, realistic, realism, 35mm film, dslr, cropped, frame, text, deformed, glitch, noise, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, sloppy, duplicate, mutated, black and white + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/a6f8d92afcd5803dfb2ebecbc92091b6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-isometric + NAME_ZH: SAI等距 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: isometric style {prompt} . vibrant, beautiful, crisp, detailed, ultra detailed, intricate + NEGATIVE_PROMPT: deformed, mutated, ugly, disfigured, blur, blurry, noise, noisy, realistic, photographic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/d4e3fcbbfd7b1323bd89decf5d7b0006.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-line art + NAME_ZH: SAI线条艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: line art drawing {prompt} . professional, sleek, modern, minimalist, graphic, line art, vector graphics + NEGATIVE_PROMPT: anime, photorealistic, 35mm film, deformed, glitch, blurry, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, mutated, realism, realistic, impressionism, expressionism, oil, acrylic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/034a51b0dd34b018be8859bf45b4f7ed.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-lowpoly + NAME_ZH: SAI低多边形 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: low-poly style {prompt} . low-poly game art, polygon mesh, jagged, blocky, wireframe edges, centered composition + NEGATIVE_PROMPT: noisy, sloppy, messy, grainy, highly detailed, ultra textured, photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/76b9913e9fa5704b6d30adbde9e1f70f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-neonpunk + NAME_ZH: SAI霓虹朋克 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: neonpunk style {prompt} . cyberpunk, vaporwave, neon, vibes, vibrant, stunningly beautiful, crisp, detailed, sleek, ultramodern, magenta highlights, dark purple shadows, high contrast, cinematic, ultra detailed, intricate, professional + NEGATIVE_PROMPT: painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/7e9ed25bb34008beb5f417df63c4b2fe.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-origami + NAME_ZH: SAI折纸 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: origami style {prompt} . paper art, pleated paper, folded, origami art, pleats, cut and fold, centered composition + NEGATIVE_PROMPT: noisy, sloppy, messy, grainy, highly detailed, ultra textured, photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/924f46a8f276011a0953d7988e90ee25.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-photographic + NAME_ZH: SAI摄影 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: cinematic photo {prompt} . 35mm photograph, film, bokeh, professional, 4k, highly detailed + NEGATIVE_PROMPT: drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/d6a2d8f3d37cc21c20c5dfc13d000b67.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-pixel art + NAME_ZH: SAI像素艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: pixel-art {prompt} . low-res, blocky, pixel art style, 8-bit graphics + NEGATIVE_PROMPT: sloppy, messy, blurry, noisy, highly detailed, ultra textured, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/a5ab89c0960be8c1216e65c98d92ae4a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-texture + NAME_ZH: SAI质地 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + PROMPT: texture {prompt} top down close-up + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/ebfeab574283fff2ac096e348a585e6d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-advertising + NAME_ZH: 广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: advertising poster style {prompt} . Professional, modern, product-focused, commercial, eye-catching, highly detailed + NEGATIVE_PROMPT: noisy, blurry, amateurish, sloppy, unattractive + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/1aa26a16126e2756bf4bf3fda29baa12.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-automotive + NAME_ZH: 汽车广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: automotive advertisement style {prompt} . sleek, dynamic, professional, commercial, vehicle-focused, high-resolution, highly detailed + NEGATIVE_PROMPT: noisy, blurry, unattractive, sloppy, unprofessional + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/ddc833b36ca23c85a4f6e7bf0088d081.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-corporate + NAME_ZH: 企业广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: corporate branding style {prompt} . professional, clean, modern, sleek, minimalist, business-oriented, highly detailed + NEGATIVE_PROMPT: noisy, blurry, grungy, sloppy, cluttered, disorganized + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/df97fa45c7842296c138aca4057db272.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-fashion editorial + NAME_ZH: 时尚编辑 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: fashion editorial style {prompt} . high fashion, trendy, stylish, editorial, magazine style, professional, highly detailed + NEGATIVE_PROMPT: outdated, blurry, noisy, unattractive, sloppy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/89259be723479cd0b81546b715bea04d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-food photography + NAME_ZH: 食品摄影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: food photography style {prompt} . appetizing, professional, culinary, high-resolution, commercial, highly detailed + NEGATIVE_PROMPT: unappetizing, sloppy, unprofessional, noisy, blurry + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/33acc98f8615940c8cebbac8ce5297b2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-gourmet food photography + NAME_ZH: 美食摄影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: gourmet food photo of {prompt} . soft natural lighting, macro details, vibrant colors, fresh ingredients, glistening textures, bokeh background, styled plating, wooden tabletop, garnished, tantalizing, editorial quality + NEGATIVE_PROMPT: cartoon, anime, sketch, grayscale, dull, overexposed, cluttered, messy plate, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/897bbd3f1d232de122796266f3845b50.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-luxury + NAME_ZH: 奢华广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: luxury product style {prompt} . elegant, sophisticated, high-end, luxurious, professional, highly detailed + NEGATIVE_PROMPT: cheap, noisy, blurry, unattractive, amateurish + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/5b33ecc84dc5ff285a0f2e69f43162cb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-real estate + NAME_ZH: 房地产广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: real estate photography style {prompt} . professional, inviting, well-lit, high-resolution, property-focused, commercial, highly detailed + NEGATIVE_PROMPT: dark, blurry, unappealing, noisy, unprofessional + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/1b99b7bcd0476144d80d066e747d8dfc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-retail + NAME_ZH: 零售广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: retail packaging style {prompt} . vibrant, enticing, commercial, product-focused, eye-catching, professional, highly detailed + NEGATIVE_PROMPT: noisy, blurry, amateurish, sloppy, unattractive + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/0029e46ef36380dde2084257108f8a6f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-abstract + NAME_ZH: 抽象艺术风格 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: abstract style {prompt} . non-representational, colors and shapes, expression of feelings, imaginative, highly detailed + NEGATIVE_PROMPT: realistic, photographic, figurative, concrete + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/8c401cb0a6ea288230222c4985e78667.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-abstract expressionism + NAME_ZH: 抽象表现主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: abstract expressionist painting {prompt} . energetic brushwork, bold colors, abstract forms, expressive, emotional + NEGATIVE_PROMPT: realistic, photorealistic, low contrast, plain, simple, monochrome + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/9df6635149c576b65d911c2e4cc6a86b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-art deco + NAME_ZH: 艺术装饰风格 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: art deco style {prompt} . geometric shapes, bold colors, luxurious, elegant, decorative, symmetrical, ornate, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, modernist, minimalist + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/82fff8a25de8075777caf14cb3eb5650.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-art nouveau + NAME_ZH: 新艺术风格 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: art nouveau style {prompt} . elegant, decorative, curvilinear forms, nature-inspired, ornate, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, modernist, minimalist + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/84075c5c0cb4b7a2541c6fbca9835cfd.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-constructivist + NAME_ZH: 构成主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: constructivist style {prompt} . geometric shapes, bold colors, dynamic composition, propaganda art style + NEGATIVE_PROMPT: realistic, photorealistic, low contrast, plain, simple, abstract expressionism + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/2a634ad0c89ecefbbea4ce5bcab3d5e5.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-cubist + NAME_ZH: 立体主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: cubist artwork {prompt} . geometric shapes, abstract, innovative, revolutionary + NEGATIVE_PROMPT: anime, photorealistic, 35mm film, deformed, glitch, low contrast, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/2a3d797008c08e12b485d61624741ea6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-expressionist + NAME_ZH: 表现主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: expressionist {prompt} . raw, emotional, dynamic, distortion for emotional effect, vibrant, use of unusual colors, detailed + NEGATIVE_PROMPT: realism, symmetry, quiet, calm, photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/83914655659001716a1acede295289d0.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-graffiti + NAME_ZH: 涂鸦 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: graffiti style {prompt} . street art, vibrant, urban, detailed, tag, mural + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/f72a23c7623eb480737eb73c08bf8423.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-hyperrealism + NAME_ZH: 超现实主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: hyperrealistic art {prompt} . extremely high-resolution details, photographic, realism pushed to extreme, fine texture, incredibly lifelike + NEGATIVE_PROMPT: simplified, abstract, unrealistic, impressionistic, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/db378d5a64a8e7ad1e29a4389bda5d1c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-impressionist + NAME_ZH: 印象主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: impressionist painting {prompt} . loose brushwork, vibrant color, light and shadow play, captures feeling over form + NEGATIVE_PROMPT: anime, photorealistic, 35mm film, deformed, glitch, low contrast, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/53b151aec4d5685dfc24511b6705b90e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-pointillism + NAME_ZH: 点彩主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: pointillism style {prompt} . composed entirely of small, distinct dots of color, vibrant, highly detailed + NEGATIVE_PROMPT: line drawing, smooth shading, large color fields, simplistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/23b137a409ee8a8c6ee160c1ddf0659f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-pop art + NAME_ZH: 波普艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: pop Art style {prompt} . bright colors, bold outlines, popular culture themes, ironic or kitsch + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, minimalist + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/bd4faf0e2b7dbc2d0eb21f3ebee97d3d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-psychedelic + NAME_ZH: 迷幻艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: psychedelic style {prompt} . vibrant colors, swirling patterns, abstract forms, surreal, trippy + NEGATIVE_PROMPT: monochrome, black and white, low contrast, realistic, photorealistic, plain, simple + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/7dc0131817f4c31517581dd4a811067b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-renaissance + NAME_ZH: 文艺复兴 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: renaissance style {prompt} . realistic, perspective, light and shadow, religious or mythological themes, highly detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, modernist, minimalist, abstract + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/69796484f61dc2e94d5853f5bbe27c05.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-steampunk + NAME_ZH: 蒸汽朋克 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: steampunk style {prompt} . antique, mechanical, brass and copper tones, gears, intricate, detailed + NEGATIVE_PROMPT: deformed, glitch, noisy, low contrast, anime, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/985005e28858b03c9500a6eb5bd9e201.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-surrealist + NAME_ZH: 超现实主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: surrealist art {prompt} . dreamlike, mysterious, provocative, symbolic, intricate, detailed + NEGATIVE_PROMPT: anime, photorealistic, realistic, deformed, glitch, noisy, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/892d19ec3c429b7148562796df0024db.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-typography + NAME_ZH: 排版艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: typographic art {prompt} . stylized, intricate, detailed, artistic, text-based + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/9adafe1bb169e1ee3f78ba2c1b1cf8d3.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-watercolor + NAME_ZH: 水彩艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: watercolor painting {prompt} . vibrant, beautiful, painterly, detailed, textural, artistic + NEGATIVE_PROMPT: anime, photorealistic, 35mm film, deformed, glitch, low contrast, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/29ca23d7a0397e9beaa72e3b63d17551.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-biomechanical + NAME_ZH: 未来生物力学 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: biomechanical style {prompt} . blend of organic and mechanical elements, futuristic, cybernetic, detailed, intricate + NEGATIVE_PROMPT: natural, rustic, primitive, organic, simplistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/5987795487a3fa74469499ae53963d5d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-biomechanical cyberpunk + NAME_ZH: 未来生物力学赛博朋克 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: biomechanical cyberpunk {prompt} . cybernetics, human-machine fusion, dystopian, organic meets artificial, dark, intricate, highly detailed + NEGATIVE_PROMPT: natural, colorful, deformed, sketch, low contrast, watercolor + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/75b56d7cff9b3f011248b3092ae3b8d2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-cybernetic + NAME_ZH: 未来赛博 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: cybernetic style {prompt} . futuristic, technological, cybernetic enhancements, robotics, artificial intelligence themes + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, historical, medieval + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/47df6db04290f01aeee7381aaf12ec07.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-cybernetic robot + NAME_ZH: 未来机器人 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: cybernetic robot {prompt} . android, AI, machine, metal, wires, tech, futuristic, highly detailed + NEGATIVE_PROMPT: organic, natural, human, sketch, watercolor, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/6f18121b4ba22c8ba7834f404501fa4c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-cyberpunk cityscape + NAME_ZH: 未来赛博朋克城市景观 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: cyberpunk cityscape {prompt} . neon lights, dark alleys, skyscrapers, futuristic, vibrant colors, high contrast, highly detailed + NEGATIVE_PROMPT: natural, rural, deformed, low contrast, black and white, sketch, watercolor + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/5e4107dace2c9dd0217a9d1b18ae28f6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-futuristic + NAME_ZH: 未来主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: futuristic style {prompt} . sleek, modern, ultramodern, high tech, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, vintage, antique + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/8a61c0853ee4079bae96ad502a6ae840.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-retro cyberpunk + NAME_ZH: 未来复古赛博朋克 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: retro cyberpunk {prompt} . 80's inspired, synthwave, neon, vibrant, detailed, retro futurism + NEGATIVE_PROMPT: modern, desaturated, black and white, realism, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/460957bf9a07a58ddec08bf22d5b3698.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-retro futurism + NAME_ZH: 未来复古主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: retro-futuristic {prompt} . vintage sci-fi, 50s and 60s style, atomic age, vibrant, highly detailed + NEGATIVE_PROMPT: contemporary, realistic, rustic, primitive + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/0434a7b23a0f936db615d7a9b8e805f1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-sci-fi + NAME_ZH: 科幻未来主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: sci-fi style {prompt} . futuristic, technological, alien worlds, space themes, advanced civilizations + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, historical, medieval + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/7c3bde651f426273758b68a2805d0c8a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-vaporwave + NAME_ZH: 未来波 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: vaporwave style {prompt} . retro aesthetic, cyberpunk, vibrant, neon colors, vintage 80s and 90s style, highly detailed + NEGATIVE_PROMPT: monochrome, muted colors, realism, rustic, minimalist, dark + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/1ebb0bf67ee3ef76288b4c0a2a65d557.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-bubble bobble + NAME_ZH: 游戏-泡泡龙 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: Bubble Bobble style {prompt} . 8-bit, cute, pixelated, fantasy, vibrant, reminiscent of Bubble Bobble game + NEGATIVE_PROMPT: realistic, modern, photorealistic, violent, horror + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/19257352df33228555cb350963d9432a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-cyberpunk game + NAME_ZH: 赛博朋克游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: cyberpunk game style {prompt} . neon, dystopian, futuristic, digital, vibrant, detailed, high contrast, reminiscent of cyberpunk genre video games + NEGATIVE_PROMPT: historical, natural, rustic, low detailed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/6165ef47bc859e3dd0e3399ba2264c2b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-fighting game + NAME_ZH: 格斗游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: fighting game style {prompt} . dynamic, vibrant, action-packed, detailed character design, reminiscent of fighting video games + NEGATIVE_PROMPT: peaceful, calm, minimalist, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/aebda69ec1097dc61966995956ae34cc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-gta + NAME_ZH: 侠盗猎车手游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: GTA-style artwork {prompt} . satirical, exaggerated, pop art style, vibrant colors, iconic characters, action-packed + NEGATIVE_PROMPT: realistic, black and white, low contrast, impressionist, cubist, noisy, blurry, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/edff7ba5fc983468e79e64beb838b829.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-mario + NAME_ZH: 马里奥游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: Super Mario style {prompt} . vibrant, cute, cartoony, fantasy, playful, reminiscent of Super Mario series + NEGATIVE_PROMPT: realistic, modern, horror, dystopian, violent + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/2a229f623ce89160d1f67620599dfc7c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-minecraft + NAME_ZH: 我的世界游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: Minecraft style {prompt} . blocky, pixelated, vibrant colors, recognizable characters and objects, game assets + NEGATIVE_PROMPT: smooth, realistic, detailed, photorealistic, noise, blurry, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/83e77332a9f234fd8c9cddd29e2ec3c7.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-pokemon + NAME_ZH: 宝可梦游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: Pokémon style {prompt} . vibrant, cute, anime, fantasy, reminiscent of Pokémon series + NEGATIVE_PROMPT: realistic, modern, horror, dystopian, violent + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/9bfe2805e6578875a8dfe2a0ea96c281.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-retro arcade + NAME_ZH: 复古街机 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: retro arcade style {prompt} . 8-bit, pixelated, vibrant, classic video game, old school gaming, reminiscent of 80s and 90s arcade games + NEGATIVE_PROMPT: modern, ultra-high resolution, photorealistic, 3D + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/76885e0b110f1fdf3eaee52fbaf27abf.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-retro game + NAME_ZH: 复古游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: retro game art {prompt} . 16-bit, vibrant colors, pixelated, nostalgic, charming, fun + NEGATIVE_PROMPT: realistic, photorealistic, 35mm film, deformed, glitch, low contrast, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/61fbae41c50f56e24dcf20fe3612d456.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-rpg fantasy game + NAME_ZH: 角色扮演幻想游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: role-playing game (RPG) style fantasy {prompt} . detailed, vibrant, immersive, reminiscent of high fantasy RPG games + NEGATIVE_PROMPT: sci-fi, modern, urban, futuristic, low detailed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/34797baf58e32b4e1a37753fe9dcff5c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-strategy game + NAME_ZH: 策略游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: strategy game style {prompt} . overhead view, detailed map, units, reminiscent of real-time strategy video games + NEGATIVE_PROMPT: first-person view, modern, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/0d276527d22510a1b5f8f74eac2790df.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-streetfighter + NAME_ZH: 街头霸王游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: Street Fighter style {prompt} . vibrant, dynamic, arcade, 2D fighting game, highly detailed, reminiscent of Street Fighter series + NEGATIVE_PROMPT: 3D, realistic, modern, photorealistic, turn-based strategy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/f5927fc2b8d4a8212242bd97adcbdfa1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-zelda + NAME_ZH: 塞尔达传说游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: Legend of Zelda style {prompt} . vibrant, fantasy, detailed, epic, heroic, reminiscent of The Legend of Zelda series + NEGATIVE_PROMPT: sci-fi, modern, realistic, horror + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/4f9eadddbc196268258089b8cc4e5c5c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-architectural + NAME_ZH: 建筑 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: architectural style {prompt} . clean lines, geometric shapes, minimalist, modern, architectural drawing, highly detailed + NEGATIVE_PROMPT: curved lines, ornate, baroque, abstract, grunge + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/488545e9fc9417d62961f42d578547d2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-disco + NAME_ZH: 迪斯科 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: disco-themed {prompt} . vibrant, groovy, retro 70s style, shiny disco balls, neon lights, dance floor, highly detailed + NEGATIVE_PROMPT: minimalist, rustic, monochrome, contemporary, simplistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/784b0ac35e0c0fdb2df21a95d5ca1c55.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-dreamscape + NAME_ZH: 梦境 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: dreamscape {prompt} . surreal, ethereal, dreamy, mysterious, fantasy, highly detailed + NEGATIVE_PROMPT: realistic, concrete, ordinary, mundane + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/2bf77804b5bf352c4e97475b1e8eb29e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-dystopian + NAME_ZH: 反乌托邦 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: dystopian style {prompt} . bleak, post-apocalyptic, somber, dramatic, highly detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, cheerful, optimistic, vibrant, colorful + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/065db0385e126192cbd27e22ca4f154c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-fairy tale + NAME_ZH: 童话故事 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: fairy tale {prompt} . magical, fantastical, enchanting, storybook style, highly detailed + NEGATIVE_PROMPT: realistic, modern, ordinary, mundane + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/578dfe65d9f03e83c95820d4c45cd396.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-gothic + NAME_ZH: 哥特 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: gothic style {prompt} . dark, mysterious, haunting, dramatic, ornate, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, cheerful, optimistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/332a1f8cd655b724cb48bc5c91b764fc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-grunge + NAME_ZH: 垃圾摇滚 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: grunge style {prompt} . textured, distressed, vintage, edgy, punk rock vibe, dirty, noisy + NEGATIVE_PROMPT: smooth, clean, minimalist, sleek, modern, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/0ccb4c03c6d983b9f6d05ba383f9d690.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-horror + NAME_ZH: 恐怖 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: horror-themed {prompt} . eerie, unsettling, dark, spooky, suspenseful, grim, highly detailed + NEGATIVE_PROMPT: cheerful, bright, vibrant, light-hearted, cute + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/fdca4780d099a39dc50e4553622fba72.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-kawaii + NAME_ZH: 卡哇伊 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: kawaii style {prompt} . cute, adorable, brightly colored, cheerful, anime influence, highly detailed + NEGATIVE_PROMPT: dark, scary, realistic, monochrome, abstract + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/99dab4185e7337189d8959878bfa308b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-lovecraftian + NAME_ZH: 克苏鲁神话 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: lovecraftian horror {prompt} . eldritch, cosmic horror, unknown, mysterious, surreal, highly detailed + NEGATIVE_PROMPT: light-hearted, mundane, familiar, simplistic, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/b7c9d084ed62c1c2e1ea080ad95af61e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-macabre + NAME_ZH: 恐怖的 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: macabre style {prompt} . dark, gothic, grim, haunting, highly detailed + NEGATIVE_PROMPT: bright, cheerful, light-hearted, cartoonish, cute + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/fd7cf2315b27b0434b909020414e1173.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-manga + NAME_ZH: 漫画 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: manga style {prompt} . vibrant, high-energy, detailed, iconic, Japanese comic style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, Western comic style + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/531aac90b321d39221ba7cf70a97b232.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-metropolis + NAME_ZH: 大都市 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: metropolis-themed {prompt} . urban, cityscape, skyscrapers, modern, futuristic, highly detailed + NEGATIVE_PROMPT: rural, natural, rustic, historical, simple + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/eaad79fe3d7160cec6e0656fc3b02d3c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-minimalist + NAME_ZH: 极简主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: minimalist style {prompt} . simple, clean, uncluttered, modern, elegant + NEGATIVE_PROMPT: ornate, complicated, highly detailed, cluttered, disordered, messy, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/e85dd1ccc7f22bdac054d74ba58521b2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-monochrome + NAME_ZH: 单色 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: monochrome {prompt} . black and white, contrast, tone, texture, detailed + NEGATIVE_PROMPT: colorful, vibrant, noisy, blurry, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/cc793ada6b47561f4b63aa66dcd282ac.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-nautical + NAME_ZH: 航海 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: nautical-themed {prompt} . sea, ocean, ships, maritime, beach, marine life, highly detailed + NEGATIVE_PROMPT: landlocked, desert, mountains, urban, rustic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/3d9f6528180670804a2c5e85c7665c42.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-space + NAME_ZH: 太空 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: space-themed {prompt} . cosmic, celestial, stars, galaxies, nebulas, planets, science fiction, highly detailed + NEGATIVE_PROMPT: earthly, mundane, ground-based, realism + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/6f5742d23b43fc99cc01c8b68518df7c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-stained glass + NAME_ZH: 彩色玻璃 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: stained glass style {prompt} . vibrant, beautiful, translucent, intricate, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/ab0512ced9ed572075c49ad4f9f9a45d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-techwear fashion + NAME_ZH: 科技服饰 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: techwear fashion {prompt} . futuristic, cyberpunk, urban, tactical, sleek, dark, highly detailed + NEGATIVE_PROMPT: vintage, rural, colorful, low contrast, realism, sketch, watercolor + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/652a6bdb1b36860041222a458c7915d0.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-tribal + NAME_ZH: 部落 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: tribal style {prompt} . indigenous, ethnic, traditional patterns, bold, natural colors, highly detailed + NEGATIVE_PROMPT: modern, futuristic, minimalist, pastel + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/1ecdaf153ece5e16250b87020b7a209b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-zentangle + NAME_ZH: 禅绕画 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: zentangle {prompt} . intricate, abstract, monochrome, patterns, meditative, highly detailed + NEGATIVE_PROMPT: colorful, representative, simplistic, large fields of color + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/80f3488cdb69f0ff13d83a4feac4499d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-collage + NAME_ZH: 纸艺拼贴 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: collage style {prompt} . mixed media, layered, textural, detailed, artistic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/c9bbdaba28358faf1a8c1df44b3de950.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-flat papercut + NAME_ZH: 平面剪纸 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: flat papercut style {prompt} . silhouette, clean cuts, paper, sharp edges, minimalist, color block + NEGATIVE_PROMPT: 3D, high detail, noise, grainy, blurry, painting, drawing, photo, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/1bffcd9a4086b29c367b8301f26eed3b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-kirigami + NAME_ZH: 剪纸 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: kirigami representation of {prompt} . 3D, paper folding, paper cutting, Japanese, intricate, symmetrical, precision, clean lines + NEGATIVE_PROMPT: painting, drawing, 2D, noisy, blurry, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/2e5f95977b97b2a6248924e118a23076.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-paper mache + NAME_ZH: 纸浆塑型 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: paper mache representation of {prompt} . 3D, sculptural, textured, handmade, vibrant, fun + NEGATIVE_PROMPT: 2D, flat, photo, sketch, digital art, deformed, noisy, blurry + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/68441f668fcf7a51db5fc9b9d4d45ce7.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-paper quilling + NAME_ZH: 纸卷艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: paper quilling art of {prompt} . intricate, delicate, curling, rolling, shaping, coiling, loops, 3D, dimensional, ornamental + NEGATIVE_PROMPT: photo, painting, drawing, 2D, flat, deformed, noisy, blurry + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/8c0504eb14341b66796612c46bb3748b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-papercut collage + NAME_ZH: 剪纸拼贴 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: papercut collage of {prompt} . mixed media, textured paper, overlapping, asymmetrical, abstract, vibrant + NEGATIVE_PROMPT: photo, 3D, realistic, drawing, painting, high detail, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/217e7c8b905b63c63c94bd6ff8fe3477.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-papercut shadow box + NAME_ZH: 剪纸影箱 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: 3D papercut shadow box of {prompt} . layered, dimensional, depth, silhouette, shadow, papercut, handmade, high contrast + NEGATIVE_PROMPT: painting, drawing, photo, 2D, flat, high detail, blurry, noisy, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/2af0d61de1b17a5a5257f512549f9616.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-stacked papercut + NAME_ZH: 堆叠剪纸 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: stacked papercut art of {prompt} . 3D, layered, dimensional, depth, precision cut, stacked layers, papercut, high contrast + NEGATIVE_PROMPT: 2D, flat, noisy, blurry, painting, drawing, photo, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/62618e32e90539827e0eb279a6ea170a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-thick layered papercut + NAME_ZH: 厚层剪纸 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: thick layered papercut art of {prompt} . deep 3D, volumetric, dimensional, depth, thick paper, high stack, heavy texture, tangible layers + NEGATIVE_PROMPT: 2D, flat, thin paper, low stack, smooth texture, painting, drawing, photo, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/17008c40a6be8d41d3921ee88bac27ad.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-alien + NAME_ZH: 异形 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: alien-themed {prompt} . extraterrestrial, cosmic, otherworldly, mysterious, sci-fi, highly detailed + NEGATIVE_PROMPT: earthly, mundane, common, realistic, simple + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/eae6043dee2b2d94cd9a22cb044db8b3.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-film noir + NAME_ZH: 黑色电影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: film noir style {prompt} . monochrome, high contrast, dramatic shadows, 1940s style, mysterious, cinematic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, vibrant, colorful + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/0b3629be5ebb7cda463877a1993a0298.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-glamour + NAME_ZH: 魅力 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: glamorous photo {prompt} . high fashion, luxurious, extravagant, stylish, sensual, opulent, elegance, stunning beauty, professional, high contrast, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, distorted, grainy, sketch, low contrast, dull, plain, modest + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/f85dc6aa5d7f7d6d3663f2270e276796.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-hdr + NAME_ZH: 高动态范围 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: HDR photo of {prompt} . High dynamic range, vivid, rich details, clear shadows and highlights, realistic, intense, enhanced contrast, highly detailed + NEGATIVE_PROMPT: flat, low contrast, oversaturated, underexposed, overexposed, blurred, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/269a98b284ae1345b0e5ac1f85c33179.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-iphone photographic + NAME_ZH: iPhone摄影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: iphone photo {prompt} . large depth of field, deep depth of field, highly detailed + NEGATIVE_PROMPT: drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly, shallow depth of field, bokeh + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/48c556a6b3c3a533847b80b031cd4962.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-long exposure + NAME_ZH: 长曝光 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: long exposure photo of {prompt} . Blurred motion, streaks of light, surreal, dreamy, ghosting effect, highly detailed + NEGATIVE_PROMPT: static, noisy, deformed, shaky, abrupt, flat, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/fda88c3fc43ea8cc04ce9b5c0261627f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-neon noir + NAME_ZH: 霓虹黑色 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: neon noir {prompt} . cyberpunk, dark, rainy streets, neon signs, high contrast, low light, vibrant, highly detailed + NEGATIVE_PROMPT: bright, sunny, daytime, low contrast, black and white, sketch, watercolor + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/8a5b71434592771e064af4b9017b59d6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-silhouette + NAME_ZH: 剪影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: silhouette style {prompt} . high contrast, minimalistic, black and white, stark, dramatic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, color, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/1892a37e66d33cdd9b713aaab6b8c597.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-tilt-shift + NAME_ZH: 倾斜移位 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD_XL1.0 + PROMPT: tilt-shift photo of {prompt} . selective focus, miniature effect, blurred background, highly detailed, vibrant, perspective control + NEGATIVE_PROMPT: blurry, noisy, deformed, flat, low contrast, unrealistic, oversaturated, underexposed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/d058a157de848a5c03d9a3e1e0e560a2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: cinematic-diva + NAME_ZH: 电影歌星画风 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: UHD, 8K, ultra detailed, a cinematic photograph of {prompt}, beautiful lighting, great composition + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, NSFW + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/967b1852ea26dcf41360fc5542a0df6b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Abstract Expressionism + NAME_ZH: 抽象表现主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Abstract Expressionism Art, {prompt}, High contrast, minimalistic, colorful, stark, dramatic, expressionism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/11667c7a085b53a6ffbb76b83788f8b5.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Academia + NAME_ZH: 学院风 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Academia, {prompt}, preppy Ivy League style, stark, dramatic, chic boarding school, academia + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, grunge, sloppy, unkempt + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/c95197ef78312e2bbd45883bfbfa095a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Action Figure + NAME_ZH: 动作人偶 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Action Figure, {prompt}, plastic collectable action figure, collectable toy action figure + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/24ac67fe21833fc1300fba09d5de6090.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Adorable 3D Character + NAME_ZH: 可爱的3D角色 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Adorable 3D Character, {prompt}, 3D render, adorable character, 3D art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, grunge, sloppy, unkempt, photograph, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/31a0ffbfc93b5b336a3bedc0a9985a02.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Adorable Kawaii + NAME_ZH: 可爱卡哇伊风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Adorable Kawaii, {prompt}, pretty, cute, adorable, kawaii + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, gothic, dark, moody, monochromatic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/82624c429d504c8290d4c9147be64029.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Art Deco + NAME_ZH: 艺术装饰风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Art Deco, {prompt}, sleek, geometric forms, art deco style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/c60ef3e7ada8774c92bb6e73c570f819.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Art Nouveau + NAME_ZH: 新艺术风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Art Nouveau, beautiful art, {prompt}, sleek, organic forms, long, sinuous, art nouveau style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, industrial, mechanical + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/153d83e71fbf145d0aa5c41ecab0a505.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Astral Aura + NAME_ZH: 星体光环 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Astral Aura, {prompt}, astral, colorful aura, vibrant energy + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/e093c9d0f81037002e88f2a6c3f38a55.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Avant-garde + NAME_ZH: 先锋派 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Avant-garde, {prompt}, unusual, experimental, avant-garde art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/9921d1944893466edfc6a060faf4070e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Baroque + NAME_ZH: 巴洛克风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Baroque, {prompt}, dramatic, exuberant, grandeur, baroque art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/d8279be4bb34e5cb00a95919412154a4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Bauhaus-Style Poster + NAME_ZH: 包豪斯风格海报 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Bauhaus-Style Poster, {prompt}, simple geometric shapes, clean lines, primary colors, Bauhaus-Style Poster + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/4bd18b32c23e13b9e4fc7f65a1916eab.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Blueprint Schematic Drawing + NAME_ZH: 蓝图原理图绘制 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Blueprint Schematic Drawing, {prompt}, technical drawing, blueprint, schematic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/62392c3715267f7162a37a8ff1caa3a1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Caricature + NAME_ZH: 漫画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Caricature, {prompt}, exaggerated, comical, caricature + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/894f40ed44b37c3372e6a22b8ae577a4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Cel Shaded Art + NAME_ZH: 单色阴影艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Cel Shaded Art, {prompt}, 2D, flat color, toon shading, cel shaded style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/71c2e8a2cd1031b2bfae1640f7b72c88.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Character Design Sheet + NAME_ZH: 角色设计图 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Character Design Sheet, {prompt}, character reference sheet, character turn around + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/eacf2134aa51d4b4a6f2f35cc170f315.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Classicism Art + NAME_ZH: 古典主义艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Classicism Art, {prompt}, inspired by Roman and Greek culture, clarity, harmonious, classicism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/10025b4f3a09e6134086e3cdec4ef2c8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Color Field Painting + NAME_ZH: 色域绘画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Color Field Painting, {prompt}, abstract, simple, geometic, color field painting style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/80e5b4075c572c04cbb4e48c37b8366b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Colored Pencil Art + NAME_ZH: 彩色铅笔艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Colored Pencil Art, {prompt}, colored pencil strokes, light color, visible paper texture, colored pencil art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/9ae235d7f1a7c2a4edab52a5e9f9cbae.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Conceptual Art + NAME_ZH: 概念艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Conceptual Art, {prompt}, concept art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/cf2e6781997c6842a16155fdff911ef8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Constructivism + NAME_ZH: 结构主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Constructivism Art, {prompt}, minimalistic, geometric forms, constructivism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/d07feccabcadfd3310464bedba858bd1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Cubism + NAME_ZH: 立体主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Cubism Art, {prompt}, flat geometric forms, cubism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/aa8313f6c3cb9cafb9a7ec07db78df1c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dadaism + NAME_ZH: 达达主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Dadaism Art, {prompt}, satirical, nonsensical, dadaism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/db27030369cb3ccb042b8aea6bf635e2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dark Fantasy + NAME_ZH: 黑暗幻想 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Dark Fantasy Art, {prompt}, dark, moody, dark fantasy style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, bright, sunny + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/c88b6e641c707afc0c8d278ba7e1ac19.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dark Moody Atmosphere + NAME_ZH: 暗色忧郁氛围 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Dark Moody Atmosphere, {prompt}, dramatic, mysterious, dark moody atmosphere + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, vibrant, colorful, bright + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/3da915da2f5cedaf243e57e08163f35b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: DMT Art Style + NAME_ZH: DMT艺术风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: DMT Art Style, {prompt}, bright colors, surreal visuals, swirling patterns, DMT art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/d4a823d2bfa912ca4bb56d96f722f08f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Doodle Art + NAME_ZH: 涂鸦艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Doodle Art Style, {prompt}, drawing, freeform, swirling patterns, doodle art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/8e1e21745c149b9634d3ce96fc7d505f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Double Exposure + NAME_ZH: 双重曝光 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Double Exposure Style, {prompt}, double image ghost effect, image combination, double exposure style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/efd7aea4af1c4ede99fdfac17350e264.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dripping Paint Splatter Art + NAME_ZH: 滴漆溅画艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Dripping Paint Splatter Art, {prompt}, dramatic, paint drips, splatters, dripping paint + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/69fd81f5983107acc3d334af62915851.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Expressionism + NAME_ZH: 表现主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Expressionism Art Style, {prompt}, movement, contrast, emotional, exaggerated forms, expressionism art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/3dfa862bd1c80cec237e4a5717cea2bd.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Faded Polaroid Photo + NAME_ZH: 褪色的宝丽来照片 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Faded Polaroid Photo, {prompt}, analog, old faded photo, old polaroid + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, vibrant, colorful + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/f152edb4b3ca6248758b48115258ddfa.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fauvism + NAME_ZH: 野兽派 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Fauvism Art, {prompt}, painterly, bold colors, textured brushwork, fauvism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/0506b350cadcf8fca42da764cd6fd5bf.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Flat 2D Art + NAME_ZH: 扁平2D艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Flat 2D Art, {prompt}, simple flat color, 2-dimensional, Flat 2D Art Style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, 3D, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/940cfd34155634cf051e1b2942cca426.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fortnite Art Style + NAME_ZH: 堡垒之夜艺术风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Fortnite Art Style, {prompt}, 3D cartoon, colorful, Fortnite Art Style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/156f8d943ff6d283f7a34f265daaa46c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Futurism + NAME_ZH: 未来主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Futurism Art Style, {prompt}, dynamic, dramatic, Futurism Art Style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/855283cc2ab6283b627ef32d06a1ae0f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Glitchcore + NAME_ZH: 故障核心 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Glitchcore Art Style, {prompt}, dynamic, dramatic, distorted, vibrant colors, glitchcore art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/9af62376402a85774179e82cf7e0dc59.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Glo-fi + NAME_ZH: 光环音乐风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Glo-fi Art Style, {prompt}, dynamic, dramatic, vibrant colors, glo-fi art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/275a6e2a3297cec57f9b5a4a17b0f749.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Googie Art Style + NAME_ZH: 古奇艺术风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Googie Art Style, {prompt}, dynamic, dramatic, 1950's futurism, bold boomerang angles, Googie art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/08ee77586d7bec3f6bad7d60cee3c540.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Graffiti Art + NAME_ZH: 涂鸦艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Graffiti Art Style, {prompt}, dynamic, dramatic, vibrant colors, graffiti art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/57b751b11564cb22cd49ef21f2004a5f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Harlem Renaissance Art + NAME_ZH: 哈莱姆文艺复兴艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Harlem Renaissance Art Style, {prompt}, dynamic, dramatic, 1920s African American culture, Harlem Renaissance art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/d09ea3dadcd0a15d8fa247ee74a75e6b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: High Fashion + NAME_ZH: 高级时装 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: High Fashion, {prompt}, dynamic, dramatic, haute couture, elegant, ornate clothing, High Fashion + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/868f752bbb5ef992a0be36d7d13de3be.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Idyllic + NAME_ZH: 田园诗般的 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Idyllic, {prompt}, peaceful, happy, pleasant, happy, harmonious, picturesque, charming + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/55bab29eeb628e7a9ae018e45e7e24db.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Impressionism + NAME_ZH: 印象主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Impressionism, {prompt}, painterly, small brushstrokes, visible brushstrokes, impressionistic style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/0312b673dc6858a9864d7f45f0c5c1fc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Infographic Drawing + NAME_ZH: 信息图表绘制 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Infographic Drawing, {prompt}, diagram, infographic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/b09151f6e0883d26056b80fcc9d398bb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Ink Dripping Drawing + NAME_ZH: 墨水滴画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Ink Dripping Drawing, {prompt}, ink drawing, dripping ink + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, colorful, vibrant + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/5f09912a07e915250a96b2023db15821.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Japanese Ink Drawing + NAME_ZH: 日本墨画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Japanese Ink Drawing, {prompt}, ink drawing, inkwash, Japanese Ink Drawing + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, colorful, vibrant + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/633ad971ff30fe4717782fc6b5f92fda.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Knolling Photography + NAME_ZH: 秩序拍摄 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Knolling Photography, {prompt}, flat lay photography, object arrangment, knolling photography + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/89a205be3a276349ecddf0eeca43ed80.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Light Cheery Atmosphere + NAME_ZH: 轻快愉快的氛围 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Light Cheery Atmosphere, {prompt}, happy, joyful, cheerful, carefree, gleeful, lighthearted, pleasant atmosphere + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, monochromatic, dark, moody + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/0913ac9815f892411f8327a630f51ae4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Logo Design + NAME_ZH: 标志设计 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Logo Design, {prompt}, dynamic graphic art, vector art, minimalist, professional logo design + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/9aa040b0c60d289da9610c91ad9b7c7e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Luxurious Elegance + NAME_ZH: 奢华优雅 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Luxurious Elegance, {prompt}, extravagant, ornate, designer, opulent, picturesque, lavish + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/e796e84ed745150f0d4e28e0ac99b4cf.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Macro Photography + NAME_ZH: 微距摄影 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Macro Photography, {prompt}, close-up, macro 100mm, macro photography + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/92e8b84379828f38e3d01c7272f41b0b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Mandola Art + NAME_ZH: 曼陀罗艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Mandola art style, {prompt}, complex, circular design, mandola + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/dbf5ca944d9213c3181348666cf337ac.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Marker Drawing + NAME_ZH: 马克笔绘图 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Marker Drawing, {prompt}, bold marker lines, visibile paper texture, marker drawing + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photograph, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/c558745f7a4b77d7ca9a428d8874efe4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Medievalism + NAME_ZH: 中世纪主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Medievalism, {prompt}, inspired by The Middle Ages, medieval art, elaborate patterns and decoration, Medievalism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/26aa6244359a4fd87f6438a341057901.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Minimalism + NAME_ZH: 极简主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Minimalism, {prompt}, abstract, simple geometic shapes, hard edges, sleek contours, Minimalism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/dce92a90da6299339cf8e9ebc6596ea2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Baroque + NAME_ZH: 新巴洛克 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Neo-Baroque, {prompt}, ornate and elaborate, dynaimc, Neo-Baroque + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/9b6cd8751b18c65b259769b44cfac351.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Byzantine + NAME_ZH: 新拜占庭 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Neo-Byzantine, {prompt}, grand decorative religious style, Orthodox Christian inspired, Neo-Byzantine + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/99c67768869b546bf527ef0b1735c0d5.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Futurism + NAME_ZH: 新未来主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Neo-Futurism, {prompt}, high-tech, curves, spirals, flowing lines, idealistic future, Neo-Futurism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/bada1534f7a60187f584febcc92f40d1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Impressionism + NAME_ZH: 新印象主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Neo-Impressionism, {prompt}, tiny dabs of color, Pointillism, painterly, Neo-Impressionism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photograph, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/6bafeac67ce2679b64a86ee1023b53c9.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Rococo + NAME_ZH: 新洛可可 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Neo-Rococo, {prompt}, curved forms, naturalistic ornamentation, elaborate, decorative, gaudy, Neo-Rococo + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/9ab0ad2b88e03933ea479357ff1e4435.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neoclassicism + NAME_ZH: 新古典主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Neoclassicism, {prompt}, ancient Rome and Greece inspired, idealic, sober colors, Neoclassicism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/83a4e3a2ca577400b05a81b5b2b8650e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Op Art + NAME_ZH: 视觉艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Op Art, {prompt}, optical illusion, abstract, geometric pattern, impression of movement, Op Art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/5f11132803dff2de5213293b91d407d7.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Ornate and Intricate + NAME_ZH: 华丽复杂 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Ornate and Intricate, {prompt}, decorative, highly detailed, elaborate, ornate, intricate + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/24b895dca946c8765ad9fa38f720f671.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Pencil Sketch Drawing + NAME_ZH: 铅笔素描 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Pencil Sketch Drawing, {prompt}, black and white drawing, graphite drawing + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/a9056e1eac85e5e4fe96a93917d4cce4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Pop Art 2 + NAME_ZH: 流行艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Pop Art, {prompt}, vivid colors, flat color, 2D, strong lines, Pop Art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/83c4c06c70a48da6558ff970ece247b6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Rococo + NAME_ZH: 洛可可 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Rococo, {prompt}, flamboyant, pastel colors, curved lines, elaborate detail, Rococo + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/4850170f410e10bc833b7d00324dff18.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Silhouette Art + NAME_ZH: 剪影艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Silhouette Art, {prompt}, high contrast, well defined, Silhouette Art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/568777f447fc02510b618152726d5002.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Simple Vector Art + NAME_ZH: 简单矢量艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Simple Vector Art, {prompt}, 2D flat, simple shapes, minimalistic, professional graphic, flat color, high contrast, Simple Vector Art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, 3D, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/24d2ab1fd175bf4e9ef3a8327651dd4b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Sketchup + NAME_ZH: 草图大师 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Sketchup, {prompt}, CAD, professional design, Sketchup + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photo, photograph + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/337dca7ac49cf7820c85ede096ebde9c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Steampunk 2 + NAME_ZH: 蒸汽朋克 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Steampunk, {prompt}, retrofuturistic science fantasy, steam-powered tech, vintage industry, gears, neo-victorian, steampunk + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/07d7b27cd73f2d43684003563511c15b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Surrealism + NAME_ZH: 超现实主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Surrealism, {prompt}, expressive, dramatic, organic lines and forms, dreamlike and mysterious, Surrealism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/38bae70377b323d1a5f5756d7e04886d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Suprematism + NAME_ZH: 至上主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Suprematism, {prompt}, abstract, limited color palette, geometric forms, Suprematism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/c48fbd8cedee84d06b4d875d566f1bb8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Terragen + NAME_ZH: 地形生成 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Terragen, {prompt}, beautiful massive landscape, epic scenery, Terragen + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/8974cd8e0f38fb7aac117cf0983fc36d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Tranquil Relaxing Atmosphere + NAME_ZH: 宁静放松的氛围 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Tranquil Relaxing Atmosphere, {prompt}, calming style, soothing colors, peaceful, idealic, Tranquil Relaxing Atmosphere + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, oversaturated + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/69170d8443a67be4210af8d5558779c2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Sticker Designs + NAME_ZH: 贴纸设计 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Vector Art Stickers, {prompt}, professional vector design, sticker designs, Sticker Sheet + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/2d1e9867058db2c57f2fe47530de3243.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Vibrant Rim Light + NAME_ZH: 生动的边缘光 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Vibrant Rim Light, {prompt}, bright rim light, high contrast, bold edge light + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/bb08936ca184daba2b30b4a9efb308f2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Volumetric Lighting + NAME_ZH: 体积光照明 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Volumetric Lighting, {prompt}, light depth, dramatic atmospheric lighting, Volumetric Lighting + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/bbad7964a2ae70b66c72804273f11e74.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Watercolor 2 + NAME_ZH: 水彩 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Watercolor style painting, {prompt}, visible paper texture, colorwash, watercolor + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/8859d532ae5901cc8457d6118fb9b7da.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Whimsical and Playful + NAME_ZH: 异想天开和俏皮 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + PROMPT: Whimsical and Playful, {prompt}, imaginative, fantastical, bight colors, stylized, happy, Whimsical and Playful + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, drab, boring, moody + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/af2267f1942e870be957c37cd73d4359.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Enhance + NAME_ZH: 焦点增强 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD1.5 + PROMPT: { + "prompt": null +} + + NEGATIVE_PROMPT: (worst quality, low quality, normal quality, lowres, low details, oversaturated, undersaturated, overexposed, underexposed, grayscale, bw, bad photo, bad photography, bad art:1.4), (watermark, signature, text font, username, error, logo, words, letters, digits, autograph, trademark, name:1.2), (blur, blurry, grainy), morbid, ugly, asymmetrical, mutated malformed, mutilated, poorly lit, bad shadow, draft, cropped, out of frame, cut off, censored, jpeg artifacts, out of focus, glitch, duplicate, (airbrushed, cartoon, anime, semi-realistic, cgi, render, blender, digital art, manga, amateur:1.3), (3D ,3D Game, 3D Game Scene, 3D Character:1.1), (bad hands, bad anatomy, bad body, bad face, bad teeth, bad arms, bad legs, deformities:1.3) + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/e501823a21bbda56592055c9613c1dbb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Sharp + NAME_ZH: 焦点锐化 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD1.5 + PROMPT: cinematic still {prompt} . emotional, harmonious, vignette, 4k epic detailed, shot on kodak, 35mm photo, sharp focus, high budget, cinemascope, moody, epic, gorgeous, film grain, grainy + NEGATIVE_PROMPT: anime, cartoon, graphic, (blur, blurry, bokeh), text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/393fb7aab57992a1c3af7cbad01c1001.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Masterpiece + NAME_ZH: 焦点杰作 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD1.5 + PROMPT: (masterpiece), (best quality), (ultra-detailed), {prompt}, illustration, disheveled hair, detailed eyes, perfect composition, moist skin, intricate details, earrings, by wlop + NEGATIVE_PROMPT: longbody, lowres, bad anatomy, bad hands, missing fingers, pubic hair,extra digit, fewer digits, cropped, worst quality, low quality + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/9e27c3d1475dacae0ee45cea783aaaf5.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Photograph + NAME_ZH: 焦点摄影 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD1.5 + PROMPT: photograph {prompt}, 50mm . cinematic 4k epic detailed 4k epic detailed photograph shot on kodak detailed cinematic hbo dark moody, 35mm photo, grainy, vignette, vintage, Kodachrome, Lomography, stained, highly detailed, found footage + NEGATIVE_PROMPT: Brad Pitt, bokeh, depth of field, blurry, cropped, regular face, saturated, contrast, deformed iris, deformed pupils, semi-realistic, cgi, 3d, render, sketch, cartoon, drawing, anime, text, cropped, out of frame, worst quality, low quality, jpeg artifacts, ugly, duplicate, morbid, mutilated, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, dehydrated, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/8b2ea41ec15bf1a16d6a837d46dbc2ac.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Negative + NAME_ZH: 焦点底片 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD1.5 + PROMPT: { + "prompt": null +} + + NEGATIVE_PROMPT: deformed, bad anatomy, disfigured, poorly drawn face, mutated, extra limb, ugly, poorly drawn hands, missing limb, floating limbs, disconnected limbs, disconnected head, malformed hands, long neck, mutated hands and fingers, bad hands, missing fingers, cropped, worst quality, low quality, mutation, poorly drawn, huge calf, bad hands, fused hand, missing hand, disappearing arms, disappearing thigh, disappearing calf, disappearing legs, missing fingers, fused fingers, abnormal eye proportion, Abnormal hands, abnormal legs, abnormal feet, abnormal fingers, drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly, anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/daaec2962291137532189b8a31012532.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Cinematic + NAME_ZH: 焦点电影 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD1.5 + PROMPT: cinematic still {prompt} . emotional, harmonious, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy + NEGATIVE_PROMPT: anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/adc4d52aa5b0afca0593a475ddc9d055.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-cinematic-dynamic + NAME_ZH: MRE电影动态 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: epic cinematic shot of dynamic {prompt} in motion. main subject of high budget action movie. raw photo, motion blur. best quality, high resolution + NEGATIVE_PROMPT: static, still, motionless, sluggish. drawing, painting, illustration, rendered. low budget. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/bd2470068e09d9f1b7d0a690c879b3ce.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-spontaneous-picture + NAME_ZH: MRE自发图片 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: spontaneous picture of {prompt}, taken by talented amateur. best quality, high resolution. magical moment, natural look. simple but good looking + NEGATIVE_PROMPT: overthinked. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/19ad6082cee5516ce330641b515467ef.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-artistic-vision + NAME_ZH: MRE艺术视觉 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: powerful artistic vision of {prompt}. breathtaking masterpiece made by great artist. best quality, high resolution + NEGATIVE_PROMPT: insignificant, flawed, made by bad artist. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/95af94e50bcb91ae8fd2914a3bf13f1e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-dark-dream + NAME_ZH: MRE黑暗梦境 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: dark and unsettling dream showing {prompt}. best quality, high resolution. created by genius but depressed mad artist. grim beauty + NEGATIVE_PROMPT: naive, cheerful. comfortable, casual, boring, cliche. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/572c8c26cc20ac0ee66684e3c5ee4e8c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-gloomy-art + NAME_ZH: MRE忧郁艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: astonishing gloomy art made mainly of shadows and lighting, forming {prompt}. masterful usage of lighting, shadows and chiaroscuro. made by black-hearted artist, drawing from darkness. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/66cbdf819e930f7580bd66a41bde7dfe.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-bad-dream + NAME_ZH: MRE恶梦 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: picture from really bad dream about terrifying {prompt}, true horror. bone-chilling vision. mad world that shouldn't exist. best quality, high resolution + NEGATIVE_PROMPT: nice dream, pleasant experience. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/b92b2bbfc400db9204fe8249354132b4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-underground + NAME_ZH: MRE地下 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: uncanny caliginous vision of {prompt}, created by remarkable underground artist. best quality, high resolution. raw and brutal art, careless but impressive style. inspired by darkness and chaos + NEGATIVE_PROMPT: photography, mainstream, civilized. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/8d46eca558d791a1f2b41b0ed7bba4d2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-surreal-painting + NAME_ZH: MRE超现实绘画 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: surreal painting representing strange vision of {prompt}. harmonious madness, synergy with chance. unique artstyle, mindbending art, magical surrealism. best quality, high resolution + NEGATIVE_PROMPT: photography, illustration, drawing. realistic, possible. logical, sane. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/58858425832b10d233f7887af4a2022f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-dynamic-illustration + NAME_ZH: MRE动态插画 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: insanely dynamic illustration of {prompt}. best quality, high resolution. crazy artstyle, careless brushstrokes, emotional and fun + NEGATIVE_PROMPT: photography, realistic. static, still, slow, boring. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/8bf9861d4d3fadcdb98ceec88a941582.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-undead-art + NAME_ZH: MRE不死艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: long forgotten art created by undead artist illustrating {prompt}, tribute to the death and decay. miserable art of the damned. wretched and decaying world. best quality, high resolution + NEGATIVE_PROMPT: alive, playful, living. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/fada50979ca180006eba9a45a00f3675.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-elemental-art + NAME_ZH: MRE元素艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: art illustrating insane amounts of raging elemental energy turning into {prompt}, avatar of elements. magical surrealism, wizardry. best quality, high resolution + NEGATIVE_PROMPT: photography, realistic, real. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/5895d78cf58c1ca05178991f37cc48ff.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-space-art + NAME_ZH: MRE太空艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: winner of inter-galactic art contest illustrating {prompt}, symbol of the interstellar singularity. best quality, high resolution. artstyle previously unseen in the whole galaxy + NEGATIVE_PROMPT: created by human race, low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/e9815495587895a21d970728474c8be6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-ancient-illustration + NAME_ZH: MRE古代插画 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: sublime ancient illustration of {prompt}, predating human civilization. crude and simple, but also surprisingly beautiful artwork, made by genius primeval artist. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/151e07c17a89ebaf7688905ea0199862.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-brave-art + NAME_ZH: MRE勇敢艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: brave, shocking, and brutally true art showing {prompt}. inspired by courage and unlimited creativity. truth found in chaos. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/1a068f2728327d21ebb99285c2ce1370.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-heroic-fantasy + NAME_ZH: MRE英雄幻想 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: heroic fantasy painting of {prompt}, in the dangerous fantasy world. airbrush over oil on canvas. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/78d05472067e0b86c8270fa5476fcb8e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-dark-cyberpunk + NAME_ZH: MRE黑暗赛博朋克 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: dark cyberpunk illustration of brutal {prompt} in a world without hope, ruled by ruthless criminal corporations. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/a9f50e3162958fd783872d6955ad7d0b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-lyrical-geometry + NAME_ZH: MRE抒情几何 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: geometric and lyrical abstraction painting presenting {prompt}. oil on metal. best quality, high resolution + NEGATIVE_PROMPT: photography, realistic, drawing, rendered. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/dfabd41d3042ced804bc97ae35e3a7cb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-sumi-e-symbolic + NAME_ZH: MRE墨绘象征 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: big long brushstrokes of deep black sumi-e turning into symbolic painting of {prompt}. master level raw art. best quality, high resolution + NEGATIVE_PROMPT: photography, rendered. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/695b1ba687544eaeec9fb5f871917aeb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-sumi-e-detailed + NAME_ZH: MRE墨绘精细 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: highly detailed black sumi-e painting of {prompt}. in-depth study of perfection, created by a master. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/16eb95e180385b88794e368b28da1812.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-manga + NAME_ZH: MRE漫画 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: manga artwork presenting {prompt}. created by japanese manga artist. highly emotional. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/ebec631bf467937f82d05958ae59f9dc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-anime + NAME_ZH: MRE动漫 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: anime artwork illustrating {prompt}. created by japanese anime studio. highly emotional. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/a08149bc8e50f6bc65c0010d4cd416f8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-comic + NAME_ZH: MRE漫画书 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + PROMPT: breathtaking illustration from adult comic book presenting {prompt}. fabulous artwork. best quality, high resolution + NEGATIVE_PROMPT: deformed, ugly, low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/48c65cebf1fa4284d7b8feb619412e65.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-3d-model + NAME_ZH: SAI三维模型 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: professional 3d model {prompt} . octane render, highly detailed, volumetric, dramatic lighting + NEGATIVE_PROMPT: ugly, deformed, noisy, low poly, blurry, painting + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/c1a765ac089fdfb3c1d11b33c75d2afd.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-analog film + NAME_ZH: SAI模拟胶片 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: analog film photo {prompt} . faded film, desaturated, 35mm photo, grainy, vignette, vintage, Kodachrome, Lomography, stained, highly detailed, found footage + NEGATIVE_PROMPT: painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/3c46d19957efd7fb78f4ab2bdada5468.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-anime + NAME_ZH: SAI动漫 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: anime artwork {prompt} . anime style, key visual, vibrant, studio anime, highly detailed + NEGATIVE_PROMPT: photo, deformed, black and white, realism, disfigured, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/c030e72561eda96abcf738f1370d36ff.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-cinematic + NAME_ZH: SAI电影 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: cinematic film still {prompt} . shallow depth of field, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy + NEGATIVE_PROMPT: anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/d9161c0d5cbf2133b2bfc1021c0c5e2a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-comic book + NAME_ZH: SAI漫画书 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: comic {prompt} . graphic illustration, comic art, graphic novel art, vibrant, highly detailed + NEGATIVE_PROMPT: photograph, deformed, glitch, noisy, realistic, stock photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/6759ecb831037367e64c4b36d802be87.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-craft clay + NAME_ZH: SAI手工粘土 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: play-doh style {prompt} . sculpture, clay art, centered composition, Claymation + NEGATIVE_PROMPT: sloppy, messy, grainy, highly detailed, ultra textured, photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/8fc51113f725f27326c4398a7457cd6d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-digital art + NAME_ZH: SAI数字艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: concept art {prompt} . digital artwork, illustrative, painterly, matte painting, highly detailed + NEGATIVE_PROMPT: photo, photorealistic, realism, ugly + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/d29adb44458700c4a45ee6edaa04bfb6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-enhance + NAME_ZH: SAI增强 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: breathtaking {prompt} . award-winning, professional, highly detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, distorted, grainy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/2be0de541ff65f8da80ddc24a65c98d8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-fantasy art + NAME_ZH: SAI幻想艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: ethereal fantasy concept art of {prompt} . magnificent, celestial, ethereal, painterly, epic, majestic, magical, fantasy art, cover art, dreamy + NEGATIVE_PROMPT: photographic, realistic, realism, 35mm film, dslr, cropped, frame, text, deformed, glitch, noise, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, sloppy, duplicate, mutated, black and white + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/a6f8d92afcd5803dfb2ebecbc92091b6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-isometric + NAME_ZH: SAI等距 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: isometric style {prompt} . vibrant, beautiful, crisp, detailed, ultra detailed, intricate + NEGATIVE_PROMPT: deformed, mutated, ugly, disfigured, blur, blurry, noise, noisy, realistic, photographic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/d4e3fcbbfd7b1323bd89decf5d7b0006.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-line art + NAME_ZH: SAI线条艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: line art drawing {prompt} . professional, sleek, modern, minimalist, graphic, line art, vector graphics + NEGATIVE_PROMPT: anime, photorealistic, 35mm film, deformed, glitch, blurry, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, mutated, realism, realistic, impressionism, expressionism, oil, acrylic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/034a51b0dd34b018be8859bf45b4f7ed.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-lowpoly + NAME_ZH: SAI低多边形 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: low-poly style {prompt} . low-poly game art, polygon mesh, jagged, blocky, wireframe edges, centered composition + NEGATIVE_PROMPT: noisy, sloppy, messy, grainy, highly detailed, ultra textured, photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/76b9913e9fa5704b6d30adbde9e1f70f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-neonpunk + NAME_ZH: SAI霓虹朋克 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: neonpunk style {prompt} . cyberpunk, vaporwave, neon, vibes, vibrant, stunningly beautiful, crisp, detailed, sleek, ultramodern, magenta highlights, dark purple shadows, high contrast, cinematic, ultra detailed, intricate, professional + NEGATIVE_PROMPT: painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/7e9ed25bb34008beb5f417df63c4b2fe.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-origami + NAME_ZH: SAI折纸 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: origami style {prompt} . paper art, pleated paper, folded, origami art, pleats, cut and fold, centered composition + NEGATIVE_PROMPT: noisy, sloppy, messy, grainy, highly detailed, ultra textured, photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/924f46a8f276011a0953d7988e90ee25.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-photographic + NAME_ZH: SAI摄影 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: cinematic photo {prompt} . 35mm photograph, film, bokeh, professional, 4k, highly detailed + NEGATIVE_PROMPT: drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/d6a2d8f3d37cc21c20c5dfc13d000b67.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-pixel art + NAME_ZH: SAI像素艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: pixel-art {prompt} . low-res, blocky, pixel art style, 8-bit graphics + NEGATIVE_PROMPT: sloppy, messy, blurry, noisy, highly detailed, ultra textured, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/a5ab89c0960be8c1216e65c98d92ae4a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-texture + NAME_ZH: SAI质地 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + PROMPT: texture {prompt} top down close-up + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/ebfeab574283fff2ac096e348a585e6d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-advertising + NAME_ZH: 广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: advertising poster style {prompt} . Professional, modern, product-focused, commercial, eye-catching, highly detailed + NEGATIVE_PROMPT: noisy, blurry, amateurish, sloppy, unattractive + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/1aa26a16126e2756bf4bf3fda29baa12.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-automotive + NAME_ZH: 汽车广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: automotive advertisement style {prompt} . sleek, dynamic, professional, commercial, vehicle-focused, high-resolution, highly detailed + NEGATIVE_PROMPT: noisy, blurry, unattractive, sloppy, unprofessional + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/ddc833b36ca23c85a4f6e7bf0088d081.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-corporate + NAME_ZH: 企业广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: corporate branding style {prompt} . professional, clean, modern, sleek, minimalist, business-oriented, highly detailed + NEGATIVE_PROMPT: noisy, blurry, grungy, sloppy, cluttered, disorganized + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/df97fa45c7842296c138aca4057db272.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-fashion editorial + NAME_ZH: 时尚编辑 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: fashion editorial style {prompt} . high fashion, trendy, stylish, editorial, magazine style, professional, highly detailed + NEGATIVE_PROMPT: outdated, blurry, noisy, unattractive, sloppy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/89259be723479cd0b81546b715bea04d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-food photography + NAME_ZH: 食品摄影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: food photography style {prompt} . appetizing, professional, culinary, high-resolution, commercial, highly detailed + NEGATIVE_PROMPT: unappetizing, sloppy, unprofessional, noisy, blurry + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/33acc98f8615940c8cebbac8ce5297b2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-gourmet food photography + NAME_ZH: 美食摄影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: gourmet food photo of {prompt} . soft natural lighting, macro details, vibrant colors, fresh ingredients, glistening textures, bokeh background, styled plating, wooden tabletop, garnished, tantalizing, editorial quality + NEGATIVE_PROMPT: cartoon, anime, sketch, grayscale, dull, overexposed, cluttered, messy plate, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/897bbd3f1d232de122796266f3845b50.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-luxury + NAME_ZH: 奢华广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: luxury product style {prompt} . elegant, sophisticated, high-end, luxurious, professional, highly detailed + NEGATIVE_PROMPT: cheap, noisy, blurry, unattractive, amateurish + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/5b33ecc84dc5ff285a0f2e69f43162cb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-real estate + NAME_ZH: 房地产广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: real estate photography style {prompt} . professional, inviting, well-lit, high-resolution, property-focused, commercial, highly detailed + NEGATIVE_PROMPT: dark, blurry, unappealing, noisy, unprofessional + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/1b99b7bcd0476144d80d066e747d8dfc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-retail + NAME_ZH: 零售广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: retail packaging style {prompt} . vibrant, enticing, commercial, product-focused, eye-catching, professional, highly detailed + NEGATIVE_PROMPT: noisy, blurry, amateurish, sloppy, unattractive + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/0029e46ef36380dde2084257108f8a6f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-abstract + NAME_ZH: 抽象艺术风格 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: abstract style {prompt} . non-representational, colors and shapes, expression of feelings, imaginative, highly detailed + NEGATIVE_PROMPT: realistic, photographic, figurative, concrete + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/8c401cb0a6ea288230222c4985e78667.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-abstract expressionism + NAME_ZH: 抽象表现主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: abstract expressionist painting {prompt} . energetic brushwork, bold colors, abstract forms, expressive, emotional + NEGATIVE_PROMPT: realistic, photorealistic, low contrast, plain, simple, monochrome + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/9df6635149c576b65d911c2e4cc6a86b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-art deco + NAME_ZH: 艺术装饰风格 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: art deco style {prompt} . geometric shapes, bold colors, luxurious, elegant, decorative, symmetrical, ornate, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, modernist, minimalist + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/82fff8a25de8075777caf14cb3eb5650.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-art nouveau + NAME_ZH: 新艺术风格 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: art nouveau style {prompt} . elegant, decorative, curvilinear forms, nature-inspired, ornate, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, modernist, minimalist + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/84075c5c0cb4b7a2541c6fbca9835cfd.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-constructivist + NAME_ZH: 构成主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: constructivist style {prompt} . geometric shapes, bold colors, dynamic composition, propaganda art style + NEGATIVE_PROMPT: realistic, photorealistic, low contrast, plain, simple, abstract expressionism + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/2a634ad0c89ecefbbea4ce5bcab3d5e5.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-cubist + NAME_ZH: 立体主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: cubist artwork {prompt} . geometric shapes, abstract, innovative, revolutionary + NEGATIVE_PROMPT: anime, photorealistic, 35mm film, deformed, glitch, low contrast, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/2a3d797008c08e12b485d61624741ea6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-expressionist + NAME_ZH: 表现主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: expressionist {prompt} . raw, emotional, dynamic, distortion for emotional effect, vibrant, use of unusual colors, detailed + NEGATIVE_PROMPT: realism, symmetry, quiet, calm, photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/83914655659001716a1acede295289d0.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-graffiti + NAME_ZH: 涂鸦 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: graffiti style {prompt} . street art, vibrant, urban, detailed, tag, mural + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/f72a23c7623eb480737eb73c08bf8423.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-hyperrealism + NAME_ZH: 超现实主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: hyperrealistic art {prompt} . extremely high-resolution details, photographic, realism pushed to extreme, fine texture, incredibly lifelike + NEGATIVE_PROMPT: simplified, abstract, unrealistic, impressionistic, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/db378d5a64a8e7ad1e29a4389bda5d1c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-impressionist + NAME_ZH: 印象主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: impressionist painting {prompt} . loose brushwork, vibrant color, light and shadow play, captures feeling over form + NEGATIVE_PROMPT: anime, photorealistic, 35mm film, deformed, glitch, low contrast, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/53b151aec4d5685dfc24511b6705b90e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-pointillism + NAME_ZH: 点彩主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: pointillism style {prompt} . composed entirely of small, distinct dots of color, vibrant, highly detailed + NEGATIVE_PROMPT: line drawing, smooth shading, large color fields, simplistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/23b137a409ee8a8c6ee160c1ddf0659f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-pop art + NAME_ZH: 波普艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: pop Art style {prompt} . bright colors, bold outlines, popular culture themes, ironic or kitsch + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, minimalist + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/bd4faf0e2b7dbc2d0eb21f3ebee97d3d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-psychedelic + NAME_ZH: 迷幻艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: psychedelic style {prompt} . vibrant colors, swirling patterns, abstract forms, surreal, trippy + NEGATIVE_PROMPT: monochrome, black and white, low contrast, realistic, photorealistic, plain, simple + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/7dc0131817f4c31517581dd4a811067b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-renaissance + NAME_ZH: 文艺复兴 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: renaissance style {prompt} . realistic, perspective, light and shadow, religious or mythological themes, highly detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, modernist, minimalist, abstract + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/69796484f61dc2e94d5853f5bbe27c05.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-steampunk + NAME_ZH: 蒸汽朋克 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: steampunk style {prompt} . antique, mechanical, brass and copper tones, gears, intricate, detailed + NEGATIVE_PROMPT: deformed, glitch, noisy, low contrast, anime, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/985005e28858b03c9500a6eb5bd9e201.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-surrealist + NAME_ZH: 超现实主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: surrealist art {prompt} . dreamlike, mysterious, provocative, symbolic, intricate, detailed + NEGATIVE_PROMPT: anime, photorealistic, realistic, deformed, glitch, noisy, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/892d19ec3c429b7148562796df0024db.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-typography + NAME_ZH: 排版艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: typographic art {prompt} . stylized, intricate, detailed, artistic, text-based + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/9adafe1bb169e1ee3f78ba2c1b1cf8d3.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-watercolor + NAME_ZH: 水彩艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: watercolor painting {prompt} . vibrant, beautiful, painterly, detailed, textural, artistic + NEGATIVE_PROMPT: anime, photorealistic, 35mm film, deformed, glitch, low contrast, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/29ca23d7a0397e9beaa72e3b63d17551.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-biomechanical + NAME_ZH: 未来生物力学 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: biomechanical style {prompt} . blend of organic and mechanical elements, futuristic, cybernetic, detailed, intricate + NEGATIVE_PROMPT: natural, rustic, primitive, organic, simplistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/5987795487a3fa74469499ae53963d5d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-biomechanical cyberpunk + NAME_ZH: 未来生物力学赛博朋克 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: biomechanical cyberpunk {prompt} . cybernetics, human-machine fusion, dystopian, organic meets artificial, dark, intricate, highly detailed + NEGATIVE_PROMPT: natural, colorful, deformed, sketch, low contrast, watercolor + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/75b56d7cff9b3f011248b3092ae3b8d2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-cybernetic + NAME_ZH: 未来赛博 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: cybernetic style {prompt} . futuristic, technological, cybernetic enhancements, robotics, artificial intelligence themes + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, historical, medieval + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/47df6db04290f01aeee7381aaf12ec07.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-cybernetic robot + NAME_ZH: 未来机器人 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: cybernetic robot {prompt} . android, AI, machine, metal, wires, tech, futuristic, highly detailed + NEGATIVE_PROMPT: organic, natural, human, sketch, watercolor, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/6f18121b4ba22c8ba7834f404501fa4c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-cyberpunk cityscape + NAME_ZH: 未来赛博朋克城市景观 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: cyberpunk cityscape {prompt} . neon lights, dark alleys, skyscrapers, futuristic, vibrant colors, high contrast, highly detailed + NEGATIVE_PROMPT: natural, rural, deformed, low contrast, black and white, sketch, watercolor + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/5e4107dace2c9dd0217a9d1b18ae28f6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-futuristic + NAME_ZH: 未来主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: futuristic style {prompt} . sleek, modern, ultramodern, high tech, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, vintage, antique + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/8a61c0853ee4079bae96ad502a6ae840.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-retro cyberpunk + NAME_ZH: 未来复古赛博朋克 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: retro cyberpunk {prompt} . 80's inspired, synthwave, neon, vibrant, detailed, retro futurism + NEGATIVE_PROMPT: modern, desaturated, black and white, realism, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/460957bf9a07a58ddec08bf22d5b3698.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-retro futurism + NAME_ZH: 未来复古主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: retro-futuristic {prompt} . vintage sci-fi, 50s and 60s style, atomic age, vibrant, highly detailed + NEGATIVE_PROMPT: contemporary, realistic, rustic, primitive + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/0434a7b23a0f936db615d7a9b8e805f1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-sci-fi + NAME_ZH: 科幻未来主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: sci-fi style {prompt} . futuristic, technological, alien worlds, space themes, advanced civilizations + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, historical, medieval + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/7c3bde651f426273758b68a2805d0c8a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-vaporwave + NAME_ZH: 未来波 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: vaporwave style {prompt} . retro aesthetic, cyberpunk, vibrant, neon colors, vintage 80s and 90s style, highly detailed + NEGATIVE_PROMPT: monochrome, muted colors, realism, rustic, minimalist, dark + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/1ebb0bf67ee3ef76288b4c0a2a65d557.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-bubble bobble + NAME_ZH: 游戏-泡泡龙 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: Bubble Bobble style {prompt} . 8-bit, cute, pixelated, fantasy, vibrant, reminiscent of Bubble Bobble game + NEGATIVE_PROMPT: realistic, modern, photorealistic, violent, horror + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/19257352df33228555cb350963d9432a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-cyberpunk game + NAME_ZH: 赛博朋克游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: cyberpunk game style {prompt} . neon, dystopian, futuristic, digital, vibrant, detailed, high contrast, reminiscent of cyberpunk genre video games + NEGATIVE_PROMPT: historical, natural, rustic, low detailed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/6165ef47bc859e3dd0e3399ba2264c2b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-fighting game + NAME_ZH: 格斗游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: fighting game style {prompt} . dynamic, vibrant, action-packed, detailed character design, reminiscent of fighting video games + NEGATIVE_PROMPT: peaceful, calm, minimalist, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/aebda69ec1097dc61966995956ae34cc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-gta + NAME_ZH: 侠盗猎车手游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: GTA-style artwork {prompt} . satirical, exaggerated, pop art style, vibrant colors, iconic characters, action-packed + NEGATIVE_PROMPT: realistic, black and white, low contrast, impressionist, cubist, noisy, blurry, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/edff7ba5fc983468e79e64beb838b829.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-mario + NAME_ZH: 马里奥游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: Super Mario style {prompt} . vibrant, cute, cartoony, fantasy, playful, reminiscent of Super Mario series + NEGATIVE_PROMPT: realistic, modern, horror, dystopian, violent + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/2a229f623ce89160d1f67620599dfc7c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-minecraft + NAME_ZH: 我的世界游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: Minecraft style {prompt} . blocky, pixelated, vibrant colors, recognizable characters and objects, game assets + NEGATIVE_PROMPT: smooth, realistic, detailed, photorealistic, noise, blurry, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/83e77332a9f234fd8c9cddd29e2ec3c7.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-pokemon + NAME_ZH: 宝可梦游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: Pokémon style {prompt} . vibrant, cute, anime, fantasy, reminiscent of Pokémon series + NEGATIVE_PROMPT: realistic, modern, horror, dystopian, violent + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/9bfe2805e6578875a8dfe2a0ea96c281.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-retro arcade + NAME_ZH: 复古街机 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: retro arcade style {prompt} . 8-bit, pixelated, vibrant, classic video game, old school gaming, reminiscent of 80s and 90s arcade games + NEGATIVE_PROMPT: modern, ultra-high resolution, photorealistic, 3D + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/76885e0b110f1fdf3eaee52fbaf27abf.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-retro game + NAME_ZH: 复古游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: retro game art {prompt} . 16-bit, vibrant colors, pixelated, nostalgic, charming, fun + NEGATIVE_PROMPT: realistic, photorealistic, 35mm film, deformed, glitch, low contrast, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/61fbae41c50f56e24dcf20fe3612d456.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-rpg fantasy game + NAME_ZH: 角色扮演幻想游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: role-playing game (RPG) style fantasy {prompt} . detailed, vibrant, immersive, reminiscent of high fantasy RPG games + NEGATIVE_PROMPT: sci-fi, modern, urban, futuristic, low detailed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/34797baf58e32b4e1a37753fe9dcff5c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-strategy game + NAME_ZH: 策略游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: strategy game style {prompt} . overhead view, detailed map, units, reminiscent of real-time strategy video games + NEGATIVE_PROMPT: first-person view, modern, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/0d276527d22510a1b5f8f74eac2790df.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-streetfighter + NAME_ZH: 街头霸王游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: Street Fighter style {prompt} . vibrant, dynamic, arcade, 2D fighting game, highly detailed, reminiscent of Street Fighter series + NEGATIVE_PROMPT: 3D, realistic, modern, photorealistic, turn-based strategy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/f5927fc2b8d4a8212242bd97adcbdfa1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-zelda + NAME_ZH: 塞尔达传说游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: Legend of Zelda style {prompt} . vibrant, fantasy, detailed, epic, heroic, reminiscent of The Legend of Zelda series + NEGATIVE_PROMPT: sci-fi, modern, realistic, horror + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/4f9eadddbc196268258089b8cc4e5c5c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-architectural + NAME_ZH: 建筑 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: architectural style {prompt} . clean lines, geometric shapes, minimalist, modern, architectural drawing, highly detailed + NEGATIVE_PROMPT: curved lines, ornate, baroque, abstract, grunge + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/488545e9fc9417d62961f42d578547d2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-disco + NAME_ZH: 迪斯科 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: disco-themed {prompt} . vibrant, groovy, retro 70s style, shiny disco balls, neon lights, dance floor, highly detailed + NEGATIVE_PROMPT: minimalist, rustic, monochrome, contemporary, simplistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/784b0ac35e0c0fdb2df21a95d5ca1c55.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-dreamscape + NAME_ZH: 梦境 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: dreamscape {prompt} . surreal, ethereal, dreamy, mysterious, fantasy, highly detailed + NEGATIVE_PROMPT: realistic, concrete, ordinary, mundane + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/2bf77804b5bf352c4e97475b1e8eb29e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-dystopian + NAME_ZH: 反乌托邦 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: dystopian style {prompt} . bleak, post-apocalyptic, somber, dramatic, highly detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, cheerful, optimistic, vibrant, colorful + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/065db0385e126192cbd27e22ca4f154c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-fairy tale + NAME_ZH: 童话故事 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: fairy tale {prompt} . magical, fantastical, enchanting, storybook style, highly detailed + NEGATIVE_PROMPT: realistic, modern, ordinary, mundane + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/578dfe65d9f03e83c95820d4c45cd396.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-gothic + NAME_ZH: 哥特 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: gothic style {prompt} . dark, mysterious, haunting, dramatic, ornate, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, cheerful, optimistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/332a1f8cd655b724cb48bc5c91b764fc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-grunge + NAME_ZH: 垃圾摇滚 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: grunge style {prompt} . textured, distressed, vintage, edgy, punk rock vibe, dirty, noisy + NEGATIVE_PROMPT: smooth, clean, minimalist, sleek, modern, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/0ccb4c03c6d983b9f6d05ba383f9d690.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-horror + NAME_ZH: 恐怖 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: horror-themed {prompt} . eerie, unsettling, dark, spooky, suspenseful, grim, highly detailed + NEGATIVE_PROMPT: cheerful, bright, vibrant, light-hearted, cute + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/fdca4780d099a39dc50e4553622fba72.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-kawaii + NAME_ZH: 卡哇伊 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: kawaii style {prompt} . cute, adorable, brightly colored, cheerful, anime influence, highly detailed + NEGATIVE_PROMPT: dark, scary, realistic, monochrome, abstract + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/99dab4185e7337189d8959878bfa308b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-lovecraftian + NAME_ZH: 克苏鲁神话 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: lovecraftian horror {prompt} . eldritch, cosmic horror, unknown, mysterious, surreal, highly detailed + NEGATIVE_PROMPT: light-hearted, mundane, familiar, simplistic, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/b7c9d084ed62c1c2e1ea080ad95af61e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-macabre + NAME_ZH: 恐怖的 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: macabre style {prompt} . dark, gothic, grim, haunting, highly detailed + NEGATIVE_PROMPT: bright, cheerful, light-hearted, cartoonish, cute + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/fd7cf2315b27b0434b909020414e1173.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-manga + NAME_ZH: 漫画 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: manga style {prompt} . vibrant, high-energy, detailed, iconic, Japanese comic style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, Western comic style + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/531aac90b321d39221ba7cf70a97b232.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-metropolis + NAME_ZH: 大都市 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: metropolis-themed {prompt} . urban, cityscape, skyscrapers, modern, futuristic, highly detailed + NEGATIVE_PROMPT: rural, natural, rustic, historical, simple + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/eaad79fe3d7160cec6e0656fc3b02d3c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-minimalist + NAME_ZH: 极简主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: minimalist style {prompt} . simple, clean, uncluttered, modern, elegant + NEGATIVE_PROMPT: ornate, complicated, highly detailed, cluttered, disordered, messy, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/e85dd1ccc7f22bdac054d74ba58521b2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-monochrome + NAME_ZH: 单色 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: monochrome {prompt} . black and white, contrast, tone, texture, detailed + NEGATIVE_PROMPT: colorful, vibrant, noisy, blurry, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/cc793ada6b47561f4b63aa66dcd282ac.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-nautical + NAME_ZH: 航海 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: nautical-themed {prompt} . sea, ocean, ships, maritime, beach, marine life, highly detailed + NEGATIVE_PROMPT: landlocked, desert, mountains, urban, rustic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/3d9f6528180670804a2c5e85c7665c42.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-space + NAME_ZH: 太空 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: space-themed {prompt} . cosmic, celestial, stars, galaxies, nebulas, planets, science fiction, highly detailed + NEGATIVE_PROMPT: earthly, mundane, ground-based, realism + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/6f5742d23b43fc99cc01c8b68518df7c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-stained glass + NAME_ZH: 彩色玻璃 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: stained glass style {prompt} . vibrant, beautiful, translucent, intricate, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/ab0512ced9ed572075c49ad4f9f9a45d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-techwear fashion + NAME_ZH: 科技服饰 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: techwear fashion {prompt} . futuristic, cyberpunk, urban, tactical, sleek, dark, highly detailed + NEGATIVE_PROMPT: vintage, rural, colorful, low contrast, realism, sketch, watercolor + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/652a6bdb1b36860041222a458c7915d0.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-tribal + NAME_ZH: 部落 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: tribal style {prompt} . indigenous, ethnic, traditional patterns, bold, natural colors, highly detailed + NEGATIVE_PROMPT: modern, futuristic, minimalist, pastel + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/1ecdaf153ece5e16250b87020b7a209b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-zentangle + NAME_ZH: 禅绕画 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: zentangle {prompt} . intricate, abstract, monochrome, patterns, meditative, highly detailed + NEGATIVE_PROMPT: colorful, representative, simplistic, large fields of color + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/80f3488cdb69f0ff13d83a4feac4499d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-collage + NAME_ZH: 纸艺拼贴 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: collage style {prompt} . mixed media, layered, textural, detailed, artistic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/c9bbdaba28358faf1a8c1df44b3de950.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-flat papercut + NAME_ZH: 平面剪纸 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: flat papercut style {prompt} . silhouette, clean cuts, paper, sharp edges, minimalist, color block + NEGATIVE_PROMPT: 3D, high detail, noise, grainy, blurry, painting, drawing, photo, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/1bffcd9a4086b29c367b8301f26eed3b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-kirigami + NAME_ZH: 剪纸 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: kirigami representation of {prompt} . 3D, paper folding, paper cutting, Japanese, intricate, symmetrical, precision, clean lines + NEGATIVE_PROMPT: painting, drawing, 2D, noisy, blurry, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/2e5f95977b97b2a6248924e118a23076.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-paper mache + NAME_ZH: 纸浆塑型 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: paper mache representation of {prompt} . 3D, sculptural, textured, handmade, vibrant, fun + NEGATIVE_PROMPT: 2D, flat, photo, sketch, digital art, deformed, noisy, blurry + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/68441f668fcf7a51db5fc9b9d4d45ce7.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-paper quilling + NAME_ZH: 纸卷艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: paper quilling art of {prompt} . intricate, delicate, curling, rolling, shaping, coiling, loops, 3D, dimensional, ornamental + NEGATIVE_PROMPT: photo, painting, drawing, 2D, flat, deformed, noisy, blurry + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/8c0504eb14341b66796612c46bb3748b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-papercut collage + NAME_ZH: 剪纸拼贴 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: papercut collage of {prompt} . mixed media, textured paper, overlapping, asymmetrical, abstract, vibrant + NEGATIVE_PROMPT: photo, 3D, realistic, drawing, painting, high detail, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/217e7c8b905b63c63c94bd6ff8fe3477.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-papercut shadow box + NAME_ZH: 剪纸影箱 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: 3D papercut shadow box of {prompt} . layered, dimensional, depth, silhouette, shadow, papercut, handmade, high contrast + NEGATIVE_PROMPT: painting, drawing, photo, 2D, flat, high detail, blurry, noisy, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/2af0d61de1b17a5a5257f512549f9616.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-stacked papercut + NAME_ZH: 堆叠剪纸 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: stacked papercut art of {prompt} . 3D, layered, dimensional, depth, precision cut, stacked layers, papercut, high contrast + NEGATIVE_PROMPT: 2D, flat, noisy, blurry, painting, drawing, photo, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/62618e32e90539827e0eb279a6ea170a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-thick layered papercut + NAME_ZH: 厚层剪纸 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: thick layered papercut art of {prompt} . deep 3D, volumetric, dimensional, depth, thick paper, high stack, heavy texture, tangible layers + NEGATIVE_PROMPT: 2D, flat, thin paper, low stack, smooth texture, painting, drawing, photo, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/17008c40a6be8d41d3921ee88bac27ad.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-alien + NAME_ZH: 异形 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: alien-themed {prompt} . extraterrestrial, cosmic, otherworldly, mysterious, sci-fi, highly detailed + NEGATIVE_PROMPT: earthly, mundane, common, realistic, simple + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/eae6043dee2b2d94cd9a22cb044db8b3.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-film noir + NAME_ZH: 黑色电影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: film noir style {prompt} . monochrome, high contrast, dramatic shadows, 1940s style, mysterious, cinematic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, vibrant, colorful + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/0b3629be5ebb7cda463877a1993a0298.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-glamour + NAME_ZH: 魅力 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: glamorous photo {prompt} . high fashion, luxurious, extravagant, stylish, sensual, opulent, elegance, stunning beauty, professional, high contrast, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, distorted, grainy, sketch, low contrast, dull, plain, modest + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/f85dc6aa5d7f7d6d3663f2270e276796.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-hdr + NAME_ZH: 高动态范围 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: HDR photo of {prompt} . High dynamic range, vivid, rich details, clear shadows and highlights, realistic, intense, enhanced contrast, highly detailed + NEGATIVE_PROMPT: flat, low contrast, oversaturated, underexposed, overexposed, blurred, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/269a98b284ae1345b0e5ac1f85c33179.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-iphone photographic + NAME_ZH: iPhone摄影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: iphone photo {prompt} . large depth of field, deep depth of field, highly detailed + NEGATIVE_PROMPT: drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly, shallow depth of field, bokeh + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/48c556a6b3c3a533847b80b031cd4962.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-long exposure + NAME_ZH: 长曝光 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: long exposure photo of {prompt} . Blurred motion, streaks of light, surreal, dreamy, ghosting effect, highly detailed + NEGATIVE_PROMPT: static, noisy, deformed, shaky, abrupt, flat, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/fda88c3fc43ea8cc04ce9b5c0261627f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-neon noir + NAME_ZH: 霓虹黑色 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: neon noir {prompt} . cyberpunk, dark, rainy streets, neon signs, high contrast, low light, vibrant, highly detailed + NEGATIVE_PROMPT: bright, sunny, daytime, low contrast, black and white, sketch, watercolor + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/8a5b71434592771e064af4b9017b59d6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-silhouette + NAME_ZH: 剪影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: silhouette style {prompt} . high contrast, minimalistic, black and white, stark, dramatic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, color, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/1892a37e66d33cdd9b713aaab6b8c597.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-tilt-shift + NAME_ZH: 倾斜移位 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD1.5 + PROMPT: tilt-shift photo of {prompt} . selective focus, miniature effect, blurred background, highly detailed, vibrant, perspective control + NEGATIVE_PROMPT: blurry, noisy, deformed, flat, low contrast, unrealistic, oversaturated, underexposed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/d058a157de848a5c03d9a3e1e0e560a2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: cinematic-diva + NAME_ZH: 电影歌星画风 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: UHD, 8K, ultra detailed, a cinematic photograph of {prompt}, beautiful lighting, great composition + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, NSFW + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/967b1852ea26dcf41360fc5542a0df6b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Abstract Expressionism + NAME_ZH: 抽象表现主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Abstract Expressionism Art, {prompt}, High contrast, minimalistic, colorful, stark, dramatic, expressionism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/11667c7a085b53a6ffbb76b83788f8b5.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Academia + NAME_ZH: 学院风 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Academia, {prompt}, preppy Ivy League style, stark, dramatic, chic boarding school, academia + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, grunge, sloppy, unkempt + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/c95197ef78312e2bbd45883bfbfa095a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Action Figure + NAME_ZH: 动作人偶 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Action Figure, {prompt}, plastic collectable action figure, collectable toy action figure + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/24ac67fe21833fc1300fba09d5de6090.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Adorable 3D Character + NAME_ZH: 可爱的3D角色 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Adorable 3D Character, {prompt}, 3D render, adorable character, 3D art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, grunge, sloppy, unkempt, photograph, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/31a0ffbfc93b5b336a3bedc0a9985a02.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Adorable Kawaii + NAME_ZH: 可爱卡哇伊风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Adorable Kawaii, {prompt}, pretty, cute, adorable, kawaii + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, gothic, dark, moody, monochromatic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/82624c429d504c8290d4c9147be64029.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Art Deco + NAME_ZH: 艺术装饰风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Art Deco, {prompt}, sleek, geometric forms, art deco style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/c60ef3e7ada8774c92bb6e73c570f819.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Art Nouveau + NAME_ZH: 新艺术风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Art Nouveau, beautiful art, {prompt}, sleek, organic forms, long, sinuous, art nouveau style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, industrial, mechanical + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/153d83e71fbf145d0aa5c41ecab0a505.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Astral Aura + NAME_ZH: 星体光环 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Astral Aura, {prompt}, astral, colorful aura, vibrant energy + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/e093c9d0f81037002e88f2a6c3f38a55.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Avant-garde + NAME_ZH: 先锋派 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Avant-garde, {prompt}, unusual, experimental, avant-garde art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/9921d1944893466edfc6a060faf4070e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Baroque + NAME_ZH: 巴洛克风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Baroque, {prompt}, dramatic, exuberant, grandeur, baroque art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/d8279be4bb34e5cb00a95919412154a4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Bauhaus-Style Poster + NAME_ZH: 包豪斯风格海报 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Bauhaus-Style Poster, {prompt}, simple geometric shapes, clean lines, primary colors, Bauhaus-Style Poster + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/4bd18b32c23e13b9e4fc7f65a1916eab.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Blueprint Schematic Drawing + NAME_ZH: 蓝图原理图绘制 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Blueprint Schematic Drawing, {prompt}, technical drawing, blueprint, schematic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/62392c3715267f7162a37a8ff1caa3a1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Caricature + NAME_ZH: 漫画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Caricature, {prompt}, exaggerated, comical, caricature + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/894f40ed44b37c3372e6a22b8ae577a4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Cel Shaded Art + NAME_ZH: 单色阴影艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Cel Shaded Art, {prompt}, 2D, flat color, toon shading, cel shaded style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/71c2e8a2cd1031b2bfae1640f7b72c88.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Character Design Sheet + NAME_ZH: 角色设计图 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Character Design Sheet, {prompt}, character reference sheet, character turn around + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/eacf2134aa51d4b4a6f2f35cc170f315.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Classicism Art + NAME_ZH: 古典主义艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Classicism Art, {prompt}, inspired by Roman and Greek culture, clarity, harmonious, classicism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/10025b4f3a09e6134086e3cdec4ef2c8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Color Field Painting + NAME_ZH: 色域绘画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Color Field Painting, {prompt}, abstract, simple, geometic, color field painting style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/80e5b4075c572c04cbb4e48c37b8366b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Colored Pencil Art + NAME_ZH: 彩色铅笔艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Colored Pencil Art, {prompt}, colored pencil strokes, light color, visible paper texture, colored pencil art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/9ae235d7f1a7c2a4edab52a5e9f9cbae.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Conceptual Art + NAME_ZH: 概念艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Conceptual Art, {prompt}, concept art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/cf2e6781997c6842a16155fdff911ef8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Constructivism + NAME_ZH: 结构主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Constructivism Art, {prompt}, minimalistic, geometric forms, constructivism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/d07feccabcadfd3310464bedba858bd1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Cubism + NAME_ZH: 立体主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Cubism Art, {prompt}, flat geometric forms, cubism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/aa8313f6c3cb9cafb9a7ec07db78df1c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dadaism + NAME_ZH: 达达主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Dadaism Art, {prompt}, satirical, nonsensical, dadaism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/db27030369cb3ccb042b8aea6bf635e2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dark Fantasy + NAME_ZH: 黑暗幻想 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Dark Fantasy Art, {prompt}, dark, moody, dark fantasy style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, bright, sunny + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/c88b6e641c707afc0c8d278ba7e1ac19.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dark Moody Atmosphere + NAME_ZH: 暗色忧郁氛围 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Dark Moody Atmosphere, {prompt}, dramatic, mysterious, dark moody atmosphere + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, vibrant, colorful, bright + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/3da915da2f5cedaf243e57e08163f35b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: DMT Art Style + NAME_ZH: DMT艺术风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: DMT Art Style, {prompt}, bright colors, surreal visuals, swirling patterns, DMT art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/d4a823d2bfa912ca4bb56d96f722f08f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Doodle Art + NAME_ZH: 涂鸦艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Doodle Art Style, {prompt}, drawing, freeform, swirling patterns, doodle art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/8e1e21745c149b9634d3ce96fc7d505f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Double Exposure + NAME_ZH: 双重曝光 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Double Exposure Style, {prompt}, double image ghost effect, image combination, double exposure style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/efd7aea4af1c4ede99fdfac17350e264.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dripping Paint Splatter Art + NAME_ZH: 滴漆溅画艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Dripping Paint Splatter Art, {prompt}, dramatic, paint drips, splatters, dripping paint + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/69fd81f5983107acc3d334af62915851.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Expressionism + NAME_ZH: 表现主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Expressionism Art Style, {prompt}, movement, contrast, emotional, exaggerated forms, expressionism art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/3dfa862bd1c80cec237e4a5717cea2bd.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Faded Polaroid Photo + NAME_ZH: 褪色的宝丽来照片 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Faded Polaroid Photo, {prompt}, analog, old faded photo, old polaroid + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, vibrant, colorful + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/f152edb4b3ca6248758b48115258ddfa.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fauvism + NAME_ZH: 野兽派 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Fauvism Art, {prompt}, painterly, bold colors, textured brushwork, fauvism art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/0506b350cadcf8fca42da764cd6fd5bf.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Flat 2D Art + NAME_ZH: 扁平2D艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Flat 2D Art, {prompt}, simple flat color, 2-dimensional, Flat 2D Art Style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, 3D, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/940cfd34155634cf051e1b2942cca426.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fortnite Art Style + NAME_ZH: 堡垒之夜艺术风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Fortnite Art Style, {prompt}, 3D cartoon, colorful, Fortnite Art Style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/156f8d943ff6d283f7a34f265daaa46c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Futurism + NAME_ZH: 未来主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Futurism Art Style, {prompt}, dynamic, dramatic, Futurism Art Style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/855283cc2ab6283b627ef32d06a1ae0f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Glitchcore + NAME_ZH: 故障核心 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Glitchcore Art Style, {prompt}, dynamic, dramatic, distorted, vibrant colors, glitchcore art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/9af62376402a85774179e82cf7e0dc59.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Glo-fi + NAME_ZH: 光环音乐风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Glo-fi Art Style, {prompt}, dynamic, dramatic, vibrant colors, glo-fi art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/275a6e2a3297cec57f9b5a4a17b0f749.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Googie Art Style + NAME_ZH: 古奇艺术风格 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Googie Art Style, {prompt}, dynamic, dramatic, 1950's futurism, bold boomerang angles, Googie art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/08ee77586d7bec3f6bad7d60cee3c540.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Graffiti Art + NAME_ZH: 涂鸦艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Graffiti Art Style, {prompt}, dynamic, dramatic, vibrant colors, graffiti art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/57b751b11564cb22cd49ef21f2004a5f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Harlem Renaissance Art + NAME_ZH: 哈莱姆文艺复兴艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Harlem Renaissance Art Style, {prompt}, dynamic, dramatic, 1920s African American culture, Harlem Renaissance art style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/d09ea3dadcd0a15d8fa247ee74a75e6b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: High Fashion + NAME_ZH: 高级时装 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: High Fashion, {prompt}, dynamic, dramatic, haute couture, elegant, ornate clothing, High Fashion + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/868f752bbb5ef992a0be36d7d13de3be.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Idyllic + NAME_ZH: 田园诗般的 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Idyllic, {prompt}, peaceful, happy, pleasant, happy, harmonious, picturesque, charming + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/55bab29eeb628e7a9ae018e45e7e24db.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Impressionism + NAME_ZH: 印象主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Impressionism, {prompt}, painterly, small brushstrokes, visible brushstrokes, impressionistic style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/0312b673dc6858a9864d7f45f0c5c1fc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Infographic Drawing + NAME_ZH: 信息图表绘制 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Infographic Drawing, {prompt}, diagram, infographic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/b09151f6e0883d26056b80fcc9d398bb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Ink Dripping Drawing + NAME_ZH: 墨水滴画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Ink Dripping Drawing, {prompt}, ink drawing, dripping ink + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, colorful, vibrant + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/5f09912a07e915250a96b2023db15821.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Japanese Ink Drawing + NAME_ZH: 日本墨画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Japanese Ink Drawing, {prompt}, ink drawing, inkwash, Japanese Ink Drawing + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, colorful, vibrant + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/633ad971ff30fe4717782fc6b5f92fda.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Knolling Photography + NAME_ZH: 秩序拍摄 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Knolling Photography, {prompt}, flat lay photography, object arrangment, knolling photography + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/89a205be3a276349ecddf0eeca43ed80.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Light Cheery Atmosphere + NAME_ZH: 轻快愉快的氛围 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Light Cheery Atmosphere, {prompt}, happy, joyful, cheerful, carefree, gleeful, lighthearted, pleasant atmosphere + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, monochromatic, dark, moody + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/0913ac9815f892411f8327a630f51ae4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Logo Design + NAME_ZH: 标志设计 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Logo Design, {prompt}, dynamic graphic art, vector art, minimalist, professional logo design + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/9aa040b0c60d289da9610c91ad9b7c7e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Luxurious Elegance + NAME_ZH: 奢华优雅 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Luxurious Elegance, {prompt}, extravagant, ornate, designer, opulent, picturesque, lavish + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/e796e84ed745150f0d4e28e0ac99b4cf.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Macro Photography + NAME_ZH: 微距摄影 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Macro Photography, {prompt}, close-up, macro 100mm, macro photography + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/92e8b84379828f38e3d01c7272f41b0b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Mandola Art + NAME_ZH: 曼陀罗艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Mandola art style, {prompt}, complex, circular design, mandola + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/dbf5ca944d9213c3181348666cf337ac.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Marker Drawing + NAME_ZH: 马克笔绘图 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Marker Drawing, {prompt}, bold marker lines, visibile paper texture, marker drawing + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photograph, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/c558745f7a4b77d7ca9a428d8874efe4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Medievalism + NAME_ZH: 中世纪主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Medievalism, {prompt}, inspired by The Middle Ages, medieval art, elaborate patterns and decoration, Medievalism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/26aa6244359a4fd87f6438a341057901.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Minimalism + NAME_ZH: 极简主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Minimalism, {prompt}, abstract, simple geometic shapes, hard edges, sleek contours, Minimalism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/dce92a90da6299339cf8e9ebc6596ea2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Baroque + NAME_ZH: 新巴洛克 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Neo-Baroque, {prompt}, ornate and elaborate, dynaimc, Neo-Baroque + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/9b6cd8751b18c65b259769b44cfac351.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Byzantine + NAME_ZH: 新拜占庭 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Neo-Byzantine, {prompt}, grand decorative religious style, Orthodox Christian inspired, Neo-Byzantine + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/99c67768869b546bf527ef0b1735c0d5.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Futurism + NAME_ZH: 新未来主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Neo-Futurism, {prompt}, high-tech, curves, spirals, flowing lines, idealistic future, Neo-Futurism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/bada1534f7a60187f584febcc92f40d1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Impressionism + NAME_ZH: 新印象主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Neo-Impressionism, {prompt}, tiny dabs of color, Pointillism, painterly, Neo-Impressionism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photograph, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/6bafeac67ce2679b64a86ee1023b53c9.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neo-Rococo + NAME_ZH: 新洛可可 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Neo-Rococo, {prompt}, curved forms, naturalistic ornamentation, elaborate, decorative, gaudy, Neo-Rococo + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/9ab0ad2b88e03933ea479357ff1e4435.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Neoclassicism + NAME_ZH: 新古典主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Neoclassicism, {prompt}, ancient Rome and Greece inspired, idealic, sober colors, Neoclassicism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/83a4e3a2ca577400b05a81b5b2b8650e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Op Art + NAME_ZH: 视觉艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Op Art, {prompt}, optical illusion, abstract, geometric pattern, impression of movement, Op Art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/5f11132803dff2de5213293b91d407d7.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Ornate and Intricate + NAME_ZH: 华丽复杂 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Ornate and Intricate, {prompt}, decorative, highly detailed, elaborate, ornate, intricate + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/24b895dca946c8765ad9fa38f720f671.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Pencil Sketch Drawing + NAME_ZH: 铅笔素描 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Pencil Sketch Drawing, {prompt}, black and white drawing, graphite drawing + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/a9056e1eac85e5e4fe96a93917d4cce4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Pop Art 2 + NAME_ZH: 流行艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Pop Art, {prompt}, vivid colors, flat color, 2D, strong lines, Pop Art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/83c4c06c70a48da6558ff970ece247b6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Rococo + NAME_ZH: 洛可可 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Rococo, {prompt}, flamboyant, pastel colors, curved lines, elaborate detail, Rococo + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/4850170f410e10bc833b7d00324dff18.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Silhouette Art + NAME_ZH: 剪影艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Silhouette Art, {prompt}, high contrast, well defined, Silhouette Art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/568777f447fc02510b618152726d5002.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Simple Vector Art + NAME_ZH: 简单矢量艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Simple Vector Art, {prompt}, 2D flat, simple shapes, minimalistic, professional graphic, flat color, high contrast, Simple Vector Art + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, 3D, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/24d2ab1fd175bf4e9ef3a8327651dd4b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Sketchup + NAME_ZH: 草图大师 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Sketchup, {prompt}, CAD, professional design, Sketchup + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photo, photograph + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/337dca7ac49cf7820c85ede096ebde9c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Steampunk 2 + NAME_ZH: 蒸汽朋克 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Steampunk, {prompt}, retrofuturistic science fantasy, steam-powered tech, vintage industry, gears, neo-victorian, steampunk + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/07d7b27cd73f2d43684003563511c15b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Surrealism + NAME_ZH: 超现实主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Surrealism, {prompt}, expressive, dramatic, organic lines and forms, dreamlike and mysterious, Surrealism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/38bae70377b323d1a5f5756d7e04886d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Suprematism + NAME_ZH: 至上主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Suprematism, {prompt}, abstract, limited color palette, geometric forms, Suprematism + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/c48fbd8cedee84d06b4d875d566f1bb8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Terragen + NAME_ZH: 地形生成 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Terragen, {prompt}, beautiful massive landscape, epic scenery, Terragen + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/8974cd8e0f38fb7aac117cf0983fc36d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Tranquil Relaxing Atmosphere + NAME_ZH: 宁静放松的氛围 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Tranquil Relaxing Atmosphere, {prompt}, calming style, soothing colors, peaceful, idealic, Tranquil Relaxing Atmosphere + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, oversaturated + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/69170d8443a67be4210af8d5558779c2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Sticker Designs + NAME_ZH: 贴纸设计 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Vector Art Stickers, {prompt}, professional vector design, sticker designs, Sticker Sheet + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/2d1e9867058db2c57f2fe47530de3243.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Vibrant Rim Light + NAME_ZH: 生动的边缘光 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Vibrant Rim Light, {prompt}, bright rim light, high contrast, bold edge light + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/bb08936ca184daba2b30b4a9efb308f2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Volumetric Lighting + NAME_ZH: 体积光照明 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Volumetric Lighting, {prompt}, light depth, dramatic atmospheric lighting, Volumetric Lighting + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/bbad7964a2ae70b66c72804273f11e74.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Watercolor 2 + NAME_ZH: 水彩 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Watercolor style painting, {prompt}, visible paper texture, colorwash, watercolor + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/8859d532ae5901cc8457d6118fb9b7da.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Whimsical and Playful + NAME_ZH: 异想天开和俏皮 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + PROMPT: Whimsical and Playful, {prompt}, imaginative, fantastical, bight colors, stylized, happy, Whimsical and Playful + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, drab, boring, moody + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/af2267f1942e870be957c37cd73d4359.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Enhance + NAME_ZH: 焦点增强 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD2.1 + PROMPT: { + "prompt": null +} + + NEGATIVE_PROMPT: (worst quality, low quality, normal quality, lowres, low details, oversaturated, undersaturated, overexposed, underexposed, grayscale, bw, bad photo, bad photography, bad art:1.4), (watermark, signature, text font, username, error, logo, words, letters, digits, autograph, trademark, name:1.2), (blur, blurry, grainy), morbid, ugly, asymmetrical, mutated malformed, mutilated, poorly lit, bad shadow, draft, cropped, out of frame, cut off, censored, jpeg artifacts, out of focus, glitch, duplicate, (airbrushed, cartoon, anime, semi-realistic, cgi, render, blender, digital art, manga, amateur:1.3), (3D ,3D Game, 3D Game Scene, 3D Character:1.1), (bad hands, bad anatomy, bad body, bad face, bad teeth, bad arms, bad legs, deformities:1.3) + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/e501823a21bbda56592055c9613c1dbb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Sharp + NAME_ZH: 焦点锐化 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD2.1 + PROMPT: cinematic still {prompt} . emotional, harmonious, vignette, 4k epic detailed, shot on kodak, 35mm photo, sharp focus, high budget, cinemascope, moody, epic, gorgeous, film grain, grainy + NEGATIVE_PROMPT: anime, cartoon, graphic, (blur, blurry, bokeh), text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/393fb7aab57992a1c3af7cbad01c1001.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Masterpiece + NAME_ZH: 焦点杰作 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD2.1 + PROMPT: (masterpiece), (best quality), (ultra-detailed), {prompt}, illustration, disheveled hair, detailed eyes, perfect composition, moist skin, intricate details, earrings, by wlop + NEGATIVE_PROMPT: longbody, lowres, bad anatomy, bad hands, missing fingers, pubic hair,extra digit, fewer digits, cropped, worst quality, low quality + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/9e27c3d1475dacae0ee45cea783aaaf5.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Photograph + NAME_ZH: 焦点摄影 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD2.1 + PROMPT: photograph {prompt}, 50mm . cinematic 4k epic detailed 4k epic detailed photograph shot on kodak detailed cinematic hbo dark moody, 35mm photo, grainy, vignette, vintage, Kodachrome, Lomography, stained, highly detailed, found footage + NEGATIVE_PROMPT: Brad Pitt, bokeh, depth of field, blurry, cropped, regular face, saturated, contrast, deformed iris, deformed pupils, semi-realistic, cgi, 3d, render, sketch, cartoon, drawing, anime, text, cropped, out of frame, worst quality, low quality, jpeg artifacts, ugly, duplicate, morbid, mutilated, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, dehydrated, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/8b2ea41ec15bf1a16d6a837d46dbc2ac.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Negative + NAME_ZH: 焦点底片 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD2.1 + PROMPT: { + "prompt": null +} + + NEGATIVE_PROMPT: deformed, bad anatomy, disfigured, poorly drawn face, mutated, extra limb, ugly, poorly drawn hands, missing limb, floating limbs, disconnected limbs, disconnected head, malformed hands, long neck, mutated hands and fingers, bad hands, missing fingers, cropped, worst quality, low quality, mutation, poorly drawn, huge calf, bad hands, fused hand, missing hand, disappearing arms, disappearing thigh, disappearing calf, disappearing legs, missing fingers, fused fingers, abnormal eye proportion, Abnormal hands, abnormal legs, abnormal feet, abnormal fingers, drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly, anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/daaec2962291137532189b8a31012532.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Fooocus Cinematic + NAME_ZH: 焦点电影 + DESCRIPTION: + SOURCE: fooocus + BASE_MODEL: SD2.1 + PROMPT: cinematic still {prompt} . emotional, harmonious, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy + NEGATIVE_PROMPT: anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/adc4d52aa5b0afca0593a475ddc9d055.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-cinematic-dynamic + NAME_ZH: MRE电影动态 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: epic cinematic shot of dynamic {prompt} in motion. main subject of high budget action movie. raw photo, motion blur. best quality, high resolution + NEGATIVE_PROMPT: static, still, motionless, sluggish. drawing, painting, illustration, rendered. low budget. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/bd2470068e09d9f1b7d0a690c879b3ce.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-spontaneous-picture + NAME_ZH: MRE自发图片 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: spontaneous picture of {prompt}, taken by talented amateur. best quality, high resolution. magical moment, natural look. simple but good looking + NEGATIVE_PROMPT: overthinked. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/19ad6082cee5516ce330641b515467ef.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-artistic-vision + NAME_ZH: MRE艺术视觉 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: powerful artistic vision of {prompt}. breathtaking masterpiece made by great artist. best quality, high resolution + NEGATIVE_PROMPT: insignificant, flawed, made by bad artist. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/95af94e50bcb91ae8fd2914a3bf13f1e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-dark-dream + NAME_ZH: MRE黑暗梦境 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: dark and unsettling dream showing {prompt}. best quality, high resolution. created by genius but depressed mad artist. grim beauty + NEGATIVE_PROMPT: naive, cheerful. comfortable, casual, boring, cliche. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/572c8c26cc20ac0ee66684e3c5ee4e8c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-gloomy-art + NAME_ZH: MRE忧郁艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: astonishing gloomy art made mainly of shadows and lighting, forming {prompt}. masterful usage of lighting, shadows and chiaroscuro. made by black-hearted artist, drawing from darkness. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/66cbdf819e930f7580bd66a41bde7dfe.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-bad-dream + NAME_ZH: MRE恶梦 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: picture from really bad dream about terrifying {prompt}, true horror. bone-chilling vision. mad world that shouldn't exist. best quality, high resolution + NEGATIVE_PROMPT: nice dream, pleasant experience. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/b92b2bbfc400db9204fe8249354132b4.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-underground + NAME_ZH: MRE地下 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: uncanny caliginous vision of {prompt}, created by remarkable underground artist. best quality, high resolution. raw and brutal art, careless but impressive style. inspired by darkness and chaos + NEGATIVE_PROMPT: photography, mainstream, civilized. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/8d46eca558d791a1f2b41b0ed7bba4d2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-surreal-painting + NAME_ZH: MRE超现实绘画 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: surreal painting representing strange vision of {prompt}. harmonious madness, synergy with chance. unique artstyle, mindbending art, magical surrealism. best quality, high resolution + NEGATIVE_PROMPT: photography, illustration, drawing. realistic, possible. logical, sane. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/58858425832b10d233f7887af4a2022f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-dynamic-illustration + NAME_ZH: MRE动态插画 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: insanely dynamic illustration of {prompt}. best quality, high resolution. crazy artstyle, careless brushstrokes, emotional and fun + NEGATIVE_PROMPT: photography, realistic. static, still, slow, boring. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/8bf9861d4d3fadcdb98ceec88a941582.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-undead-art + NAME_ZH: MRE不死艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: long forgotten art created by undead artist illustrating {prompt}, tribute to the death and decay. miserable art of the damned. wretched and decaying world. best quality, high resolution + NEGATIVE_PROMPT: alive, playful, living. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/fada50979ca180006eba9a45a00f3675.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-elemental-art + NAME_ZH: MRE元素艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: art illustrating insane amounts of raging elemental energy turning into {prompt}, avatar of elements. magical surrealism, wizardry. best quality, high resolution + NEGATIVE_PROMPT: photography, realistic, real. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/5895d78cf58c1ca05178991f37cc48ff.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-space-art + NAME_ZH: MRE太空艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: winner of inter-galactic art contest illustrating {prompt}, symbol of the interstellar singularity. best quality, high resolution. artstyle previously unseen in the whole galaxy + NEGATIVE_PROMPT: created by human race, low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/e9815495587895a21d970728474c8be6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-ancient-illustration + NAME_ZH: MRE古代插画 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: sublime ancient illustration of {prompt}, predating human civilization. crude and simple, but also surprisingly beautiful artwork, made by genius primeval artist. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/151e07c17a89ebaf7688905ea0199862.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-brave-art + NAME_ZH: MRE勇敢艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: brave, shocking, and brutally true art showing {prompt}. inspired by courage and unlimited creativity. truth found in chaos. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/1a068f2728327d21ebb99285c2ce1370.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-heroic-fantasy + NAME_ZH: MRE英雄幻想 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: heroic fantasy painting of {prompt}, in the dangerous fantasy world. airbrush over oil on canvas. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/78d05472067e0b86c8270fa5476fcb8e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-dark-cyberpunk + NAME_ZH: MRE黑暗赛博朋克 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: dark cyberpunk illustration of brutal {prompt} in a world without hope, ruled by ruthless criminal corporations. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/a9f50e3162958fd783872d6955ad7d0b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-lyrical-geometry + NAME_ZH: MRE抒情几何 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: geometric and lyrical abstraction painting presenting {prompt}. oil on metal. best quality, high resolution + NEGATIVE_PROMPT: photography, realistic, drawing, rendered. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/dfabd41d3042ced804bc97ae35e3a7cb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-sumi-e-symbolic + NAME_ZH: MRE墨绘象征 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: big long brushstrokes of deep black sumi-e turning into symbolic painting of {prompt}. master level raw art. best quality, high resolution + NEGATIVE_PROMPT: photography, rendered. low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/695b1ba687544eaeec9fb5f871917aeb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-sumi-e-detailed + NAME_ZH: MRE墨绘精细 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: highly detailed black sumi-e painting of {prompt}. in-depth study of perfection, created by a master. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/16eb95e180385b88794e368b28da1812.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-manga + NAME_ZH: MRE漫画 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: manga artwork presenting {prompt}. created by japanese manga artist. highly emotional. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/ebec631bf467937f82d05958ae59f9dc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-anime + NAME_ZH: MRE动漫 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: anime artwork illustrating {prompt}. created by japanese anime studio. highly emotional. best quality, high resolution + NEGATIVE_PROMPT: low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/a08149bc8e50f6bc65c0010d4cd416f8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-comic + NAME_ZH: MRE漫画书 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + PROMPT: breathtaking illustration from adult comic book presenting {prompt}. fabulous artwork. best quality, high resolution + NEGATIVE_PROMPT: deformed, ugly, low quality, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/48c65cebf1fa4284d7b8feb619412e65.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-3d-model + NAME_ZH: SAI三维模型 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: professional 3d model {prompt} . octane render, highly detailed, volumetric, dramatic lighting + NEGATIVE_PROMPT: ugly, deformed, noisy, low poly, blurry, painting + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/c1a765ac089fdfb3c1d11b33c75d2afd.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-analog film + NAME_ZH: SAI模拟胶片 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: analog film photo {prompt} . faded film, desaturated, 35mm photo, grainy, vignette, vintage, Kodachrome, Lomography, stained, highly detailed, found footage + NEGATIVE_PROMPT: painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/3c46d19957efd7fb78f4ab2bdada5468.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-anime + NAME_ZH: SAI动漫 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: anime artwork {prompt} . anime style, key visual, vibrant, studio anime, highly detailed + NEGATIVE_PROMPT: photo, deformed, black and white, realism, disfigured, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/c030e72561eda96abcf738f1370d36ff.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-cinematic + NAME_ZH: SAI电影 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: cinematic film still {prompt} . shallow depth of field, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy + NEGATIVE_PROMPT: anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/d9161c0d5cbf2133b2bfc1021c0c5e2a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-comic book + NAME_ZH: SAI漫画书 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: comic {prompt} . graphic illustration, comic art, graphic novel art, vibrant, highly detailed + NEGATIVE_PROMPT: photograph, deformed, glitch, noisy, realistic, stock photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/6759ecb831037367e64c4b36d802be87.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-craft clay + NAME_ZH: SAI手工粘土 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: play-doh style {prompt} . sculpture, clay art, centered composition, Claymation + NEGATIVE_PROMPT: sloppy, messy, grainy, highly detailed, ultra textured, photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/8fc51113f725f27326c4398a7457cd6d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-digital art + NAME_ZH: SAI数字艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: concept art {prompt} . digital artwork, illustrative, painterly, matte painting, highly detailed + NEGATIVE_PROMPT: photo, photorealistic, realism, ugly + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/d29adb44458700c4a45ee6edaa04bfb6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-enhance + NAME_ZH: SAI增强 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: breathtaking {prompt} . award-winning, professional, highly detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, distorted, grainy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/2be0de541ff65f8da80ddc24a65c98d8.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-fantasy art + NAME_ZH: SAI幻想艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: ethereal fantasy concept art of {prompt} . magnificent, celestial, ethereal, painterly, epic, majestic, magical, fantasy art, cover art, dreamy + NEGATIVE_PROMPT: photographic, realistic, realism, 35mm film, dslr, cropped, frame, text, deformed, glitch, noise, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, sloppy, duplicate, mutated, black and white + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/a6f8d92afcd5803dfb2ebecbc92091b6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-isometric + NAME_ZH: SAI等距 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: isometric style {prompt} . vibrant, beautiful, crisp, detailed, ultra detailed, intricate + NEGATIVE_PROMPT: deformed, mutated, ugly, disfigured, blur, blurry, noise, noisy, realistic, photographic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/d4e3fcbbfd7b1323bd89decf5d7b0006.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-line art + NAME_ZH: SAI线条艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: line art drawing {prompt} . professional, sleek, modern, minimalist, graphic, line art, vector graphics + NEGATIVE_PROMPT: anime, photorealistic, 35mm film, deformed, glitch, blurry, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, mutated, realism, realistic, impressionism, expressionism, oil, acrylic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/034a51b0dd34b018be8859bf45b4f7ed.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-lowpoly + NAME_ZH: SAI低多边形 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: low-poly style {prompt} . low-poly game art, polygon mesh, jagged, blocky, wireframe edges, centered composition + NEGATIVE_PROMPT: noisy, sloppy, messy, grainy, highly detailed, ultra textured, photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/76b9913e9fa5704b6d30adbde9e1f70f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-neonpunk + NAME_ZH: SAI霓虹朋克 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: neonpunk style {prompt} . cyberpunk, vaporwave, neon, vibes, vibrant, stunningly beautiful, crisp, detailed, sleek, ultramodern, magenta highlights, dark purple shadows, high contrast, cinematic, ultra detailed, intricate, professional + NEGATIVE_PROMPT: painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/7e9ed25bb34008beb5f417df63c4b2fe.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-origami + NAME_ZH: SAI折纸 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: origami style {prompt} . paper art, pleated paper, folded, origami art, pleats, cut and fold, centered composition + NEGATIVE_PROMPT: noisy, sloppy, messy, grainy, highly detailed, ultra textured, photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/924f46a8f276011a0953d7988e90ee25.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-photographic + NAME_ZH: SAI摄影 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: cinematic photo {prompt} . 35mm photograph, film, bokeh, professional, 4k, highly detailed + NEGATIVE_PROMPT: drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/d6a2d8f3d37cc21c20c5dfc13d000b67.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-pixel art + NAME_ZH: SAI像素艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: pixel-art {prompt} . low-res, blocky, pixel art style, 8-bit graphics + NEGATIVE_PROMPT: sloppy, messy, blurry, noisy, highly detailed, ultra textured, photo, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/a5ab89c0960be8c1216e65c98d92ae4a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-texture + NAME_ZH: SAI质地 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + PROMPT: texture {prompt} top down close-up + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/ebfeab574283fff2ac096e348a585e6d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-advertising + NAME_ZH: 广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: advertising poster style {prompt} . Professional, modern, product-focused, commercial, eye-catching, highly detailed + NEGATIVE_PROMPT: noisy, blurry, amateurish, sloppy, unattractive + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/1aa26a16126e2756bf4bf3fda29baa12.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-automotive + NAME_ZH: 汽车广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: automotive advertisement style {prompt} . sleek, dynamic, professional, commercial, vehicle-focused, high-resolution, highly detailed + NEGATIVE_PROMPT: noisy, blurry, unattractive, sloppy, unprofessional + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/ddc833b36ca23c85a4f6e7bf0088d081.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-corporate + NAME_ZH: 企业广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: corporate branding style {prompt} . professional, clean, modern, sleek, minimalist, business-oriented, highly detailed + NEGATIVE_PROMPT: noisy, blurry, grungy, sloppy, cluttered, disorganized + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/df97fa45c7842296c138aca4057db272.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-fashion editorial + NAME_ZH: 时尚编辑 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: fashion editorial style {prompt} . high fashion, trendy, stylish, editorial, magazine style, professional, highly detailed + NEGATIVE_PROMPT: outdated, blurry, noisy, unattractive, sloppy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/89259be723479cd0b81546b715bea04d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-food photography + NAME_ZH: 食品摄影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: food photography style {prompt} . appetizing, professional, culinary, high-resolution, commercial, highly detailed + NEGATIVE_PROMPT: unappetizing, sloppy, unprofessional, noisy, blurry + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/33acc98f8615940c8cebbac8ce5297b2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-gourmet food photography + NAME_ZH: 美食摄影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: gourmet food photo of {prompt} . soft natural lighting, macro details, vibrant colors, fresh ingredients, glistening textures, bokeh background, styled plating, wooden tabletop, garnished, tantalizing, editorial quality + NEGATIVE_PROMPT: cartoon, anime, sketch, grayscale, dull, overexposed, cluttered, messy plate, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/897bbd3f1d232de122796266f3845b50.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-luxury + NAME_ZH: 奢华广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: luxury product style {prompt} . elegant, sophisticated, high-end, luxurious, professional, highly detailed + NEGATIVE_PROMPT: cheap, noisy, blurry, unattractive, amateurish + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/5b33ecc84dc5ff285a0f2e69f43162cb.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-real estate + NAME_ZH: 房地产广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: real estate photography style {prompt} . professional, inviting, well-lit, high-resolution, property-focused, commercial, highly detailed + NEGATIVE_PROMPT: dark, blurry, unappealing, noisy, unprofessional + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/1b99b7bcd0476144d80d066e747d8dfc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: ads-retail + NAME_ZH: 零售广告 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: retail packaging style {prompt} . vibrant, enticing, commercial, product-focused, eye-catching, professional, highly detailed + NEGATIVE_PROMPT: noisy, blurry, amateurish, sloppy, unattractive + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/0029e46ef36380dde2084257108f8a6f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-abstract + NAME_ZH: 抽象艺术风格 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: abstract style {prompt} . non-representational, colors and shapes, expression of feelings, imaginative, highly detailed + NEGATIVE_PROMPT: realistic, photographic, figurative, concrete + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/8c401cb0a6ea288230222c4985e78667.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-abstract expressionism + NAME_ZH: 抽象表现主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: abstract expressionist painting {prompt} . energetic brushwork, bold colors, abstract forms, expressive, emotional + NEGATIVE_PROMPT: realistic, photorealistic, low contrast, plain, simple, monochrome + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/9df6635149c576b65d911c2e4cc6a86b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-art deco + NAME_ZH: 艺术装饰风格 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: art deco style {prompt} . geometric shapes, bold colors, luxurious, elegant, decorative, symmetrical, ornate, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, modernist, minimalist + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/82fff8a25de8075777caf14cb3eb5650.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-art nouveau + NAME_ZH: 新艺术风格 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: art nouveau style {prompt} . elegant, decorative, curvilinear forms, nature-inspired, ornate, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, modernist, minimalist + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/84075c5c0cb4b7a2541c6fbca9835cfd.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-constructivist + NAME_ZH: 构成主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: constructivist style {prompt} . geometric shapes, bold colors, dynamic composition, propaganda art style + NEGATIVE_PROMPT: realistic, photorealistic, low contrast, plain, simple, abstract expressionism + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/2a634ad0c89ecefbbea4ce5bcab3d5e5.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-cubist + NAME_ZH: 立体主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: cubist artwork {prompt} . geometric shapes, abstract, innovative, revolutionary + NEGATIVE_PROMPT: anime, photorealistic, 35mm film, deformed, glitch, low contrast, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/2a3d797008c08e12b485d61624741ea6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-expressionist + NAME_ZH: 表现主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: expressionist {prompt} . raw, emotional, dynamic, distortion for emotional effect, vibrant, use of unusual colors, detailed + NEGATIVE_PROMPT: realism, symmetry, quiet, calm, photo + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/83914655659001716a1acede295289d0.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-graffiti + NAME_ZH: 涂鸦 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: graffiti style {prompt} . street art, vibrant, urban, detailed, tag, mural + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/f72a23c7623eb480737eb73c08bf8423.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-hyperrealism + NAME_ZH: 超现实主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: hyperrealistic art {prompt} . extremely high-resolution details, photographic, realism pushed to extreme, fine texture, incredibly lifelike + NEGATIVE_PROMPT: simplified, abstract, unrealistic, impressionistic, low resolution + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/db378d5a64a8e7ad1e29a4389bda5d1c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-impressionist + NAME_ZH: 印象主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: impressionist painting {prompt} . loose brushwork, vibrant color, light and shadow play, captures feeling over form + NEGATIVE_PROMPT: anime, photorealistic, 35mm film, deformed, glitch, low contrast, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/53b151aec4d5685dfc24511b6705b90e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-pointillism + NAME_ZH: 点彩主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: pointillism style {prompt} . composed entirely of small, distinct dots of color, vibrant, highly detailed + NEGATIVE_PROMPT: line drawing, smooth shading, large color fields, simplistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/23b137a409ee8a8c6ee160c1ddf0659f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-pop art + NAME_ZH: 波普艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: pop Art style {prompt} . bright colors, bold outlines, popular culture themes, ironic or kitsch + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, minimalist + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/bd4faf0e2b7dbc2d0eb21f3ebee97d3d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-psychedelic + NAME_ZH: 迷幻艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: psychedelic style {prompt} . vibrant colors, swirling patterns, abstract forms, surreal, trippy + NEGATIVE_PROMPT: monochrome, black and white, low contrast, realistic, photorealistic, plain, simple + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/7dc0131817f4c31517581dd4a811067b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-renaissance + NAME_ZH: 文艺复兴 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: renaissance style {prompt} . realistic, perspective, light and shadow, religious or mythological themes, highly detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, modernist, minimalist, abstract + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/69796484f61dc2e94d5853f5bbe27c05.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-steampunk + NAME_ZH: 蒸汽朋克 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: steampunk style {prompt} . antique, mechanical, brass and copper tones, gears, intricate, detailed + NEGATIVE_PROMPT: deformed, glitch, noisy, low contrast, anime, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/985005e28858b03c9500a6eb5bd9e201.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-surrealist + NAME_ZH: 超现实主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: surrealist art {prompt} . dreamlike, mysterious, provocative, symbolic, intricate, detailed + NEGATIVE_PROMPT: anime, photorealistic, realistic, deformed, glitch, noisy, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/892d19ec3c429b7148562796df0024db.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-typography + NAME_ZH: 排版艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: typographic art {prompt} . stylized, intricate, detailed, artistic, text-based + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/9adafe1bb169e1ee3f78ba2c1b1cf8d3.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: artstyle-watercolor + NAME_ZH: 水彩艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: watercolor painting {prompt} . vibrant, beautiful, painterly, detailed, textural, artistic + NEGATIVE_PROMPT: anime, photorealistic, 35mm film, deformed, glitch, low contrast, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/29ca23d7a0397e9beaa72e3b63d17551.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-biomechanical + NAME_ZH: 未来生物力学 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: biomechanical style {prompt} . blend of organic and mechanical elements, futuristic, cybernetic, detailed, intricate + NEGATIVE_PROMPT: natural, rustic, primitive, organic, simplistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/5987795487a3fa74469499ae53963d5d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-biomechanical cyberpunk + NAME_ZH: 未来生物力学赛博朋克 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: biomechanical cyberpunk {prompt} . cybernetics, human-machine fusion, dystopian, organic meets artificial, dark, intricate, highly detailed + NEGATIVE_PROMPT: natural, colorful, deformed, sketch, low contrast, watercolor + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/75b56d7cff9b3f011248b3092ae3b8d2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-cybernetic + NAME_ZH: 未来赛博 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: cybernetic style {prompt} . futuristic, technological, cybernetic enhancements, robotics, artificial intelligence themes + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, historical, medieval + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/47df6db04290f01aeee7381aaf12ec07.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-cybernetic robot + NAME_ZH: 未来机器人 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: cybernetic robot {prompt} . android, AI, machine, metal, wires, tech, futuristic, highly detailed + NEGATIVE_PROMPT: organic, natural, human, sketch, watercolor, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/6f18121b4ba22c8ba7834f404501fa4c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-cyberpunk cityscape + NAME_ZH: 未来赛博朋克城市景观 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: cyberpunk cityscape {prompt} . neon lights, dark alleys, skyscrapers, futuristic, vibrant colors, high contrast, highly detailed + NEGATIVE_PROMPT: natural, rural, deformed, low contrast, black and white, sketch, watercolor + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/5e4107dace2c9dd0217a9d1b18ae28f6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-futuristic + NAME_ZH: 未来主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: futuristic style {prompt} . sleek, modern, ultramodern, high tech, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, vintage, antique + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/8a61c0853ee4079bae96ad502a6ae840.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-retro cyberpunk + NAME_ZH: 未来复古赛博朋克 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: retro cyberpunk {prompt} . 80's inspired, synthwave, neon, vibrant, detailed, retro futurism + NEGATIVE_PROMPT: modern, desaturated, black and white, realism, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/460957bf9a07a58ddec08bf22d5b3698.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-retro futurism + NAME_ZH: 未来复古主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: retro-futuristic {prompt} . vintage sci-fi, 50s and 60s style, atomic age, vibrant, highly detailed + NEGATIVE_PROMPT: contemporary, realistic, rustic, primitive + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/0434a7b23a0f936db615d7a9b8e805f1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-sci-fi + NAME_ZH: 科幻未来主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: sci-fi style {prompt} . futuristic, technological, alien worlds, space themes, advanced civilizations + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, historical, medieval + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/7c3bde651f426273758b68a2805d0c8a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: futuristic-vaporwave + NAME_ZH: 未来波 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: vaporwave style {prompt} . retro aesthetic, cyberpunk, vibrant, neon colors, vintage 80s and 90s style, highly detailed + NEGATIVE_PROMPT: monochrome, muted colors, realism, rustic, minimalist, dark + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/1ebb0bf67ee3ef76288b4c0a2a65d557.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-bubble bobble + NAME_ZH: 游戏-泡泡龙 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: Bubble Bobble style {prompt} . 8-bit, cute, pixelated, fantasy, vibrant, reminiscent of Bubble Bobble game + NEGATIVE_PROMPT: realistic, modern, photorealistic, violent, horror + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/19257352df33228555cb350963d9432a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-cyberpunk game + NAME_ZH: 赛博朋克游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: cyberpunk game style {prompt} . neon, dystopian, futuristic, digital, vibrant, detailed, high contrast, reminiscent of cyberpunk genre video games + NEGATIVE_PROMPT: historical, natural, rustic, low detailed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/6165ef47bc859e3dd0e3399ba2264c2b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-fighting game + NAME_ZH: 格斗游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: fighting game style {prompt} . dynamic, vibrant, action-packed, detailed character design, reminiscent of fighting video games + NEGATIVE_PROMPT: peaceful, calm, minimalist, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/aebda69ec1097dc61966995956ae34cc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-gta + NAME_ZH: 侠盗猎车手游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: GTA-style artwork {prompt} . satirical, exaggerated, pop art style, vibrant colors, iconic characters, action-packed + NEGATIVE_PROMPT: realistic, black and white, low contrast, impressionist, cubist, noisy, blurry, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/edff7ba5fc983468e79e64beb838b829.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-mario + NAME_ZH: 马里奥游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: Super Mario style {prompt} . vibrant, cute, cartoony, fantasy, playful, reminiscent of Super Mario series + NEGATIVE_PROMPT: realistic, modern, horror, dystopian, violent + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/2a229f623ce89160d1f67620599dfc7c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-minecraft + NAME_ZH: 我的世界游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: Minecraft style {prompt} . blocky, pixelated, vibrant colors, recognizable characters and objects, game assets + NEGATIVE_PROMPT: smooth, realistic, detailed, photorealistic, noise, blurry, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/83e77332a9f234fd8c9cddd29e2ec3c7.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-pokemon + NAME_ZH: 宝可梦游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: Pokémon style {prompt} . vibrant, cute, anime, fantasy, reminiscent of Pokémon series + NEGATIVE_PROMPT: realistic, modern, horror, dystopian, violent + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/9bfe2805e6578875a8dfe2a0ea96c281.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-retro arcade + NAME_ZH: 复古街机 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: retro arcade style {prompt} . 8-bit, pixelated, vibrant, classic video game, old school gaming, reminiscent of 80s and 90s arcade games + NEGATIVE_PROMPT: modern, ultra-high resolution, photorealistic, 3D + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/76885e0b110f1fdf3eaee52fbaf27abf.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-retro game + NAME_ZH: 复古游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: retro game art {prompt} . 16-bit, vibrant colors, pixelated, nostalgic, charming, fun + NEGATIVE_PROMPT: realistic, photorealistic, 35mm film, deformed, glitch, low contrast, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/61fbae41c50f56e24dcf20fe3612d456.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-rpg fantasy game + NAME_ZH: 角色扮演幻想游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: role-playing game (RPG) style fantasy {prompt} . detailed, vibrant, immersive, reminiscent of high fantasy RPG games + NEGATIVE_PROMPT: sci-fi, modern, urban, futuristic, low detailed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/34797baf58e32b4e1a37753fe9dcff5c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-strategy game + NAME_ZH: 策略游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: strategy game style {prompt} . overhead view, detailed map, units, reminiscent of real-time strategy video games + NEGATIVE_PROMPT: first-person view, modern, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/0d276527d22510a1b5f8f74eac2790df.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-streetfighter + NAME_ZH: 街头霸王游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: Street Fighter style {prompt} . vibrant, dynamic, arcade, 2D fighting game, highly detailed, reminiscent of Street Fighter series + NEGATIVE_PROMPT: 3D, realistic, modern, photorealistic, turn-based strategy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/f5927fc2b8d4a8212242bd97adcbdfa1.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: game-zelda + NAME_ZH: 塞尔达传说游戏 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: Legend of Zelda style {prompt} . vibrant, fantasy, detailed, epic, heroic, reminiscent of The Legend of Zelda series + NEGATIVE_PROMPT: sci-fi, modern, realistic, horror + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/4f9eadddbc196268258089b8cc4e5c5c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-architectural + NAME_ZH: 建筑 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: architectural style {prompt} . clean lines, geometric shapes, minimalist, modern, architectural drawing, highly detailed + NEGATIVE_PROMPT: curved lines, ornate, baroque, abstract, grunge + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/488545e9fc9417d62961f42d578547d2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-disco + NAME_ZH: 迪斯科 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: disco-themed {prompt} . vibrant, groovy, retro 70s style, shiny disco balls, neon lights, dance floor, highly detailed + NEGATIVE_PROMPT: minimalist, rustic, monochrome, contemporary, simplistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/784b0ac35e0c0fdb2df21a95d5ca1c55.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-dreamscape + NAME_ZH: 梦境 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: dreamscape {prompt} . surreal, ethereal, dreamy, mysterious, fantasy, highly detailed + NEGATIVE_PROMPT: realistic, concrete, ordinary, mundane + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/2bf77804b5bf352c4e97475b1e8eb29e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-dystopian + NAME_ZH: 反乌托邦 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: dystopian style {prompt} . bleak, post-apocalyptic, somber, dramatic, highly detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, cheerful, optimistic, vibrant, colorful + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/065db0385e126192cbd27e22ca4f154c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-fairy tale + NAME_ZH: 童话故事 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: fairy tale {prompt} . magical, fantastical, enchanting, storybook style, highly detailed + NEGATIVE_PROMPT: realistic, modern, ordinary, mundane + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/578dfe65d9f03e83c95820d4c45cd396.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-gothic + NAME_ZH: 哥特 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: gothic style {prompt} . dark, mysterious, haunting, dramatic, ornate, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, cheerful, optimistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/332a1f8cd655b724cb48bc5c91b764fc.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-grunge + NAME_ZH: 垃圾摇滚 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: grunge style {prompt} . textured, distressed, vintage, edgy, punk rock vibe, dirty, noisy + NEGATIVE_PROMPT: smooth, clean, minimalist, sleek, modern, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/0ccb4c03c6d983b9f6d05ba383f9d690.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-horror + NAME_ZH: 恐怖 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: horror-themed {prompt} . eerie, unsettling, dark, spooky, suspenseful, grim, highly detailed + NEGATIVE_PROMPT: cheerful, bright, vibrant, light-hearted, cute + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/fdca4780d099a39dc50e4553622fba72.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-kawaii + NAME_ZH: 卡哇伊 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: kawaii style {prompt} . cute, adorable, brightly colored, cheerful, anime influence, highly detailed + NEGATIVE_PROMPT: dark, scary, realistic, monochrome, abstract + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/99dab4185e7337189d8959878bfa308b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-lovecraftian + NAME_ZH: 克苏鲁神话 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: lovecraftian horror {prompt} . eldritch, cosmic horror, unknown, mysterious, surreal, highly detailed + NEGATIVE_PROMPT: light-hearted, mundane, familiar, simplistic, realistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/b7c9d084ed62c1c2e1ea080ad95af61e.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-macabre + NAME_ZH: 恐怖的 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: macabre style {prompt} . dark, gothic, grim, haunting, highly detailed + NEGATIVE_PROMPT: bright, cheerful, light-hearted, cartoonish, cute + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/fd7cf2315b27b0434b909020414e1173.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-manga + NAME_ZH: 漫画 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: manga style {prompt} . vibrant, high-energy, detailed, iconic, Japanese comic style + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, Western comic style + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/531aac90b321d39221ba7cf70a97b232.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-metropolis + NAME_ZH: 大都市 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: metropolis-themed {prompt} . urban, cityscape, skyscrapers, modern, futuristic, highly detailed + NEGATIVE_PROMPT: rural, natural, rustic, historical, simple + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/eaad79fe3d7160cec6e0656fc3b02d3c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-minimalist + NAME_ZH: 极简主义 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: minimalist style {prompt} . simple, clean, uncluttered, modern, elegant + NEGATIVE_PROMPT: ornate, complicated, highly detailed, cluttered, disordered, messy, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/e85dd1ccc7f22bdac054d74ba58521b2.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-monochrome + NAME_ZH: 单色 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: monochrome {prompt} . black and white, contrast, tone, texture, detailed + NEGATIVE_PROMPT: colorful, vibrant, noisy, blurry, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/cc793ada6b47561f4b63aa66dcd282ac.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-nautical + NAME_ZH: 航海 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: nautical-themed {prompt} . sea, ocean, ships, maritime, beach, marine life, highly detailed + NEGATIVE_PROMPT: landlocked, desert, mountains, urban, rustic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/3d9f6528180670804a2c5e85c7665c42.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-space + NAME_ZH: 太空 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: space-themed {prompt} . cosmic, celestial, stars, galaxies, nebulas, planets, science fiction, highly detailed + NEGATIVE_PROMPT: earthly, mundane, ground-based, realism + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/6f5742d23b43fc99cc01c8b68518df7c.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-stained glass + NAME_ZH: 彩色玻璃 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: stained glass style {prompt} . vibrant, beautiful, translucent, intricate, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/ab0512ced9ed572075c49ad4f9f9a45d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-techwear fashion + NAME_ZH: 科技服饰 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: techwear fashion {prompt} . futuristic, cyberpunk, urban, tactical, sleek, dark, highly detailed + NEGATIVE_PROMPT: vintage, rural, colorful, low contrast, realism, sketch, watercolor + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/652a6bdb1b36860041222a458c7915d0.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-tribal + NAME_ZH: 部落 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: tribal style {prompt} . indigenous, ethnic, traditional patterns, bold, natural colors, highly detailed + NEGATIVE_PROMPT: modern, futuristic, minimalist, pastel + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/1ecdaf153ece5e16250b87020b7a209b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: misc-zentangle + NAME_ZH: 禅绕画 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: zentangle {prompt} . intricate, abstract, monochrome, patterns, meditative, highly detailed + NEGATIVE_PROMPT: colorful, representative, simplistic, large fields of color + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/80f3488cdb69f0ff13d83a4feac4499d.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-collage + NAME_ZH: 纸艺拼贴 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: collage style {prompt} . mixed media, layered, textural, detailed, artistic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/c9bbdaba28358faf1a8c1df44b3de950.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-flat papercut + NAME_ZH: 平面剪纸 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: flat papercut style {prompt} . silhouette, clean cuts, paper, sharp edges, minimalist, color block + NEGATIVE_PROMPT: 3D, high detail, noise, grainy, blurry, painting, drawing, photo, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/1bffcd9a4086b29c367b8301f26eed3b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-kirigami + NAME_ZH: 剪纸 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: kirigami representation of {prompt} . 3D, paper folding, paper cutting, Japanese, intricate, symmetrical, precision, clean lines + NEGATIVE_PROMPT: painting, drawing, 2D, noisy, blurry, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/2e5f95977b97b2a6248924e118a23076.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-paper mache + NAME_ZH: 纸浆塑型 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: paper mache representation of {prompt} . 3D, sculptural, textured, handmade, vibrant, fun + NEGATIVE_PROMPT: 2D, flat, photo, sketch, digital art, deformed, noisy, blurry + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/68441f668fcf7a51db5fc9b9d4d45ce7.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-paper quilling + NAME_ZH: 纸卷艺术 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: paper quilling art of {prompt} . intricate, delicate, curling, rolling, shaping, coiling, loops, 3D, dimensional, ornamental + NEGATIVE_PROMPT: photo, painting, drawing, 2D, flat, deformed, noisy, blurry + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/8c0504eb14341b66796612c46bb3748b.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-papercut collage + NAME_ZH: 剪纸拼贴 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: papercut collage of {prompt} . mixed media, textured paper, overlapping, asymmetrical, abstract, vibrant + NEGATIVE_PROMPT: photo, 3D, realistic, drawing, painting, high detail, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/217e7c8b905b63c63c94bd6ff8fe3477.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-papercut shadow box + NAME_ZH: 剪纸影箱 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: 3D papercut shadow box of {prompt} . layered, dimensional, depth, silhouette, shadow, papercut, handmade, high contrast + NEGATIVE_PROMPT: painting, drawing, photo, 2D, flat, high detail, blurry, noisy, disfigured + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/2af0d61de1b17a5a5257f512549f9616.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-stacked papercut + NAME_ZH: 堆叠剪纸 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: stacked papercut art of {prompt} . 3D, layered, dimensional, depth, precision cut, stacked layers, papercut, high contrast + NEGATIVE_PROMPT: 2D, flat, noisy, blurry, painting, drawing, photo, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/62618e32e90539827e0eb279a6ea170a.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: papercraft-thick layered papercut + NAME_ZH: 厚层剪纸 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: thick layered papercut art of {prompt} . deep 3D, volumetric, dimensional, depth, thick paper, high stack, heavy texture, tangible layers + NEGATIVE_PROMPT: 2D, flat, thin paper, low stack, smooth texture, painting, drawing, photo, deformed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/17008c40a6be8d41d3921ee88bac27ad.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-alien + NAME_ZH: 异形 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: alien-themed {prompt} . extraterrestrial, cosmic, otherworldly, mysterious, sci-fi, highly detailed + NEGATIVE_PROMPT: earthly, mundane, common, realistic, simple + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/eae6043dee2b2d94cd9a22cb044db8b3.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-film noir + NAME_ZH: 黑色电影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: film noir style {prompt} . monochrome, high contrast, dramatic shadows, 1940s style, mysterious, cinematic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, vibrant, colorful + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/0b3629be5ebb7cda463877a1993a0298.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-glamour + NAME_ZH: 魅力 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: glamorous photo {prompt} . high fashion, luxurious, extravagant, stylish, sensual, opulent, elegance, stunning beauty, professional, high contrast, detailed + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, distorted, grainy, sketch, low contrast, dull, plain, modest + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/f85dc6aa5d7f7d6d3663f2270e276796.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-hdr + NAME_ZH: 高动态范围 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: HDR photo of {prompt} . High dynamic range, vivid, rich details, clear shadows and highlights, realistic, intense, enhanced contrast, highly detailed + NEGATIVE_PROMPT: flat, low contrast, oversaturated, underexposed, overexposed, blurred, noisy + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/269a98b284ae1345b0e5ac1f85c33179.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-iphone photographic + NAME_ZH: iPhone摄影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: iphone photo {prompt} . large depth of field, deep depth of field, highly detailed + NEGATIVE_PROMPT: drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly, shallow depth of field, bokeh + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/48c556a6b3c3a533847b80b031cd4962.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-long exposure + NAME_ZH: 长曝光 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: long exposure photo of {prompt} . Blurred motion, streaks of light, surreal, dreamy, ghosting effect, highly detailed + NEGATIVE_PROMPT: static, noisy, deformed, shaky, abrupt, flat, low contrast + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/fda88c3fc43ea8cc04ce9b5c0261627f.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-neon noir + NAME_ZH: 霓虹黑色 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: neon noir {prompt} . cyberpunk, dark, rainy streets, neon signs, high contrast, low light, vibrant, highly detailed + NEGATIVE_PROMPT: bright, sunny, daytime, low contrast, black and white, sketch, watercolor + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/8a5b71434592771e064af4b9017b59d6.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-silhouette + NAME_ZH: 剪影 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: silhouette style {prompt} . high contrast, minimalistic, black and white, stark, dramatic + NEGATIVE_PROMPT: ugly, deformed, noisy, blurry, low contrast, color, realism, photorealistic + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/1892a37e66d33cdd9b713aaab6b8c597.png + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: photo-tilt-shift + NAME_ZH: 倾斜移位 + DESCRIPTION: + SOURCE: twri + BASE_MODEL: SD2.1 + PROMPT: tilt-shift photo of {prompt} . selective focus, miniature effect, blurred background, highly detailed, vibrant, perspective control + NEGATIVE_PROMPT: blurry, noisy, deformed, flat, low contrast, unrealistic, oversaturated, underexposed + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/d058a157de848a5c03d9a3e1e0e560a2.png + PROMPT_EXAMPLE: a boy wearing green jacket diff --git a/scepter/methods/studio/extensions/tuners/official_tuners.yaml b/scepter/methods/studio/extensions/tuners/official_tuners.yaml new file mode 100644 index 0000000..99ee032 --- /dev/null +++ b/scepter/methods/studio/extensions/tuners/official_tuners.yaml @@ -0,0 +1,721 @@ +TUNERS: + - + NAME: Caricature + NAME_ZH: 夸张漫画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/894f40ed44b37c3372e6a22b8ae577a4.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/Caricature + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Caricature + NAME_ZH: 夸张漫画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/894f40ed44b37c3372e6a22b8ae577a4.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/Caricature + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Caricature + NAME_ZH: 夸张漫画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/894f40ed44b37c3372e6a22b8ae577a4.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/Caricature + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Color Field Painting + NAME_ZH: 色域绘画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/80e5b4075c572c04cbb4e48c37b8366b.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/ColorFieldPainting + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Color Field Painting + NAME_ZH: 色域绘画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/80e5b4075c572c04cbb4e48c37b8366b.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/ColorFieldPainting + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Color Field Painting + NAME_ZH: 色域绘画 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/80e5b4075c572c04cbb4e48c37b8366b.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/ColorFieldPainting + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Colored Pencil Art + NAME_ZH: 彩色铅笔艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/9ae235d7f1a7c2a4edab52a5e9f9cbae.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/ColoredPencilArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Colored Pencil Art + NAME_ZH: 彩色铅笔艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/9ae235d7f1a7c2a4edab52a5e9f9cbae.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/ColoredPencilArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Colored Pencil Art + NAME_ZH: 彩色铅笔艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/9ae235d7f1a7c2a4edab52a5e9f9cbae.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/ColoredPencilArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dark Moody Atmosphere + NAME_ZH: 暗色忧郁氛围 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/3da915da2f5cedaf243e57e08163f35b.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/DarkMoodyAtmosphere + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dark Moody Atmosphere + NAME_ZH: 暗色忧郁氛围 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/3da915da2f5cedaf243e57e08163f35b.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/DarkMoodyAtmosphere + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dark Moody Atmosphere + NAME_ZH: 暗色忧郁氛围 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/3da915da2f5cedaf243e57e08163f35b.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/DarkMoodyAtmosphere + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dripping Paint Splatter Art + NAME_ZH: 滴漆溅画艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/69fd81f5983107acc3d334af62915851.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/DrippingPaintSplatterArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dripping Paint Splatter Art + NAME_ZH: 滴漆溅画艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/69fd81f5983107acc3d334af62915851.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/DrippingPaintSplatterArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Dripping Paint Splatter Art + NAME_ZH: 滴漆溅画艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/69fd81f5983107acc3d334af62915851.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/DrippingPaintSplatterArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Faded Polaroid Photo + NAME_ZH: 褪色的宝丽来照片 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/f152edb4b3ca6248758b48115258ddfa.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/FadedPolaroidPhoto + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Faded Polaroid Photo + NAME_ZH: 褪色的宝丽来照片 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/f152edb4b3ca6248758b48115258ddfa.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/FadedPolaroidPhoto + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Faded Polaroid Photo + NAME_ZH: 褪色的宝丽来照片 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/f152edb4b3ca6248758b48115258ddfa.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/FadedPolaroidPhoto + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Flat 2D Art + NAME_ZH: 扁平2D艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/940cfd34155634cf051e1b2942cca426.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/Flat2DArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Flat 2D Art + NAME_ZH: 扁平2D艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/940cfd34155634cf051e1b2942cca426.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/Flat2DArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Flat 2D Art + NAME_ZH: 扁平2D艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/940cfd34155634cf051e1b2942cca426.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/Flat2DArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Graffiti Art + NAME_ZH: 涂鸦艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/57b751b11564cb22cd49ef21f2004a5f.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/GraffitiArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Graffiti Art + NAME_ZH: 涂鸦艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/57b751b11564cb22cd49ef21f2004a5f.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/GraffitiArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Graffiti Art + NAME_ZH: 涂鸦艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/57b751b11564cb22cd49ef21f2004a5f.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/GraffitiArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Impressionism + NAME_ZH: 印象主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/0312b673dc6858a9864d7f45f0c5c1fc.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/Impressionism + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Impressionism + NAME_ZH: 印象主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/0312b673dc6858a9864d7f45f0c5c1fc.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/Impressionism + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Impressionism + NAME_ZH: 印象主义 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/0312b673dc6858a9864d7f45f0c5c1fc.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/Impressionism + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Logo Design + NAME_ZH: 标志设计 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/9aa040b0c60d289da9610c91ad9b7c7e.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/LogoDesign + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Logo Design + NAME_ZH: 标志设计 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/9aa040b0c60d289da9610c91ad9b7c7e.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/LogoDesign + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Logo Design + NAME_ZH: 标志设计 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/9aa040b0c60d289da9610c91ad9b7c7e.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/LogoDesign + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Pencil Sketch Drawing + NAME_ZH: 铅笔素描 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/a9056e1eac85e5e4fe96a93917d4cce4.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/PencilSketchDrawing + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Pencil Sketch Drawing + NAME_ZH: 铅笔素描 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/a9056e1eac85e5e4fe96a93917d4cce4.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/PencilSketchDrawing + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Pencil Sketch Drawing + NAME_ZH: 铅笔素描 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/a9056e1eac85e5e4fe96a93917d4cce4.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/PencilSketchDrawing + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Silhouette Art + NAME_ZH: 剪影艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/568777f447fc02510b618152726d5002.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/SilhouetteArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Silhouette Art + NAME_ZH: 剪影艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/568777f447fc02510b618152726d5002.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/SilhouetteArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Silhouette Art + NAME_ZH: 剪影艺术 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/568777f447fc02510b618152726d5002.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/SilhouetteArt + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Steampunk 2 + NAME_ZH: 蒸汽朋克 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/07d7b27cd73f2d43684003563511c15b.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/Steampunk2 + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Steampunk 2 + NAME_ZH: 蒸汽朋克 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/07d7b27cd73f2d43684003563511c15b.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/Steampunk2 + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Steampunk 2 + NAME_ZH: 蒸汽朋克 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/07d7b27cd73f2d43684003563511c15b.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/Steampunk2 + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Sticker Designs + NAME_ZH: 贴纸设计 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/2d1e9867058db2c57f2fe47530de3243.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/StickerDesigns + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Sticker Designs + NAME_ZH: 贴纸设计 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/2d1e9867058db2c57f2fe47530de3243.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/StickerDesigns + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Sticker Designs + NAME_ZH: 贴纸设计 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/2d1e9867058db2c57f2fe47530de3243.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/StickerDesigns + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Watercolor 2 + NAME_ZH: 水彩 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/8859d532ae5901cc8457d6118fb9b7da.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/Watercolor2 + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Watercolor 2 + NAME_ZH: 水彩 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/8859d532ae5901cc8457d6118fb9b7da.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/Watercolor2 + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: Watercolor 2 + NAME_ZH: 水彩 + DESCRIPTION: + SOURCE: diva + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/8859d532ae5901cc8457d6118fb9b7da.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/Watercolor2 + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-elemental-art + NAME_ZH: MRE元素艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/5895d78cf58c1ca05178991f37cc48ff.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/mre-elemental-art + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-elemental-art + NAME_ZH: MRE元素艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/5895d78cf58c1ca05178991f37cc48ff.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/mre-elemental-art + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-elemental-art + NAME_ZH: MRE元素艺术 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/5895d78cf58c1ca05178991f37cc48ff.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/mre-elemental-art + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-anime + NAME_ZH: MRE动漫 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/a08149bc8e50f6bc65c0010d4cd416f8.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/mre-anime + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-anime + NAME_ZH: MRE动漫 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/a08149bc8e50f6bc65c0010d4cd416f8.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/mre-anime + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-anime + NAME_ZH: MRE动漫 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/a08149bc8e50f6bc65c0010d4cd416f8.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/mre-anime + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-comic + NAME_ZH: MRE漫画书 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/48c65cebf1fa4284d7b8feb619412e65.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/mre-comic + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-comic + NAME_ZH: MRE漫画书 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/48c65cebf1fa4284d7b8feb619412e65.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/mre-comic + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: mre-comic + NAME_ZH: MRE漫画书 + DESCRIPTION: + SOURCE: mre + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/48c65cebf1fa4284d7b8feb619412e65.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/mre-comic + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-craft clay + NAME_ZH: SAI手工粘土 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/8fc51113f725f27326c4398a7457cd6d.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/sai-craftclay + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-craft clay + NAME_ZH: SAI手工粘土 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/8fc51113f725f27326c4398a7457cd6d.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/sai-craftclay + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-craft clay + NAME_ZH: SAI手工粘土 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/8fc51113f725f27326c4398a7457cd6d.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/sai-craftclay + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-fantasy art + NAME_ZH: SAI幻想艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/a6f8d92afcd5803dfb2ebecbc92091b6.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/sai-fantasyart + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-fantasy art + NAME_ZH: SAI幻想艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/a6f8d92afcd5803dfb2ebecbc92091b6.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/sai-fantasyart + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-fantasy art + NAME_ZH: SAI幻想艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/a6f8d92afcd5803dfb2ebecbc92091b6.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/sai-fantasyart + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-line art + NAME_ZH: SAI线条艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/034a51b0dd34b018be8859bf45b4f7ed.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/sai-lineart + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-line art + NAME_ZH: SAI线条艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/034a51b0dd34b018be8859bf45b4f7ed.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/sai-lineart + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-line art + NAME_ZH: SAI线条艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/034a51b0dd34b018be8859bf45b4f7ed.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/sai-lineart + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-neonpunk + NAME_ZH: SAI霓虹朋克 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/7e9ed25bb34008beb5f417df63c4b2fe.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/sai-neonpunk + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-neonpunk + NAME_ZH: SAI霓虹朋克 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/7e9ed25bb34008beb5f417df63c4b2fe.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/sai-neonpunk + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-neonpunk + NAME_ZH: SAI霓虹朋克 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/7e9ed25bb34008beb5f417df63c4b2fe.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/sai-neonpunk + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-origami + NAME_ZH: SAI折纸 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/924f46a8f276011a0953d7988e90ee25.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/sai-origami + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-origami + NAME_ZH: SAI折纸 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/924f46a8f276011a0953d7988e90ee25.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/sai-origami + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-origami + NAME_ZH: SAI折纸 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/924f46a8f276011a0953d7988e90ee25.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/sai-origami + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-pixel art + NAME_ZH: SAI像素艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD_XL1.0 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD_XL1.0/a5ab89c0960be8c1216e65c98d92ae4a.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD_XL1.0/sai-pixelart + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-pixel art + NAME_ZH: SAI像素艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD2.1 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD2.1/a5ab89c0960be8c1216e65c98d92ae4a.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD2.1/sai-pixelart + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket + - + NAME: sai-pixel art + NAME_ZH: SAI像素艺术 + DESCRIPTION: + SOURCE: sai + BASE_MODEL: SD1.5 + IMAGE_PATH: ms://damo/scepter@mantra_images/SD1.5/a5ab89c0960be8c1216e65c98d92ae4a.png + MODEL_PATH: ms://damo/scepter_scedit@tuners_model/SD1.5/sai-pixelart + TUNER_TYPE: SwiftSCE + PROMPT_EXAMPLE: a boy wearing green jacket diff --git a/scepter/methods/studio/home/home.yaml b/scepter/methods/studio/home/home.yaml new file mode 100644 index 0000000..e760d92 --- /dev/null +++ b/scepter/methods/studio/home/home.yaml @@ -0,0 +1,95 @@ +WORK_DIR: home +FILE_SYSTEM: + - + NAME: LocalFs + AUTO_CLEAN: False +DESC_INFO: + ZH_INFO: | +

基本介绍

+

+ + + + +
+ +

SCEPTER Studio是基于开源基模型和自研微调编辑算法构建的生成定制和编辑工具箱,提供围绕生成、微调、编辑、数据处理等一系列的工具和插件。

+

+

+ EN_INFO: | +

Introduction

+

+ + + + +
+ +

SCEPTER Studio is a customized generation and editing toolkit built on the open-source base models and proprietary fine-tuning editing algorithms, offering a range of tools and plugins centered around generation, fine-tuning, editing, and data processing.

+

+

+GUIDE_INFO: + ZH_INFO: | +

用户指南

+ + + +
+
+ +
训练与推理演示
+
+
+ + EN_INFO: | +

User Guide

+ + + +
+
+ +
Train & Inference Video
+
+
+ \ No newline at end of file diff --git a/scepter/methods/studio/inference/inference.yaml b/scepter/methods/studio/inference/inference.yaml new file mode 100644 index 0000000..33a78b3 --- /dev/null +++ b/scepter/methods/studio/inference/inference.yaml @@ -0,0 +1,117 @@ +WORK_DIR: "inference" +DIFFUSION_PARAS: + SAMPLE: + VALUES: ['ddim', 'euler', 'euler_ancestral', 'heun', 'dpm2', + 'dpm2_ancestral', 'dpmpp_2m', 'dpmpp_sde', 'dpmpp_2m_sde', 'dpmpp_2s_ancestral', + 'dpm2_karras', 'dpm2_ancestral_karras', 'dpmpp_2s_ancestral_karras', 'dpmpp_2m_karras', + 'dpmpp_sde_karras', 'dpmpp_2m_sde_karras'] + DEFAULT: 'dpmpp_2s_ancestral' + NEGATIVE_PROMPT: + DEFAULT: + PROMPT_PREFIX: + DEFAULT: + SAMPLES: + MIN: 1 + MAX: 4 + DEFAULT: 1 + SAMPLE_STEPS: + MIN: 1 + MAX: 100 + DEFAULT: 30 + GUIDE_SCALE: + MIN: 0 + MAX: 10 + DEFAULT: 5.0 + GUIDE_RESCALE: + MIN: 0 + MAX: 1.0 + DEFAULT: 0.5 + DISCRETIZATION: + VALUES: ["trailing", "leading", "linspace"] + DEFAULT: "linspace" + REFINE_SAMPLERS: + VALUES: [ 'ddim', 'euler', 'euler_ancestral', 'heun', 'dpm2', + 'dpm2_ancestral', 'dpmpp_2m', 'dpmpp_sde', 'dpmpp_2m_sde', 'dpmpp_2s_ancestral', + 'dpm2_karras', 'dpm2_ancestral_karras', 'dpmpp_2s_ancestral_karras', 'dpmpp_2m_karras', + 'dpmpp_sde_karras', 'dpmpp_2m_sde_karras' ] + DEFAULT: 'dpmpp_2s_ancestral' + REFINE_SAMPLE_STEPS: + MIN: 0 + MAX: 100 + DEFAULT: 30 + REFINE_GUIDE_SCALE: + MIN: 0 + MAX: 10 + DEFAULT: 5.0 + REFINE_GUIDE_RESCALE: + MIN: 0 + MAX: 1.0 + DEFAULT: 0.5 + REFINE_DISCRETIZATION: + VALUES: [ "trailing", "leading", "linspace" ] + DEFAULT: "linspace" + AESTHETIC_SCORE: + MIN: 0.0 + MAX: 10.0 + DEFAULT: 6.0 + NEGATIVE_AESTHETIC_SCORE: + MIN: 0.0 + MAX: 10.0 + DEFAULT: 2.5 + REFINE_STRENGTH: + MIN: 0 + MAX: 1.0 + DEFAULT: 0.15 + RESOLUTIONS: + VALUES: [[704, 1408], [704, 1344], [768, 1344], + [720, 1280], + [768, 1280], [832, 1216], [832, 1152], + [896, 1152], [896, 1088], [960, 1088], + [960, 1024], [1024, 1024], [1024, 960], + [1088, 960], [1088, 896], [1152, 896], + [1152, 832], [1216, 832], [1280, 720], + [1280, 768], + [1344, 768], [1344, 704], [1408, 704], + [1472, 704], [1536, 640], [1600, 640], + [1664, 576], [1728, 576]] + DEFAULT: [1024, 1024] +EXTENSION_PARAS: + MANTRA_BOOK: scepter/methods/studio/extensions/mantra_book/mantra_book.yaml + OFFICIAL_TUNERS: scepter/methods/studio/extensions/tuners/official_tuners.yaml + OFFICIAL_CONTROLLERS: scepter/methods/studio/extensions/controllers/official_controllers.yaml +CONTROLABLE_ANNOTATORS: + - + NAME: "CannyAnnotator" + LOW_THRESHOLD: 100 + HIGH_THRESHOLD: 200 + TYPE: Canny + IS_DEFAULT: True + - + NAME: "HedAnnotator" + PRETRAINED_MODEL: "ms://damo/scepter_scedit@annotator/ckpts/ControlNetHED.pth" + TYPE: Hed + IS_DEFAULT: False + - + NAME: "OpenposeAnnotator" + BODY_MODEL_PATH: "ms://damo/scepter_scedit@annotator/ckpts/body_pose_model.pth" + HAND_MODEL_PATH: "ms://damo/scepter_scedit@annotator/ckpts/hand_pose_model.pth" + TYPE: Openpose + IS_DEFAULT: False + - + NAME: "MidasDetector" + PRETRAINED_MODEL: "ms://damo/scepter_scedit@annotator/ckpts/dpt_hybrid-midas-501f0c75.pt" + A: 6.2 + BG_TH: 0.1 + TYPE: Midas + IS_DEFAULT: False + - + NAME: "ColorAnnotator" + TYPE: Color + IS_DEFAULT: False + - + NAME: "MLSDdetector" + PRETRAINED_MODEL: "ms://damo/scepter_scedit@annotator/ckpts/mlsd_large_512_fp32.pth" + THR_V: 0.1 + THR_D: 0.1 + TYPE: MLSD + IS_DEFAULT: False diff --git a/scepter/methods/studio/inference/sdxl/sdxl1.0_pro.yaml b/scepter/methods/studio/inference/sdxl/sdxl1.0_pro.yaml new file mode 100644 index 0000000..ef45d41 --- /dev/null +++ b/scepter/methods/studio/inference/sdxl/sdxl1.0_pro.yaml @@ -0,0 +1,242 @@ +NAME: SD_XL1.0 +IS_DEFAULT: True +DEFAULT_PARAS: + PARAS: + RESOLUTIONS: [[1024, 1024]] + INPUT: + IMAGE: + ORIGINAL_SIZE_AS_TUPLE: [1024, 1024] + TARGET_SIZE_AS_TUPLE: [1024, 1024] + AESTHETIC_SCORE: 6.0 + NEGATIVE_AESTHETIC_SCORE: 2.5 + PROMPT: "" + NEGATIVE_PROMPT: "" + PROMPT_PREFIX: "" + CROP_COORDS_TOP_LEFT: [0, 0] + SAMPLE: ddim + SAMPLE_STEPS: 50 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 + DISCRETIZATION: trailing + REFINE_SAMPLE: ddim + REFINE_GUIDE_SCALE: 7.5 + REFINE_GUIDE_RESCALE: 0.5 + REFINE_DISCRETIZATION: trailing + OUTPUT: + LATENT: + BEFORE_REFINE_IMAGES: + IMAGES: + SEED: + MODULES_PARAS: + FIRST_STAGE_MODEL: + FUNCTION: + - + NAME: encode + DTYPE: float32 + INPUT: ["IMAGE"] + - + NAME: decode + DTYPE: float32 + INPUT: ["LATENT"] + PARAS: + # SCALE_FACTOR DESCRIPTION: The vae embeding scale. TYPE: float default: 0.18215 + SCALE_FACTOR: 0.13025 + SIZE_FACTOR: 8 + DIFFUSION_MODEL: + FUNCTION: + - + NAME: forward + DTYPE: float16 + INPUT: ["SAMPLE_STEPS", "SAMPLE", "GUIDE_SCALE", "GUIDE_RESCALE", "DISCRETIZATION"] + COND_STAGE_MODEL: + FUNCTION: + - + NAME: encode + DTYPE: float16 + INPUT: ["ORIGINAL_SIZE_AS_TUPLE", "CROP_COORDS_TOP_LEFT", "PROMPT", "NEGATIVE_PROMPT"] + REFINER_MODEL: + FUNCTION: + - + NAME: forward + DTYPE: float16 + INPUT: ["SAMPLE_STEPS", "REFINE_SAMPLE", "REFINE_GUIDE_SCALE", "REFINE_GUIDE_RESCALE", "REFINE_DISCRETIZATION"] + REFINER_COND_MODEL: + FUNCTION: + - + NAME: encode + DTYPE: float16 + INPUT: ["ORIGINAL_SIZE_AS_TUPLE", "AESTHETIC_SCORE", "NEGATIVE_AESTHETIC_SCORE", "CROP_COORDS_TOP_LEFT", "PROMPT", "NEGATIVE_PROMPT"] + +MODEL: + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-xl-base-1.0@sd_xl_base_1.0.safetensors + # SCHEDULE_ARGS DESCRIPTION: TYPE: default: '' + SCHEDULE: + PARAMETERIZATION: "eps" + TIMESTEPS: 1000 + ZERO_TERMINAL_SNR: False + SCHEDULE_ARGS: + # NAME DESCRIPTION: TYPE: default: '' + NAME: "scaled_linear" + BETA_MIN: 0.00085 + BETA_MAX: 0.0120 + # DIFFUSION_MODEL DESCRIPTION: TYPE: default: '' + DIFFUSION_MODEL: + # NAME DESCRIPTION: TYPE: default: 'DiffusionUNetXL' + NAME: DiffusionUNetXL + # PRETRAINED_MODEL DESCRIPTION: Whole model's pretrained model path. TYPE: NoneType default: None + PRETRAINED_MODEL: + # IN_CHANNELS DESCRIPTION: Unet channels for input, considering the input image's channels. TYPE: int default: 4 + IN_CHANNELS: 4 + # OUT_CHANNELS DESCRIPTION: Unet channels for output, considering the input image's channels. TYPE: int default: 4 + OUT_CHANNELS: 4 + # NUM_RES_BLOCKS DESCRIPTION: The blocks's number of res. TYPE: int default: 2 + NUM_RES_BLOCKS: 2 + # MODEL_CHANNELS DESCRIPTION: base channel count for the model. TYPE: int default: 320 + MODEL_CHANNELS: 320 + # ATTENTION_RESOLUTIONS DESCRIPTION: A collection of downsample rates at which attention will take place. May be a set, list, or tuple. For example, if this contains 4, then at 4x downsampling, attentio will be used. TYPE: list default: [4, 2] + ATTENTION_RESOLUTIONS: [4, 2] + # DROPOUT DESCRIPTION: The dropout rate. TYPE: int default: 0 + DROPOUT: 0 + # CHANNEL_MULT DESCRIPTION: channel multiplier for each level of the UNet. TYPE: list default: [1, 2, 4] + CHANNEL_MULT: [1, 2, 4] + # CONV_RESAMPLE DESCRIPTION: Use conv to resample when downsample. TYPE: bool default: True + CONV_RESAMPLE: True + # DIMS DESCRIPTION: The Conv dims which 2 represent Conv2D. TYPE: int default: 2 + DIMS: 2 + # NUM_CLASSES DESCRIPTION: The class num for class guided setting, also can be set as continuous. TYPE: str default: 'sequential' + NUM_CLASSES: sequential + # USE_CHECKPOINT DESCRIPTION: Use gradient checkpointing to reduce memory usage. TYPE: bool default: False + USE_CHECKPOINT: False + # NUM_HEADS DESCRIPTION: The number of attention heads in each attention layer. TYPE: int default: -1 + NUM_HEADS: -1 + # NUM_HEADS_CHANNELS DESCRIPTION: If specified, ignore num_heads and instead use a fixed channel width per attention head. TYPE: int default: 64 + NUM_HEADS_CHANNELS: 64 + # USE_SCALE_SHIFT_NORM DESCRIPTION: The scale and shift for the outnorm of RESBLOCK, use a FiLM-like conditioning mechanism. TYPE: bool default: False + USE_SCALE_SHIFT_NORM: False + # RESBLOCK_UPDOWN DESCRIPTION: Use residual blocks for up/downsampling, if False use Conv. TYPE: bool default: False + RESBLOCK_UPDOWN: False + # USE_NEW_ATTENTION_ORDER DESCRIPTION: Whether use new attention(qkv before split heads or not) or not. TYPE: bool default: True + USE_NEW_ATTENTION_ORDER: True + # USE_SPATIAL_TRANSFORMER DESCRIPTION: Custom transformer which support the context, if context_dim is not None, the parameter must set True TYPE: bool default: True + USE_SPATIAL_TRANSFORMER: True + # TRANSFORMER_DEPTH DESCRIPTION: Custom transformer's depth, valid when USE_SPATIAL_TRANSFORMER is True. TYPE: list default: [1, 2, 10] + TRANSFORMER_DEPTH: [1, 2, 10] + # TRANSFORMER_DEPTH_MIDDLE DESCRIPTION: Custom transformer's depth of middle block, If set None, use TRANSFORMER_DEPTH last value. TYPE: NoneType default: None + # TRANSFORMER_DEPTH_MIDDLE: None + # CONTEXT_DIM DESCRIPTION: Custom context info, if set, USE_SPATIAL_TRANSFORMER also set True. TYPE: int default: 2048 + CONTEXT_DIM: 2048 + # DISABLE_SELF_ATTENTIONS DESCRIPTION: Whether disable the self-attentions on some level, should be a list, [False, True, ...] TYPE: NoneType default: None + # DISABLE_SELF_ATTENTIONS: None + # NUM_ATTENTION_BLOCKS DESCRIPTION: The number of attention blocks for attention layer. TYPE: NoneType default: None + # NUM_ATTENTION_BLOCKS: None + # DISABLE_MIDDLE_SELF_ATTN DESCRIPTION: Whether disable the self-attentions in middle blocks. TYPE: bool default: False + DISABLE_MIDDLE_SELF_ATTN: False + # USE_LINEAR_IN_TRANSFORMER DESCRIPTION: Custom transformer's parameter, valid when USE_SPATIAL_TRANSFORMER is True. TYPE: bool default: True + USE_LINEAR_IN_TRANSFORMER: True + # ADM_IN_CHANNELS DESCRIPTION: Used when num_classes == 'sequential' or 'timestep'. TYPE: int default: 2816 + ADM_IN_CHANNELS: 2816 + # USE_SENTENCE_EMB DESCRIPTION: Used sentence emb or not, default False. TYPE: bool default: False + USE_SENTENCE_EMB: False + # USE_WORD_MAPPING DESCRIPTION: Used word mapping or not, default False. TYPE: bool default: False + USE_WORD_MAPPING: False + # FIRST_STAGE_MODEL DESCRIPTION: TYPE: default: '' + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + IGNORE_KEYS: [ ] + BATCH_SIZE: 1 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # COND_STAGE_MODEL DESCRIPTION: TYPE: default: '' + COND_STAGE_MODEL: + # NAME DESCRIPTION: TYPE: default: 'GeneralConditioner' + NAME: GeneralConditioner + USE_GRAD: False + # EMBEDDERS DESCRIPTION: TYPE: default: '' + EMBEDDERS: + - + # NAME DESCRIPTION: TYPE: default: 'FrozenCLIPEmbedder' + NAME: FrozenCLIPEmbedder + # PRETRAINED_MODEL DESCRIPTION: TYPE: str default: '' + PRETRAINED_MODEL: ms://AI-ModelScope/clip-vit-large-patch14 + TOKENIZER_PATH: ms://AI-ModelScope/clip-vit-large-patch14 + # MAX_LENGTH DESCRIPTION: TYPE: int default: 77 + MAX_LENGTH: 77 + # FREEZE DESCRIPTION: TYPE: bool default: True + FREEZE: True + # LAYER DESCRIPTION: TYPE: str default: 'last' + LAYER: hidden + # LAYER_IDX DESCRIPTION: TYPE: NoneType default: None + LAYER_IDX: 11 + # USE_FINAL_LAYER_NORM DESCRIPTION: TYPE: bool default: False + USE_FINAL_LAYER_NORM: False + UCG_RATE: 0.0 + INPUT_KEYS: ["prompt"] + LEGACY_UCG_VALUE: + - + # NAME DESCRIPTION: TYPE: default: 'FrozenOpenCLIPEmbedder2' + NAME: FrozenOpenCLIPEmbedder2 + # ARCH DESCRIPTION: TYPE: str default: 'ViT-H-14' + ARCH: ViT-bigG-14 + # MAX_LENGTH DESCRIPTION: TYPE: int default: 77 + MAX_LENGTH: 77 + # FREEZE DESCRIPTION: TYPE: bool default: True + FREEZE: True + # ALWAYS_RETURN_POOLED DESCRIPTION: Whether always return pooled results or not ,default False. TYPE: bool default: False + ALWAYS_RETURN_POOLED: True + # LEGACY DESCRIPTION: Whether use legacy returnd feature or not ,default True. TYPE: bool default: True + LEGACY: False + # LAYER DESCRIPTION: TYPE: str default: 'last' + LAYER: penultimate + UCG_RATE: 0.0 + INPUT_KEYS: ["prompt"] + LEGACY_UCG_VALUE: + - + # NAME DESCRIPTION: TYPE: default: 'ConcatTimestepEmbedderND' + NAME: ConcatTimestepEmbedderND + # OUT_DIM DESCRIPTION: Output dim TYPE: int default: 256 + OUT_DIM: 256 + UCG_RATE: 0.0 + INPUT_KEYS: ["original_size_as_tuple"] + LEGACY_UCG_VALUE: + - + # NAME DESCRIPTION: TYPE: default: 'ConcatTimestepEmbedderND' + NAME: ConcatTimestepEmbedderND + # OUT_DIM DESCRIPTION: Output dim TYPE: int default: 256 + OUT_DIM: 256 + UCG_RATE: 0.0 + INPUT_KEYS: ["crop_coords_top_left"] + LEGACY_UCG_VALUE: + - + # NAME DESCRIPTION: TYPE: default: 'ConcatTimestepEmbedderND' + NAME: ConcatTimestepEmbedderND + # OUT_DIM DESCRIPTION: Output dim TYPE: int default: 256 + OUT_DIM: 256 + UCG_RATE: 0.0 + INPUT_KEYS: ["target_size_as_tuple"] + LEGACY_UCG_VALUE: diff --git a/scepter/methods/studio/inference/stable_diffusion/sd15_pro.yaml b/scepter/methods/studio/inference/stable_diffusion/sd15_pro.yaml new file mode 100644 index 0000000..d817eb5 --- /dev/null +++ b/scepter/methods/studio/inference/stable_diffusion/sd15_pro.yaml @@ -0,0 +1,126 @@ +NAME: SD1.5 +IS_DEFAULT: False +DEFAULT_PARAS: + PARAS: + RESOLUTIONS: [[512, 512]] + INPUT: + IMAGE: + PROMPT: "" + NEGATIVE_PROMPT: "" + TARGET_SIZE_AS_TUPLE: [512, 512] + PROMPT_PREFIX: "" + SAMPLE: ddim + SAMPLE_STEPS: 50 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 + DISCRETIZATION: trailing + OUTPUT: + LATENT: + IMAGES: + SEED: + MODULES_PARAS: + FIRST_STAGE_MODEL: + FUNCTION: + - + NAME: encode + DTYPE: float16 + INPUT: ["IMAGE"] + - + NAME: decode + DTYPE: float16 + INPUT: ["LATENT"] + PARAS: + # SCALE_FACTOR DESCRIPTION: The vae embeding scale. TYPE: float default: 0.18215 + SCALE_FACTOR: 0.18215 + SIZE_FACTOR: 8 + DIFFUSION_MODEL: + FUNCTION: + - + NAME: forward + DTYPE: float16 + INPUT: ["SAMPLE_STEPS", "SAMPLE", "GUIDE_SCALE", "GUIDE_RESCALE", "DISCRETIZATION"] + COND_STAGE_MODEL: + FUNCTION: + - + NAME: encode_text + DTYPE: float16 + INPUT: ["PROMPT", "NEGATIVE_PROMPT"] + +MODEL: + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-v1-5@v1-5-pruned-emaonly.safetensors + SCHEDULE: + PARAMETERIZATION: "eps" + TIMESTEPS: 1000 + ZERO_TERMINAL_SNR: False + SCHEDULE_ARGS: + # NAME DESCRIPTION: TYPE: default: '' + NAME: "scaled_linear" + BETA_MIN: 0.00085 + BETA_MAX: 0.0120 + # + DIFFUSION_MODEL: + NAME: DiffusionUNet + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + MODEL_CHANNELS: 320 + NUM_HEADS: 8 + NUM_RES_BLOCKS: 2 + ATTENTION_RESOLUTIONS: [ 4, 2, 1 ] + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + USE_CHECKPOINT: False + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 1 + CONTEXT_DIM: 768 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: False + IGNORE_KEYS: [] + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + IGNORE_KEYS: [] + BATCH_SIZE: 4 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + TOKENIZER: + NAME: ClipTokenizer + PRETRAINED_PATH: ms://AI-ModelScope/clip-vit-large-patch14 + LENGTH: 77 + CLEAN: True + # + COND_STAGE_MODEL: + NAME: FrozenCLIPEmbedder + FREEZE: True + USE_GRAD: False + LAYER: last + PRETRAINED_MODEL: ms://AI-ModelScope/clip-vit-large-patch14 diff --git a/scepter/methods/studio/inference/stable_diffusion/sd21_pro.yaml b/scepter/methods/studio/inference/stable_diffusion/sd21_pro.yaml new file mode 100644 index 0000000..44d5205 --- /dev/null +++ b/scepter/methods/studio/inference/stable_diffusion/sd21_pro.yaml @@ -0,0 +1,124 @@ +NAME: SD2.1 +IS_DEFAULT: False +DEFAULT_PARAS: + PARAS: + RESOLUTIONS: [[768, 768]] + INPUT: + IMAGE: + PROMPT: "" + NEGATIVE_PROMPT: "" + PROMPT_PREFIX: "" + TARGET_SIZE_AS_TUPLE: [768, 768] + SAMPLE: ddim + SAMPLE_STEPS: 50 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: 0.5 + DISCRETIZATION: trailing + OUTPUT: + LATENT: + IMAGES: + SEED: + MODULES_PARAS: + FIRST_STAGE_MODEL: + FUNCTION: + - + NAME: encode + DTYPE: float16 + INPUT: ["IMAGE"] + - + NAME: decode + DTYPE: float16 + INPUT: ["LATENT"] + PARAS: + # SCALE_FACTOR DESCRIPTION: The vae embeding scale. TYPE: float default: 0.18215 + SCALE_FACTOR: 0.18215 + SIZE_FACTOR: 8 + DIFFUSION_MODEL: + FUNCTION: + - + NAME: forward + DTYPE: float16 + INPUT: ["SAMPLE_STEPS", "SAMPLE", "GUIDE_SCALE", "GUIDE_RESCALE", "DISCRETIZATION"] + COND_STAGE_MODEL: + FUNCTION: + - + NAME: encode_text + DTYPE: float16 + INPUT: ["PROMPT", "NEGATIVE_PROMPT"] + +MODEL: + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-2-1@v2-1_768-ema-pruned.safetensors + SCHEDULE: + PARAMETERIZATION: "v" + TIMESTEPS: 1000 + ZERO_TERMINAL_SNR: False + SCHEDULE_ARGS: + # NAME DESCRIPTION: TYPE: default: '' + NAME: "scaled_linear" + BETA_MIN: 0.00085 + BETA_MAX: 0.0120 + # + DIFFUSION_MODEL: + NAME: DiffusionUNet + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + MODEL_CHANNELS: 320 + NUM_HEADS_CHANNELS: 64 + NUM_RES_BLOCKS: 2 + ATTENTION_RESOLUTIONS: [ 4, 2, 1 ] + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + USE_CHECKPOINT: False + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 1 + CONTEXT_DIM: 1024 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + PRETRAINED_MODEL: + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + PRETRAINED_MODEL: + IGNORE_KEYS: [ ] + BATCH_SIZE: 4 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + TOKENIZER: + NAME: OpenClipTokenizer + LENGTH: 77 + # + COND_STAGE_MODEL: + NAME: FrozenOpenCLIPEmbedder + ARCH: ViT-H-14 + PRETRAINED_MODEL: + LAYER: penultimate diff --git a/scepter/methods/studio/preprocess/preprocess.yaml b/scepter/methods/studio/preprocess/preprocess.yaml new file mode 100644 index 0000000..c54f678 --- /dev/null +++ b/scepter/methods/studio/preprocess/preprocess.yaml @@ -0,0 +1,7 @@ +WORK_DIR: datasets +EXPORT_DIR: export_datasets +FILE_SYSTEM: + - + # NAME DESCRIPTION: TYPE: default: '' + NAME: LocalFs + AUTO_CLEAN: False diff --git a/scepter/methods/studio/scepter_ui.yaml b/scepter/methods/studio/scepter_ui.yaml new file mode 100644 index 0000000..b3587e1 --- /dev/null +++ b/scepter/methods/studio/scepter_ui.yaml @@ -0,0 +1,85 @@ +HOST: "localhost" +PORT: 2024 +ROOT: "" +TITLE: SCEPTER Studio +BANNER: | + + + + +WORK_DIR: "cache/scepter_ui" +FILE_SYSTEM: + - + NAME: "ModelscopeFs" + TEMP_DIR: "cache/cache_data" + - + NAME: "HttpFs" + TEMP_DIR: "cache/cache_data" +INTERFACE: + - NAME: 首页 + NAME_EN: Home + IFID: home + CONFIG: scepter/methods/studio/home/home.yaml + - NAME: 数据管理 + NAME_EN: Dataset Management + IFID: preprocess + CONFIG: scepter/methods/studio/preprocess/preprocess.yaml + - NAME: 训练 + NAME_EN: Train + IFID: self_train + CONFIG: scepter/methods/studio/self_train/self_train.yaml + - NAME: 推理 + NAME_EN: Inference + IFID: inference + CONFIG: scepter/methods/studio/inference/inference.yaml diff --git a/scepter/methods/studio/self_train/sd_xl/sdxl_pro.yaml b/scepter/methods/studio/self_train/sd_xl/sdxl_pro.yaml new file mode 100644 index 0000000..dfee523 --- /dev/null +++ b/scepter/methods/studio/self_train/sd_xl/sdxl_pro.yaml @@ -0,0 +1,600 @@ +ENV: + BACKEND: nccl + +META: + VERSION: 'SD_XL1.0' + DESCRIPTION: "Stable Diffusion XL1.0" + IS_DEFAULT: True + INFERENCE_PARAS: + INFERENCE_BATCH_SIZE: 1 + INFERENCE_PREFIX: "" + DEFAULT_SAMPLER: "dpmpp_2s_ancestral" + DEFAULT_SAMPLE_STEPS: 40 + INFERENCE_N_PROMPT: "" + RESOLUTION: 1024 + PARAS: + - + TRAIN_BATCH_SIZE: 2 + TRAIN_PREFIX: "" + TRAIN_N_PROMPT: "" + RESOLUTION: 1024 + MEMORY: 29000 + EPOCHS: 50 + SAVE_INTERVAL: 25 + EPSEC: 0.818 + LEARNING_RATE: 0.0001 + IS_DEFAULT: False + TUNER: FULL + - + TRAIN_BATCH_SIZE: 2 + TRAIN_PREFIX: "" + TRAIN_N_PROMPT: "" + RESOLUTION: 1024 + MEMORY: 29000 + EPOCHS: 50 + SAVE_INTERVAL: 25 + EPSEC: 0.818 + LEARNING_RATE: 0.0001 + IS_DEFAULT: False + TUNER: LORA + - + TRAIN_BATCH_SIZE: 2 + TRAIN_PREFIX: "" + TRAIN_N_PROMPT: "" + RESOLUTION: 1024 + MEMORY: 29000 + EPOCHS: 200 + SAVE_INTERVAL: 25 + EPSEC: 0.818 + LEARNING_RATE: 0.0001 + IS_DEFAULT: False + TUNER: SCE + - + TRAIN_BATCH_SIZE: 2 + TRAIN_PREFIX: "" + TRAIN_N_PROMPT: "" + RESOLUTION: 1024 + MEMORY: 29000 + EPOCHS: 200 + SAVE_INTERVAL: 25 + EPSEC: 0.818 + LEARNING_RATE: 0.0001 + IS_DEFAULT: True + TUNER: TEXT_SCE + - + TRAIN_BATCH_SIZE: 2 + TRAIN_PREFIX: "" + TRAIN_N_PROMPT: "" + RESOLUTION: 1024 + MEMORY: 29000 + EPOCHS: 50 + SAVE_INTERVAL: 25 + EPSEC: 0.818 + LEARNING_RATE: 0.0001 + IS_DEFAULT: False + TUNER: TEXT_LORA + + TUNERS: + LORA: + - + NAME: SwiftLoRA + R: 256 + LORA_ALPHA: 256 + LORA_DROPOUT: 0.0 + BIAS: "none" + TARGET_MODULES: "model.*(to_q|to_k|to_v|to_out.0|net.0.proj|net.2)$" + TEXT_LORA: + - + NAME: SwiftLoRA + R: 256 + LORA_ALPHA: 256 + LORA_DROPOUT: 0.0 + BIAS: "none" + TARGET_MODULES: "(cond_stage_model.embedders.0.*(q_proj|k_proj|v_proj|out_proj|mlp.fc1|mlp.fc2))|(model.*(to_q|to_k|to_v|to_out.0|net.0.proj|net.2))$" + SCE: + - + NAME: SwiftSCETuning + DIMS: [1280, 1280, 640, 640, 640, 320, 320, 320, 320] + TARGET_MODULES: model.lsc_identity\.\d+$ + DOWN_RATIO: 1.0 + TUNER_MODE: identity + TEXT_SCE: + - + NAME: SwiftSCETuning + DIMS: [ 1280, 1280, 640, 640, 640, 320, 320, 320, 320 ] + TARGET_MODULES: model.lsc_identity\.\d+$ + DOWN_RATIO: 1.0 + TUNER_MODE: identity + - + NAME: SwiftLoRA + R: 256 + LORA_ALPHA: 256 + LORA_DROPOUT: 0.0 + BIAS: "none" + TARGET_MODULES: "cond_stage_model.embedders.0.*(q_proj|k_proj|v_proj|out_proj|mlp.fc1|mlp.fc2)$" + + MODIFY_PARAS: + TEXT_LORA: + TRAIN: + SOLVER.MODEL.COND_STAGE_MODEL.USE_GRAD: True + TEXT_SCE: + TRAIN: + SOLVER.MODEL.COND_STAGE_MODEL.USE_GRAD: True + +SOLVER: + # NAME DESCRIPTION: TYPE: default: 'LatentDiffusionSolver' + NAME: LatentDiffusionSolver + # MAX_STEPS DESCRIPTION: The total steps for training. TYPE: int default: 100000 + MAX_STEPS: 2000 + # USE_AMP DESCRIPTION: Use amp to surpport mix precision or not, default is False. TYPE: bool default: False + USE_AMP: False + # DTYPE DESCRIPTION: The precision for training. TYPE: str default: 'float32' + DTYPE: float16 + # USE_FAIRSCALE DESCRIPTION: Use fairscale as the backend of ddp, default False. TYPE: bool default: False + USE_FAIRSCALE: False + # USE_FSDP DESCRIPTION: Use fsdp as the backend of ddp, default False. TYPE: bool default: False + USE_FSDP: False + # SHARDING_STRATEGY DESCRIPTION: The shard strategy for fsdp, select from ['full_shard', 'shard_grad_op'] TYPE: str default: 'shard_grad_op' + SHARDING_STRATEGY: + # LOAD_MODEL_ONLY DESCRIPTION: Only load the model rather than the optimizer and schedule, default is False. TYPE: bool default: False + LOAD_MODEL_ONLY: False + # CHANNELS_LAST DESCRIPTION: The channels last, default is False. TYPE: bool default: False + CHANNELS_LAST: False + # RESUME_FROM DESCRIPTION: Resume from some state of training! TYPE: str default: '' + RESUME_FROM: + # MAX_EPOCHS DESCRIPTION: Max epochs for training. TYPE: int default: 10 + MAX_EPOCHS: -1 + # NUM_FOLDS DESCRIPTION: Num folds for training. TYPE: int default: 1 + NUM_FOLDS: 1 + # WORK_DIR DESCRIPTION: Save dir of the training log or model. TYPE: str default: '' + WORK_DIR: + # LOG_FILE DESCRIPTION: Save log path. TYPE: str default: '' + LOG_FILE: stg_log.txt + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + TUNER: + # MODEL DESCRIPTION: TYPE: default: '' + MODEL: + # NAME DESCRIPTION: + NAME: LatentDiffusionXL + # PARAMETERIZATION DESCRIPTION: The prediction type, you can choose from 'eps' and 'x0' and 'v' TYPE: str default: 'v' + PARAMETERIZATION: eps + # TIMESTEPS DESCRIPTION: The schedule steps for diffusion. TYPE: int default: 1000 + TIMESTEPS: 1000 + # MIN_SNR_GAMMA DESCRIPTION: The minimum snr gamma, default is None. TYPE: NoneType default: None + # MIN_SNR_GAMMA: None + # ZERO_TERMINAL_SNR DESCRIPTION: Whether zero terminal snr, default is False. TYPE: bool default: False + ZERO_TERMINAL_SNR: False + # PRETRAINED_MODEL DESCRIPTION: Whole model's pretrained model path. TYPE: NoneType default: None + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-xl-base-1.0@sd_xl_base_1.0.safetensors + # IGNORE_KEYS DESCRIPTION: The ignore keys for pretrain model loaded. TYPE: list default: [] + IGNORE_KEYS: [ ] + # SCALE_FACTOR DESCRIPTION: The vae embeding scale. TYPE: float default: 0.18215 + SCALE_FACTOR: 0.13025 + # SIZE_FACTOR DESCRIPTION: The vae size factor. TYPE: int default: 8 + SIZE_FACTOR: 8 + # DEFAULT_N_PROMPT DESCRIPTION: The default negtive prompt. TYPE: str default: '' + DEFAULT_N_PROMPT: "" + # TRAIN_N_PROMPT DESCRIPTION: The negtive prompt used in train phase. TYPE: str default: '' + TRAIN_N_PROMPT: "" + # P_ZERO DESCRIPTION: The prob for zero or negtive prompt. TYPE: float default: 0.0 + P_ZERO: 0.1 + # USE_EMA DESCRIPTION: Use Ema or not. Default True TYPE: bool default: True + USE_EMA: False + LOAD_REFINER: False + # SCHEDULE_ARGS DESCRIPTION: TYPE: default: '' + SCHEDULE_ARGS: + # NAME DESCRIPTION: TYPE: default: '' + "NAME": "scaled_linear" + "BETA_MIN": 0.00085 + "BETA_MAX": 0.0120 + # DIFFUSION_MODEL DESCRIPTION: TYPE: default: '' + DIFFUSION_MODEL: + # NAME DESCRIPTION: TYPE: default: 'DiffusionUNetXL' + NAME: DiffusionUNetXL + # PRETRAINED_MODEL DESCRIPTION: Whole model's pretrained model path. TYPE: NoneType default: None + PRETRAINED_MODEL: + # IN_CHANNELS DESCRIPTION: Unet channels for input, considering the input image's channels. TYPE: int default: 4 + IN_CHANNELS: 4 + # OUT_CHANNELS DESCRIPTION: Unet channels for output, considering the input image's channels. TYPE: int default: 4 + OUT_CHANNELS: 4 + # NUM_RES_BLOCKS DESCRIPTION: The blocks's number of res. TYPE: int default: 2 + NUM_RES_BLOCKS: 2 + # MODEL_CHANNELS DESCRIPTION: base channel count for the model. TYPE: int default: 320 + MODEL_CHANNELS: 320 + # ATTENTION_RESOLUTIONS DESCRIPTION: A collection of downsample rates at which attention will take place. May be a set, list, or tuple. For example, if this contains 4, then at 4x downsampling, attentio will be used. TYPE: list default: [4, 2] + ATTENTION_RESOLUTIONS: [4, 2] + # DROPOUT DESCRIPTION: The dropout rate. TYPE: int default: 0 + DROPOUT: 0 + # CHANNEL_MULT DESCRIPTION: channel multiplier for each level of the UNet. TYPE: list default: [1, 2, 4] + CHANNEL_MULT: [1, 2, 4] + # CONV_RESAMPLE DESCRIPTION: Use conv to resample when downsample. TYPE: bool default: True + CONV_RESAMPLE: True + # DIMS DESCRIPTION: The Conv dims which 2 represent Conv2D. TYPE: int default: 2 + DIMS: 2 + # NUM_CLASSES DESCRIPTION: The class num for class guided setting, also can be set as continuous. TYPE: str default: 'sequential' + NUM_CLASSES: sequential + # USE_CHECKPOINT DESCRIPTION: Use gradient checkpointing to reduce memory usage. TYPE: bool default: False + USE_CHECKPOINT: False + # NUM_HEADS DESCRIPTION: The number of attention heads in each attention layer. TYPE: int default: -1 + NUM_HEADS: -1 + # NUM_HEADS_CHANNELS DESCRIPTION: If specified, ignore num_heads and instead use a fixed channel width per attention head. TYPE: int default: 64 + NUM_HEADS_CHANNELS: 64 + # USE_SCALE_SHIFT_NORM DESCRIPTION: The scale and shift for the outnorm of RESBLOCK, use a FiLM-like conditioning mechanism. TYPE: bool default: False + USE_SCALE_SHIFT_NORM: False + # RESBLOCK_UPDOWN DESCRIPTION: Use residual blocks for up/downsampling, if False use Conv. TYPE: bool default: False + RESBLOCK_UPDOWN: False + # USE_NEW_ATTENTION_ORDER DESCRIPTION: Whether use new attention(qkv before split heads or not) or not. TYPE: bool default: True + USE_NEW_ATTENTION_ORDER: True + # USE_SPATIAL_TRANSFORMER DESCRIPTION: Custom transformer which support the context, if context_dim is not None, the parameter must set True TYPE: bool default: True + USE_SPATIAL_TRANSFORMER: True + # TRANSFORMER_DEPTH DESCRIPTION: Custom transformer's depth, valid when USE_SPATIAL_TRANSFORMER is True. TYPE: list default: [1, 2, 10] + TRANSFORMER_DEPTH: [1, 2, 10] + # TRANSFORMER_DEPTH_MIDDLE DESCRIPTION: Custom transformer's depth of middle block, If set None, use TRANSFORMER_DEPTH last value. TYPE: NoneType default: None + # TRANSFORMER_DEPTH_MIDDLE: None + # CONTEXT_DIM DESCRIPTION: Custom context info, if set, USE_SPATIAL_TRANSFORMER also set True. TYPE: int default: 2048 + CONTEXT_DIM: 2048 + # DISABLE_SELF_ATTENTIONS DESCRIPTION: Whether disable the self-attentions on some level, should be a list, [False, True, ...] TYPE: NoneType default: None + # DISABLE_SELF_ATTENTIONS: None + # NUM_ATTENTION_BLOCKS DESCRIPTION: The number of attention blocks for attention layer. TYPE: NoneType default: None + # NUM_ATTENTION_BLOCKS: None + # DISABLE_MIDDLE_SELF_ATTN DESCRIPTION: Whether disable the self-attentions in middle blocks. TYPE: bool default: False + DISABLE_MIDDLE_SELF_ATTN: False + # USE_LINEAR_IN_TRANSFORMER DESCRIPTION: Custom transformer's parameter, valid when USE_SPATIAL_TRANSFORMER is True. TYPE: bool default: True + USE_LINEAR_IN_TRANSFORMER: True + # ADM_IN_CHANNELS DESCRIPTION: Used when num_classes == 'sequential' or 'timestep'. TYPE: int default: 2816 + ADM_IN_CHANNELS: 2816 + # USE_SENTENCE_EMB DESCRIPTION: Used sentence emb or not, default False. TYPE: bool default: False + USE_SENTENCE_EMB: False + # USE_WORD_MAPPING DESCRIPTION: Used word mapping or not, default False. TYPE: bool default: False + USE_WORD_MAPPING: False + # DIFFUSION_MODEL_EMA DESCRIPTION: TYPE: default: '' + DIFFUSION_MODEL_EMA: + # NAME DESCRIPTION: TYPE: default: 'DiffusionUNetXL' + NAME: DiffusionUNetXL + # IN_CHANNELS DESCRIPTION: Unet channels for input, considering the input image's channels. TYPE: int default: 4 + IN_CHANNELS: 4 + # OUT_CHANNELS DESCRIPTION: Unet channels for output, considering the input image's channels. TYPE: int default: 4 + OUT_CHANNELS: 4 + # NUM_RES_BLOCKS DESCRIPTION: The blocks's number of res. TYPE: int default: 2 + NUM_RES_BLOCKS: 2 + # MODEL_CHANNELS DESCRIPTION: base channel count for the model. TYPE: int default: 320 + MODEL_CHANNELS: 320 + # ATTENTION_RESOLUTIONS DESCRIPTION: A collection of downsample rates at which attention will take place. May be a set, list, or tuple. For example, if this contains 4, then at 4x downsampling, attentio will be used. TYPE: list default: [4, 2] + ATTENTION_RESOLUTIONS: [4, 2] + # DROPOUT DESCRIPTION: The dropout rate. TYPE: int default: 0 + DROPOUT: 0 + # CHANNEL_MULT DESCRIPTION: channel multiplier for each level of the UNet. TYPE: list default: [1, 2, 4] + CHANNEL_MULT: [1, 2, 4] + # CONV_RESAMPLE DESCRIPTION: Use conv to resample when downsample. TYPE: bool default: True + CONV_RESAMPLE: True + # DIMS DESCRIPTION: The Conv dims which 2 represent Conv2D. TYPE: int default: 2 + DIMS: 2 + # NUM_CLASSES DESCRIPTION: The class num for class guided setting, also can be set as continuous. TYPE: str default: 'sequential' + NUM_CLASSES: sequential + # USE_CHECKPOINT DESCRIPTION: Use gradient checkpointing to reduce memory usage. TYPE: bool default: False + USE_CHECKPOINT: False + # NUM_HEADS DESCRIPTION: The number of attention heads in each attention layer. TYPE: int default: -1 + NUM_HEADS: -1 + # NUM_HEADS_CHANNELS DESCRIPTION: If specified, ignore num_heads and instead use a fixed channel width per attention head. TYPE: int default: 64 + NUM_HEADS_CHANNELS: 64 + # USE_SCALE_SHIFT_NORM DESCRIPTION: The scale and shift for the outnorm of RESBLOCK, use a FiLM-like conditioning mechanism. TYPE: bool default: False + USE_SCALE_SHIFT_NORM: False + # RESBLOCK_UPDOWN DESCRIPTION: Use residual blocks for up/downsampling, if False use Conv. TYPE: bool default: False + RESBLOCK_UPDOWN: False + # USE_NEW_ATTENTION_ORDER DESCRIPTION: Whether use new attention(qkv before split heads or not) or not. TYPE: bool default: True + USE_NEW_ATTENTION_ORDER: True + # USE_SPATIAL_TRANSFORMER DESCRIPTION: Custom transformer which support the context, if context_dim is not None, the parameter must set True TYPE: bool default: True + USE_SPATIAL_TRANSFORMER: True + # TRANSFORMER_DEPTH DESCRIPTION: Custom transformer's depth, valid when USE_SPATIAL_TRANSFORMER is True. TYPE: list default: [1, 2, 10] + TRANSFORMER_DEPTH: [1, 2, 10] + # TRANSFORMER_DEPTH_MIDDLE DESCRIPTION: Custom transformer's depth of middle block, If set None, use TRANSFORMER_DEPTH last value. TYPE: NoneType default: None + # TRANSFORMER_DEPTH_MIDDLE: None + # CONTEXT_DIM DESCRIPTION: Custom context info, if set, USE_SPATIAL_TRANSFORMER also set True. TYPE: int default: 2048 + CONTEXT_DIM: 2048 + # DISABLE_SELF_ATTENTIONS DESCRIPTION: Whether disable the self-attentions on some level, should be a list, [False, True, ...] TYPE: NoneType default: None + # DISABLE_SELF_ATTENTIONS: None + # NUM_ATTENTION_BLOCKS DESCRIPTION: The number of attention blocks for attention layer. TYPE: NoneType default: None + # NUM_ATTENTION_BLOCKS: None + # DISABLE_MIDDLE_SELF_ATTN DESCRIPTION: Whether disable the self-attentions in middle blocks. TYPE: bool default: False + DISABLE_MIDDLE_SELF_ATTN: False + # USE_LINEAR_IN_TRANSFORMER DESCRIPTION: Custom transformer's parameter, valid when USE_SPATIAL_TRANSFORMER is True. TYPE: bool default: True + USE_LINEAR_IN_TRANSFORMER: True + # ADM_IN_CHANNELS DESCRIPTION: Used when num_classes == 'sequential' or 'timestep'. TYPE: int default: 2816 + ADM_IN_CHANNELS: 2816 + # USE_SENTENCE_EMB DESCRIPTION: Used sentence emb or not, default False. TYPE: bool default: False + USE_SENTENCE_EMB: False + # USE_WORD_MAPPING DESCRIPTION: Used word mapping or not, default False. TYPE: bool default: False + USE_WORD_MAPPING: False + # FIRST_STAGE_MODEL DESCRIPTION: TYPE: default: '' + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + PRETRAINED_MODEL: + IGNORE_KEYS: [ ] + BATCH_SIZE: 1 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # COND_STAGE_MODEL DESCRIPTION: TYPE: default: '' + COND_STAGE_MODEL: + # NAME DESCRIPTION: TYPE: default: 'GeneralConditioner' + NAME: GeneralConditioner + PRETRAINED_MODEL: + USE_GRAD: False + # EMBEDDERS DESCRIPTION: TYPE: default: '' + EMBEDDERS: + - + # NAME DESCRIPTION: TYPE: default: 'FrozenCLIPEmbedder' + NAME: FrozenCLIPEmbedder + PRETRAINED_MODEL: ms://AI-ModelScope/clip-vit-large-patch14 + TOKENIZER_PATH: ms://AI-ModelScope/clip-vit-large-patch14 + # MAX_LENGTH DESCRIPTION: TYPE: int default: 77 + MAX_LENGTH: 77 + # FREEZE DESCRIPTION: TYPE: bool default: True + FREEZE: True + # LAYER DESCRIPTION: TYPE: str default: 'last' + LAYER: hidden + # LAYER_IDX DESCRIPTION: TYPE: NoneType default: None + LAYER_IDX: 11 + # USE_FINAL_LAYER_NORM DESCRIPTION: TYPE: bool default: False + USE_FINAL_LAYER_NORM: False + UCG_RATE: 0.0 + INPUT_KEYS: ["prompt"] + LEGACY_UCG_VALUE: + - + # NAME DESCRIPTION: TYPE: default: 'FrozenOpenCLIPEmbedder2' + NAME: FrozenOpenCLIPEmbedder2 + # ARCH DESCRIPTION: TYPE: str default: 'ViT-H-14' + ARCH: ViT-bigG-14 + # MAX_LENGTH DESCRIPTION: TYPE: int default: 77 + MAX_LENGTH: 77 + # FREEZE DESCRIPTION: TYPE: bool default: True + FREEZE: True + # ALWAYS_RETURN_POOLED DESCRIPTION: Whether always return pooled results or not ,default False. TYPE: bool default: False + ALWAYS_RETURN_POOLED: True + # LEGACY DESCRIPTION: Whether use legacy returnd feature or not ,default True. TYPE: bool default: True + LEGACY: False + # LAYER DESCRIPTION: TYPE: str default: 'last' + LAYER: penultimate + UCG_RATE: 0.0 + INPUT_KEYS: ["prompt"] + LEGACY_UCG_VALUE: + - + # NAME DESCRIPTION: TYPE: default: 'ConcatTimestepEmbedderND' + NAME: ConcatTimestepEmbedderND + # OUT_DIM DESCRIPTION: Output dim TYPE: int default: 256 + OUT_DIM: 256 + UCG_RATE: 0.0 + INPUT_KEYS: ["original_size_as_tuple"] + LEGACY_UCG_VALUE: + - + # NAME DESCRIPTION: TYPE: default: 'ConcatTimestepEmbedderND' + NAME: ConcatTimestepEmbedderND + # OUT_DIM DESCRIPTION: Output dim TYPE: int default: 256 + OUT_DIM: 256 + UCG_RATE: 0.0 + INPUT_KEYS: ["crop_coords_top_left"] + LEGACY_UCG_VALUE: + - + # NAME DESCRIPTION: TYPE: default: 'ConcatTimestepEmbedderND' + NAME: ConcatTimestepEmbedderND + # OUT_DIM DESCRIPTION: Output dim TYPE: int default: 256 + OUT_DIM: 256 + UCG_RATE: 0.0 + INPUT_KEYS: ["target_size_as_tuple"] + LEGACY_UCG_VALUE: + # APPLY REFINER + REFINER_MODEL: + # NAME DESCRIPTION: TYPE: default: 'DiffusionUNetXL' + NAME: DiffusionUNetXL + # PRETRAINED_MODEL DESCRIPTION: Whole model's pretrained model path. TYPE: NoneType default: None + PRETRAINED_MODEL: + # IN_CHANNELS DESCRIPTION: Unet channels for input, considering the input image's channels. TYPE: int default: 4 + IN_CHANNELS: 4 + # OUT_CHANNELS DESCRIPTION: Unet channels for output, considering the input image's channels. TYPE: int default: 4 + OUT_CHANNELS: 4 + # NUM_RES_BLOCKS DESCRIPTION: The blocks's number of res. TYPE: int default: 2 + NUM_RES_BLOCKS: 2 + # MODEL_CHANNELS DESCRIPTION: base channel count for the model. TYPE: int default: 320 + MODEL_CHANNELS: 384 + # ATTENTION_RESOLUTIONS DESCRIPTION: A collection of downsample rates at which attention will take place. May be a set, list, or tuple. For example, if this contains 4, then at 4x downsampling, attentio will be used. TYPE: list default: [4, 2] + ATTENTION_RESOLUTIONS: [ 4, 2 ] + # DROPOUT DESCRIPTION: The dropout rate. TYPE: int default: 0 + DROPOUT: 0 + # CHANNEL_MULT DESCRIPTION: channel multiplier for each level of the UNet. TYPE: list default: [1, 2, 4] + CHANNEL_MULT: [ 1, 2, 4, 4 ] + # CONV_RESAMPLE DESCRIPTION: Use conv to resample when downsample. TYPE: bool default: True + CONV_RESAMPLE: True + # DIMS DESCRIPTION: The Conv dims which 2 represent Conv2D. TYPE: int default: 2 + DIMS: 2 + # NUM_CLASSES DESCRIPTION: The class num for class guided setting, also can be set as continuous. TYPE: str default: 'sequential' + NUM_CLASSES: sequential + # USE_CHECKPOINT DESCRIPTION: Use gradient checkpointing to reduce memory usage. TYPE: bool default: False + USE_CHECKPOINT: False + # NUM_HEADS DESCRIPTION: The number of attention heads in each attention layer. TYPE: int default: -1 + NUM_HEADS: -1 + # NUM_HEADS_CHANNELS DESCRIPTION: If specified, ignore num_heads and instead use a fixed channel width per attention head. TYPE: int default: 64 + NUM_HEADS_CHANNELS: 64 + # USE_SCALE_SHIFT_NORM DESCRIPTION: The scale and shift for the outnorm of RESBLOCK, use a FiLM-like conditioning mechanism. TYPE: bool default: False + USE_SCALE_SHIFT_NORM: False + # RESBLOCK_UPDOWN DESCRIPTION: Use residual blocks for up/downsampling, if False use Conv. TYPE: bool default: False + RESBLOCK_UPDOWN: False + # USE_NEW_ATTENTION_ORDER DESCRIPTION: Whether use new attention(qkv before split heads or not) or not. TYPE: bool default: True + USE_NEW_ATTENTION_ORDER: True + # USE_SPATIAL_TRANSFORMER DESCRIPTION: Custom transformer which support the context, if context_dim is not None, the parameter must set True TYPE: bool default: True + USE_SPATIAL_TRANSFORMER: True + # TRANSFORMER_DEPTH DESCRIPTION: Custom transformer's depth, valid when USE_SPATIAL_TRANSFORMER is True. TYPE: list default: [1, 2, 10] + TRANSFORMER_DEPTH: 4 + # TRANSFORMER_DEPTH_MIDDLE DESCRIPTION: Custom transformer's depth of middle block, If set None, use TRANSFORMER_DEPTH last value. TYPE: NoneType default: None + # TRANSFORMER_DEPTH_MIDDLE: None + # CONTEXT_DIM DESCRIPTION: Custom context info, if set, USE_SPATIAL_TRANSFORMER also set True. TYPE: int default: 2048 + CONTEXT_DIM: [ 1280, 1280, 1280, 1280 ] + # DISABLE_SELF_ATTENTIONS DESCRIPTION: Whether disable the self-attentions on some level, should be a list, [False, True, ...] TYPE: NoneType default: None + # DISABLE_SELF_ATTENTIONS: None + # NUM_ATTENTION_BLOCKS DESCRIPTION: The number of attention blocks for attention layer. TYPE: NoneType default: None + # NUM_ATTENTION_BLOCKS: None + # DISABLE_MIDDLE_SELF_ATTN DESCRIPTION: Whether disable the self-attentions in middle blocks. TYPE: bool default: False + DISABLE_MIDDLE_SELF_ATTN: False + # USE_LINEAR_IN_TRANSFORMER DESCRIPTION: Custom transformer's parameter, valid when USE_SPATIAL_TRANSFORMER is True. TYPE: bool default: True + USE_LINEAR_IN_TRANSFORMER: True + # ADM_IN_CHANNELS DESCRIPTION: Used when num_classes == 'sequential' or 'timestep'. TYPE: int default: 2816 + ADM_IN_CHANNELS: 2560 + # USE_SENTENCE_EMB DESCRIPTION: Used sentence emb or not, default False. TYPE: bool default: False + USE_SENTENCE_EMB: False + # USE_WORD_MAPPING DESCRIPTION: Used word mapping or not, default False. TYPE: bool default: False + USE_WORD_MAPPING: False + # COND_STAGE_MODEL DESCRIPTION: TYPE: default: '' + REFINER_COND_MODEL: + # NAME DESCRIPTION: TYPE: default: 'GeneralConditioner' + NAME: GeneralConditioner + PRETRAINED_MODEL: + # EMBEDDERS DESCRIPTION: TYPE: default: '' + EMBEDDERS: + - + # NAME DESCRIPTION: TYPE: default: 'FrozenOpenCLIPEmbedder2' + NAME: FrozenOpenCLIPEmbedder2 + # ARCH DESCRIPTION: TYPE: str default: 'ViT-H-14' + ARCH: ViT-bigG-14 + # MAX_LENGTH DESCRIPTION: TYPE: int default: 77 + MAX_LENGTH: 77 + # FREEZE DESCRIPTION: TYPE: bool default: True + FREEZE: True + # ALWAYS_RETURN_POOLED DESCRIPTION: Whether always return pooled results or not ,default False. TYPE: bool default: False + ALWAYS_RETURN_POOLED: True + # LEGACY DESCRIPTION: Whether use legacy returnd feature or not ,default True. TYPE: bool default: True + LEGACY: False + # LAYER DESCRIPTION: TYPE: str default: 'last' + LAYER: penultimate + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: ["prompt"] + LEGACY_UCG_VALUE: + - + # NAME DESCRIPTION: TYPE: default: 'ConcatTimestepEmbedderND' + NAME: ConcatTimestepEmbedderND + # OUT_DIM DESCRIPTION: Output dim TYPE: int default: 256 + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: ["original_size_as_tuple"] + LEGACY_UCG_VALUE: + - + # NAME DESCRIPTION: TYPE: default: 'ConcatTimestepEmbedderND' + NAME: ConcatTimestepEmbedderND + # OUT_DIM DESCRIPTION: Output dim TYPE: int default: 256 + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: ["crop_coords_top_left"] + LEGACY_UCG_VALUE: + - + # NAME DESCRIPTION: TYPE: default: 'ConcatTimestepEmbedderND' + NAME: ConcatTimestepEmbedderND + # OUT_DIM DESCRIPTION: Output dim TYPE: int default: 256 + OUT_DIM: 256 + IS_TRAINABLE: False + UCG_RATE: 0.0 + INPUT_KEYS: ["aesthetic_score"] + LEGACY_UCG_VALUE: + + SAMPLE_ARGS: + SAMPLER: ddim + SAMPLE_STEPS: 50 + SEED: 2023 + GUIDE_SCALE: 5.0 + GUIDE_RESCALE: + DISCRETIZATION: linspace + IMAGE_SIZE: [ 1024, 1024] + RUN_TRAIN_N: False + # OPTIMIZER DESCRIPTION: TYPE: default: '' + OPTIMIZER: + # NAME DESCRIPTION: TYPE: default: '' + NAME: AdamW + LEARNING_RATE: 0.0064 + EPS: 1e-8 + AMSGRAD: False + # + TRAIN_DATA: + NAME: ImageTextPairMSDataset + MODE: train + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 1 + NUM_WORKERS: 4 + SAMPLER: + NAME: LoopSampler + # + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: FlexibleResize + INTERPOLATION: bicubic + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: FlexibleCropXL + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: torchvision + - NAME: Select + KEYS: [ 'img', 'prompt', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left' ] + META_KEYS: ['data_key', 'img_path'] + - NAME: Rename + INPUT_KEY: [ 'img', 'img_original_size_as_tuple', 'img_target_size_as_tuple', 'img_crop_coords_top_left'] + OUTPUT_KEY: [ 'image', 'original_size_as_tuple', 'target_size_as_tuple', 'crop_coords_top_left' ] + # + TRAIN_HOOKS: + - NAME: BackwardHook + # GRADIENT_CLIP: 1.0 + PRIORITY: 0 + - NAME: LogHook + LOG_INTERVAL: 50 + SHOW_GPU_MEM: True + - + NAME: CheckpointHook + SAVE_LAST: True + INTERVAL: 10000 + PRIORITY: 200 diff --git a/scepter/methods/studio/self_train/self_train.yaml b/scepter/methods/studio/self_train/self_train.yaml new file mode 100644 index 0000000..0c5925f --- /dev/null +++ b/scepter/methods/studio/self_train/self_train.yaml @@ -0,0 +1,10 @@ +WORK_DIR: "self_train" +SCRIPT_DIR: "scepter/studio/self_train/scripts" +DEFAULT_FOLDER: sd_xl +SAMPLERS: + - + NAME: 'ddim' + - + NAME: 'dpmpp_2m_sde' + - + NAME: 'dpmpp_2s_ancestral' diff --git a/scepter/methods/studio/self_train/stable_diffusion/sd15_pro.yaml b/scepter/methods/studio/self_train/stable_diffusion/sd15_pro.yaml new file mode 100644 index 0000000..ca7f4d1 --- /dev/null +++ b/scepter/methods/studio/self_train/stable_diffusion/sd15_pro.yaml @@ -0,0 +1,312 @@ +ENV: + BACKEND: nccl +META: + VERSION: 'SD1.5' + DESCRIPTION: "Stable Diffusion v1.5" + IS_DEFAULT: False + INFERENCE_PARAS: + INFERENCE_BATCH_SIZE: 1 + INFERENCE_PREFIX: "" + DEFAULT_SAMPLER: "ddim" + DEFAULT_SAMPLE_STEPS: 40 + INFERENCE_N_PROMPT: "" + RESOLUTION: 512 + PARAS: + - + TRAIN_BATCH_SIZE: 2 + TRAIN_PREFIX: "" + TRAIN_N_PROMPT: "" + RESOLUTION: 512 + MEMORY: 29000 + EPOCHS: 50 + SAVE_INTERVAL: 25 + EPSEC: 0.818 + LEARNING_RATE: 0.0001 + IS_DEFAULT: False + TUNER: FULL + - + TRAIN_BATCH_SIZE: 2 + TRAIN_PREFIX: "" + TRAIN_N_PROMPT: "" + RESOLUTION: 512 + MEMORY: 29000 + EPOCHS: 50 + SAVE_INTERVAL: 25 + EPSEC: 0.818 + LEARNING_RATE: 0.0001 + IS_DEFAULT: False + TUNER: LORA + - + TRAIN_BATCH_SIZE: 2 + TRAIN_PREFIX: "" + TRAIN_N_PROMPT: "" + RESOLUTION: 512 + MEMORY: 29000 + EPOCHS: 200 + SAVE_INTERVAL: 25 + EPSEC: 0.818 + LEARNING_RATE: 0.0001 + IS_DEFAULT: False + TUNER: SCE + + - + TRAIN_BATCH_SIZE: 2 + TRAIN_PREFIX: "" + TRAIN_N_PROMPT: "" + RESOLUTION: 512 + MEMORY: 29000 + EPOCHS: 200 + SAVE_INTERVAL: 25 + EPSEC: 0.818 + LEARNING_RATE: 0.0001 + IS_DEFAULT: True + TUNER: TEXT_SCE + + - + TRAIN_BATCH_SIZE: 4 + TRAIN_PREFIX: "" + TRAIN_N_PROMPT: "" + RESOLUTION: 512 + MEMORY: 29000 + EPOCHS: 50 + SAVE_INTERVAL: 25 + EPSEC: 0.818 + LEARNING_RATE: 0.0001 + IS_DEFAULT: False + TUNER: TEXT_LORA + + TUNERS: + LORA: + - + NAME: SwiftLoRA + R: 256 + LORA_ALPHA: 256 + LORA_DROPOUT: 0.0 + BIAS: "none" + TARGET_MODULES: "model.*(to_q|to_k|to_v|to_out.0|net.0.proj|net.2)$" + TEXT_LORA: + - + NAME: SwiftLoRA + R: 256 + LORA_ALPHA: 256 + LORA_DROPOUT: 0.0 + BIAS: "none" + TARGET_MODULES: "(cond_stage_model.*(q_proj|k_proj|v_proj|out_proj|mlp.fc1|mlp.fc2))|(model.*(to_q|to_k|to_v|to_out.0|net.0.proj|net.2))$" + SCE: + - + NAME: SwiftSCETuning + DIMS: [1280, 1280, 1280, 1280, 1280, 640, 640, 640, 320, 320, 320, 320] + DOWN_RATIO: 1.0 + TARGET_MODULES: model.lsc_identity\.\d+$ + TUNER_MODE: identity + TEXT_SCE: + - + NAME: SwiftSCETuning + DIMS: [ 1280, 1280, 1280, 1280, 1280, 640, 640, 640, 320, 320, 320, 320 ] + DOWN_RATIO: 1.0 + TARGET_MODULES: model.lsc_identity\.\d+$ + TUNER_MODE: identity + - + NAME: SwiftLoRA + R: 256 + LORA_ALPHA: 256 + LORA_DROPOUT: 0.0 + BIAS: "none" + TARGET_MODULES: "cond_stage_model.*(q_proj|k_proj|v_proj|out_proj|mlp.fc1|mlp.fc2)$" + + MODIFY_PARAS: + TEXT_LORA: + TRAIN: + SOLVER.MODEL.COND_STAGE_MODEL.USE_GRAD: True + TEXT_SCE: + TRAIN: + SOLVER.MODEL.COND_STAGE_MODEL.USE_GRAD: True + +SOLVER: + NAME: LatentDiffusionSolver + RESUME_FROM: + LOAD_MODEL_ONLY: True + USE_FSDP: False + SHARDING_STRATEGY: + USE_AMP: True + DTYPE: float16 + CHANNELS_LAST: True + MAX_STEPS: 1000 + MAX_EPOCHS: -1 + NUM_FOLDS: 1 + ACCU_STEP: 1 + # + WORK_DIR: + LOG_FILE: std_log.txt + # + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + FREEZE: + # + TUNER: + # + MODEL: + NAME: LatentDiffusion + PARAMETERIZATION: eps + TIMESTEPS: 1000 + MIN_SNR_GAMMA: + ZERO_TERMINAL_SNR: False + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-v1-5@v1-5-pruned-emaonly.safetensors + IGNORE_KEYS: [ ] + SCALE_FACTOR: 0.18215 + SIZE_FACTOR: 8 + # DEFAULT_N_PROMPT: 'lowres, error, worst quality, low quality, jpeg artifacts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, dehydrated, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck, username, watermark, signature' + DEFAULT_N_PROMPT: + SCHEDULE_ARGS: + "NAME": "scaled_linear" + "BETA_MIN": 0.00085 + "BETA_MAX": 0.012 + USE_EMA: False + # + DIFFUSION_MODEL: + NAME: DiffusionUNet + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + MODEL_CHANNELS: 320 + NUM_HEADS: 8 + NUM_RES_BLOCKS: 2 + ATTENTION_RESOLUTIONS: [ 4, 2, 1 ] + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + USE_CHECKPOINT: False + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 1 + CONTEXT_DIM: 768 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: False + IGNORE_KEYS: [] + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + IGNORE_KEYS: [] + BATCH_SIZE: 4 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + TOKENIZER: + NAME: ClipTokenizer + PRETRAINED_PATH: ms://AI-ModelScope/clip-vit-large-patch14 + LENGTH: 77 + CLEAN: True + # + COND_STAGE_MODEL: + NAME: FrozenCLIPEmbedder + FREEZE: True + USE_GRAD: False + LAYER: last + PRETRAINED_MODEL: ms://AI-ModelScope/clip-vit-large-patch14 + # + LOSS: + NAME: ReconstructLoss + LOSS_TYPE: l2 + # + SAMPLE_ARGS: + SAMPLER: ddim + SAMPLE_STEPS: 50 + SEED: 2023 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: + DISCRETIZATION: trailing + IMAGE_SIZE: [512, 512] + RUN_TRAIN_N: False + # + OPTIMIZER: + NAME: AdamW + LEARNING_RATE: 0.064 + BETAS: [ 0.9, 0.999 ] + EPS: 1e-8 + WEIGHT_DECAY: 1e-2 + AMSGRAD: False + # + TRAIN_DATA: + NAME: ImageTextPairMSDataset + MODE: train + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 1 + NUM_WORKERS: 4 + SAMPLER: + NAME: LoopSampler + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: Resize + SIZE: 512 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: CenterCrop + SIZE: 512 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image' ] + BACKEND: torchvision + - NAME: Select + KEYS: [ 'image', 'prompt' ] + META_KEYS: [ 'data_key' ] + # + TRAIN_HOOKS: + - NAME: BackwardHook + # GRADIENT_CLIP: 1.0 + PRIORITY: 0 + - NAME: LogHook + LOG_INTERVAL: 50 + SHOW_GPU_MEM: True + - + NAME: CheckpointHook + SAVE_LAST: True + INTERVAL: 10000 + PRIORITY: 200 diff --git a/scepter/methods/studio/self_train/stable_diffusion/sd21_pro.yaml b/scepter/methods/studio/self_train/stable_diffusion/sd21_pro.yaml new file mode 100644 index 0000000..e05788f --- /dev/null +++ b/scepter/methods/studio/self_train/stable_diffusion/sd21_pro.yaml @@ -0,0 +1,254 @@ +ENV: + BACKEND: nccl +META: + VERSION: 'SD2.1' + DESCRIPTION: "Stable Diffusion v2.1" + IS_DEFAULT: False + INFERENCE_PARAS: + INFERENCE_BATCH_SIZE: 1 + INFERENCE_PREFIX: "" + DEFAULT_SAMPLER: "ddim" + DEFAULT_SAMPLE_STEPS: 40 + INFERENCE_N_PROMPT: "" + RESOLUTION: 768 + PARAS: + - + TRAIN_BATCH_SIZE: 2 + TRAIN_PREFIX: "" + TRAIN_N_PROMPT: "" + RESOLUTION: 768 + MEMORY: 29000 + EPOCHS: 50 + SAVE_INTERVAL: 25 + EPSEC: 0.818 + LEARNING_RATE: 0.0001 + IS_DEFAULT: False + TUNER: FULL + - + TRAIN_BATCH_SIZE: 2 + TRAIN_PREFIX: "" + TRAIN_N_PROMPT: "" + RESOLUTION: 768 + MEMORY: 29000 + EPOCHS: 50 + SAVE_INTERVAL: 25 + EPSEC: 0.818 + LEARNING_RATE: 0.0001 + IS_DEFAULT: False + TUNER: LORA + - + TRAIN_BATCH_SIZE: 2 + TRAIN_PREFIX: "" + TRAIN_N_PROMPT: "" + RESOLUTION: 768 + MEMORY: 29000 + EPOCHS: 200 + SAVE_INTERVAL: 25 + EPSEC: 0.818 + LEARNING_RATE: 0.0001 + IS_DEFAULT: True + TUNER: SCE + + TUNERS: + LORA: + - + NAME: SwiftLoRA + R: 256 + LORA_ALPHA: 256 + LORA_DROPOUT: 0.0 + BIAS: "none" + TARGET_MODULES: "model.*(to_q|to_k|to_v|to_out.0|net.0.proj|net.2)$" + SCE: + - + NAME: SwiftSCETuning + DIMS: [1280, 1280, 1280, 1280, 1280, 640, 640, 640, 320, 320, 320, 320] + DOWN_RATIO: 1.0 + TARGET_MODULES: model.lsc_identity\.\d+$ + TUNER_MODE: identity +SOLVER: + NAME: LatentDiffusionSolver + RESUME_FROM: + LOAD_MODEL_ONLY: True + USE_FSDP: False + SHARDING_STRATEGY: + USE_AMP: True + DTYPE: float16 + CHANNELS_LAST: True + MAX_STEPS: 1000 + MAX_EPOCHS: -1 + NUM_FOLDS: 1 + ACCU_STEP: 1 + # + WORK_DIR: + LOG_FILE: std_log.txt + # + FILE_SYSTEM: + NAME: "ModelscopeFs" + TEMP_DIR: "./cache/data" + # + FREEZE: + # + TUNER: + # + MODEL: + NAME: LatentDiffusion + PARAMETERIZATION: v + TIMESTEPS: 1000 + MIN_SNR_GAMMA: + ZERO_TERMINAL_SNR: False + PRETRAINED_MODEL: ms://AI-ModelScope/stable-diffusion-2-1@v2-1_768-ema-pruned.safetensors + IGNORE_KEYS: [ ] + SCALE_FACTOR: 0.18215 + SIZE_FACTOR: 8 + # DEFAULT_N_PROMPT: 'lowres, error, worst quality, low quality, jpeg artifacts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, dehydrated, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck, username, watermark, signature' + DEFAULT_N_PROMPT: + SCHEDULE_ARGS: + "NAME": "scaled_linear" + "BETA_MIN": 0.00085 + "BETA_MAX": 0.012 + USE_EMA: False + # + DIFFUSION_MODEL: + NAME: DiffusionUNet + IN_CHANNELS: 4 + OUT_CHANNELS: 4 + MODEL_CHANNELS: 320 + NUM_HEADS_CHANNELS: 64 + NUM_RES_BLOCKS: 2 + ATTENTION_RESOLUTIONS: [ 4, 2, 1 ] + CHANNEL_MULT: [ 1, 2, 4, 4 ] + CONV_RESAMPLE: True + DIMS: 2 + USE_CHECKPOINT: False + USE_SCALE_SHIFT_NORM: False + RESBLOCK_UPDOWN: False + USE_SPATIAL_TRANSFORMER: True + TRANSFORMER_DEPTH: 1 + CONTEXT_DIM: 1024 + DISABLE_MIDDLE_SELF_ATTN: False + USE_LINEAR_IN_TRANSFORMER: True + PRETRAINED_MODEL: + # + FIRST_STAGE_MODEL: + NAME: AutoencoderKL + EMBED_DIM: 4 + PRETRAINED_MODEL: + IGNORE_KEYS: [ ] + BATCH_SIZE: 4 + # + ENCODER: + NAME: Encoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DOUBLE_Z: True + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + # + DECODER: + NAME: Decoder + CH: 128 + OUT_CH: 3 + NUM_RES_BLOCKS: 2 + IN_CHANNELS: 3 + ATTN_RESOLUTIONS: [ ] + CH_MULT: [ 1, 2, 4, 4 ] + Z_CHANNELS: 4 + DROPOUT: 0.0 + RESAMP_WITH_CONV: True + GIVE_PRE_END: False + TANH_OUT: False + # + TOKENIZER: + NAME: OpenClipTokenizer + LENGTH: 77 + # + COND_STAGE_MODEL: + NAME: FrozenOpenCLIPEmbedder + ARCH: ViT-H-14 + PRETRAINED_MODEL: + USE_GRAD: False + LAYER: penultimate + # + LOSS: + NAME: ReconstructLoss + LOSS_TYPE: l2 + # + SAMPLE_ARGS: + SAMPLER: ddim + SAMPLE_STEPS: 50 + SEED: 2023 + GUIDE_SCALE: 7.5 + GUIDE_RESCALE: + DISCRETIZATION: trailing + IMAGE_SIZE: [768, 768] + RUN_TRAIN_N: False + # + OPTIMIZER: + NAME: AdamW + LEARNING_RATE: 0.064 + BETAS: [ 0.9, 0.999 ] + EPS: 1e-8 + WEIGHT_DECAY: 1e-2 + AMSGRAD: False + # + TRAIN_DATA: + NAME: ImageTextPairMSDataset + MODE: train + MS_DATASET_NAME: style_custom_dataset + MS_DATASET_NAMESPACE: damo + MS_DATASET_SUBNAME: 3D + PROMPT_PREFIX: "" + MS_DATASET_SPLIT: train + MS_REMAP_KEYS: { 'Image:FILE': 'Target:FILE' } + REPLACE_STYLE: False + PIN_MEMORY: True + BATCH_SIZE: 1 + NUM_WORKERS: 4 + SAMPLER: + NAME: LoopSampler + TRANSFORMS: + - NAME: LoadImageFromFile + RGB_ORDER: RGB + BACKEND: pillow + - NAME: Resize + SIZE: 768 + INTERPOLATION: bilinear + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: CenterCrop + SIZE: 768 + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: ImageToTensor + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'img' ] + BACKEND: pillow + - NAME: Normalize + MEAN: [ 0.5, 0.5, 0.5 ] + STD: [ 0.5, 0.5, 0.5 ] + INPUT_KEY: [ 'img' ] + OUTPUT_KEY: [ 'image' ] + BACKEND: torchvision + - NAME: Select + KEYS: [ 'image', 'prompt' ] + META_KEYS: [ 'data_key' ] + # + TRAIN_HOOKS: + - NAME: BackwardHook + # GRADIENT_CLIP: 1.0 + PRIORITY: 0 + - NAME: LogHook + LOG_INTERVAL: 50 + SHOW_GPU_MEM: True + - + NAME: CheckpointHook + SAVE_LAST: True + INTERVAL: 10000 + PRIORITY: 200 diff --git a/scepter/modules/__init__.py b/scepter/modules/__init__.py index 43a95d8..c0ccc94 100644 --- a/scepter/modules/__init__.py +++ b/scepter/modules/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- # Copyright (c) Alibaba, Inc. and its affiliates. -from scepter.modules import data, model, opt, solver, transform, utils +from scepter.modules import (data, inference, model, opt, solver, transform, + utils) diff --git a/scepter/modules/annotator/__init__.py b/scepter/modules/annotator/__init__.py new file mode 100644 index 0000000..46a3367 --- /dev/null +++ b/scepter/modules/annotator/__init__.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +from scepter.modules.annotator.base_annotator import GeneralAnnotator +from scepter.modules.annotator.canny import CannyAnnotator +from scepter.modules.annotator.color import ColorAnnotator +from scepter.modules.annotator.hed import HedAnnotator +from scepter.modules.annotator.midas_op import MidasDetector +from scepter.modules.annotator.mlsd_op import MLSDdetector +from scepter.modules.annotator.openpose import OpenposeAnnotator diff --git a/scepter/modules/annotator/base_annotator.py b/scepter/modules/annotator/base_annotator.py new file mode 100644 index 0000000..11d9def --- /dev/null +++ b/scepter/modules/annotator/base_annotator.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright (c) Alibaba, Inc. and its affiliates. +from abc import ABCMeta + +import torch +import torch.nn as nn + +from scepter.modules.annotator.registry import ANNOTATORS +from scepter.modules.model.base_model import BaseModel +from scepter.modules.utils.config import dict_to_yaml + + +@ANNOTATORS.register_class() +class BaseAnnotator(BaseModel, metaclass=ABCMeta): + para_dict = {} + + def __init__(self, cfg, logger=None): + super().__init__(cfg, logger=logger) + + @torch.no_grad() + @torch.inference_mode + def forward(self, *args, **kwargs): + raise NotImplementedError + + @staticmethod + def get_config_template(): + return dict_to_yaml('ANNOTATORS', + __class__.__name__, + BaseAnnotator.para_dict, + set_name=True) + + +@ANNOTATORS.register_class() +class GeneralAnnotator(BaseAnnotator, metaclass=ABCMeta): + def __init__(self, cfg, logger=None): + super().__init__(cfg, logger=logger) + anno_models = cfg.get('ANNOTATORS', []) + self.annotators = nn.ModuleList() + for n, anno_config in enumerate(anno_models): + annotator = ANNOTATORS.build(anno_config, logger=logger) + annotator.input_keys = anno_config.get('INPUT_KEYS', []) + if isinstance(annotator.input_keys, str): + annotator.input_keys = [annotator.input_keys] + annotator.output_keys = anno_config.get('OUTPUT_KEYS', []) + if isinstance(annotator.output_keys, str): + annotator.output_keys = [annotator.output_keys] + assert len(annotator.input_keys) == len(annotator.output_keys) + self.annotators.append(annotator) + + def forward(self, input_dict): + output_dict = {} + for annotator in self.annotators: + for idx, in_key in enumerate(annotator.input_keys): + if in_key in input_dict: + image = annotator(input_dict[in_key]) + output_dict[annotator.output_keys[idx]] = image + return output_dict diff --git a/scepter/modules/annotator/canny.py b/scepter/modules/annotator/canny.py new file mode 100644 index 0000000..6048970 --- /dev/null +++ b/scepter/modules/annotator/canny.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +from abc import ABCMeta + +import cv2 +import numpy as np +import torch +from PIL import Image + +from scepter.modules.annotator.base_annotator import BaseAnnotator +from scepter.modules.annotator.registry import ANNOTATORS +from scepter.modules.utils.config import dict_to_yaml + + +@ANNOTATORS.register_class() +class CannyAnnotator(BaseAnnotator, metaclass=ABCMeta): + para_dict = {} + + def __init__(self, cfg, logger=None): + super().__init__(cfg, logger=logger) + self.low_threshold = cfg.get('LOW_THRESHOLD', 100) + self.high_threshold = cfg.get('HIGH_THRESHOLD', 200) + + def forward(self, image): + if isinstance(image, Image.Image): + image = np.array(image) + image = cv2.Canny(image, self.low_threshold, self.high_threshold) + elif isinstance(image, torch.Tensor): + image = image.detach().cpu().numpy() + image = cv2.Canny(image, self.low_threshold, self.high_threshold) + elif isinstance(image, np.ndarray): + image = cv2.Canny(image.copy(), self.low_threshold, + self.high_threshold) + else: + raise f'Unsurpport datatype{type(image)}, only surpport np.ndarray, torch.Tensor, Pillow Image.' + assert len(image.shape) < 4 + return image[..., None].repeat(3, 2) + + @staticmethod + def get_config_template(): + return dict_to_yaml('ANNOTATORS', + __class__.__name__, + CannyAnnotator.para_dict, + set_name=True) diff --git a/scepter/modules/annotator/color.py b/scepter/modules/annotator/color.py new file mode 100644 index 0000000..02b406d --- /dev/null +++ b/scepter/modules/annotator/color.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +from abc import ABCMeta + +import cv2 +import numpy as np +import torch +from PIL import Image + +from scepter.modules.annotator.base_annotator import BaseAnnotator +from scepter.modules.annotator.registry import ANNOTATORS +from scepter.modules.utils.config import dict_to_yaml + + +@ANNOTATORS.register_class() +class ColorAnnotator(BaseAnnotator, metaclass=ABCMeta): + para_dict = {} + + def __init__(self, cfg, logger=None): + super().__init__(cfg, logger=logger) + self.ratio = cfg.get('RATIO', 64) + + def forward(self, image): + if isinstance(image, Image.Image): + image = np.array(image) + elif isinstance(image, torch.Tensor): + image = image.detach().cpu().numpy() + elif isinstance(image, np.ndarray): + image = image.copy() + else: + raise f'Unsurpport datatype{type(image)}, only surpport np.ndarray, torch.Tensor, Pillow Image.' + h, w = image.shape[:2] + ratio = self.ratio + image = cv2.resize(image, (w // ratio, h // ratio), + interpolation=cv2.INTER_CUBIC) + image = cv2.resize(image, (w, h), interpolation=cv2.INTER_NEAREST) + assert len(image.shape) < 4 + return image + + @staticmethod + def get_config_template(): + return dict_to_yaml('ANNOTATORS', + __class__.__name__, + ColorAnnotator.para_dict, + set_name=True) diff --git a/scepter/modules/annotator/hed.py b/scepter/modules/annotator/hed.py new file mode 100644 index 0000000..fbfd84c --- /dev/null +++ b/scepter/modules/annotator/hed.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- +# Please use this implementation in your products +# This implementation may produce slightly different results from Saining Xie's official implementations, +# but it generates smoother edges and is more suitable for ControlNet as well as other image-to-image translations. +# Different from official models and other implementations, this is an RGB-input model (rather than BGR) +# and in this way it works better for gradio's RGB protocol + +from abc import ABCMeta + +import cv2 +import numpy as np +import torch +from einops import rearrange + +from scepter.modules.annotator.base_annotator import BaseAnnotator +from scepter.modules.annotator.registry import ANNOTATORS +from scepter.modules.utils.config import dict_to_yaml +from scepter.modules.utils.distribute import we +from scepter.modules.utils.file_system import FS + + +def nms(x, t, s): + x = cv2.GaussianBlur(x.astype(np.float32), (0, 0), s) + + f1 = np.array([[0, 0, 0], [1, 1, 1], [0, 0, 0]], dtype=np.uint8) + f2 = np.array([[0, 1, 0], [0, 1, 0], [0, 1, 0]], dtype=np.uint8) + f3 = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=np.uint8) + f4 = np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0]], dtype=np.uint8) + + y = np.zeros_like(x) + + for f in [f1, f2, f3, f4]: + np.putmask(y, cv2.dilate(x, kernel=f) == x, x) + + z = np.zeros_like(y, dtype=np.uint8) + z[y > t] = 255 + return z + + +class DoubleConvBlock(torch.nn.Module): + def __init__(self, input_channel, output_channel, layer_number): + super().__init__() + self.convs = torch.nn.Sequential() + self.convs.append( + torch.nn.Conv2d(in_channels=input_channel, + out_channels=output_channel, + kernel_size=(3, 3), + stride=(1, 1), + padding=1)) + for i in range(1, layer_number): + self.convs.append( + torch.nn.Conv2d(in_channels=output_channel, + out_channels=output_channel, + kernel_size=(3, 3), + stride=(1, 1), + padding=1)) + self.projection = torch.nn.Conv2d(in_channels=output_channel, + out_channels=1, + kernel_size=(1, 1), + stride=(1, 1), + padding=0) + + def __call__(self, x, down_sampling=False): + h = x + if down_sampling: + h = torch.nn.functional.max_pool2d(h, + kernel_size=(2, 2), + stride=(2, 2)) + for conv in self.convs: + h = conv(h) + h = torch.nn.functional.relu(h) + return h, self.projection(h) + + +class ControlNetHED_Apache2(torch.nn.Module): + def __init__(self): + super().__init__() + self.norm = torch.nn.Parameter(torch.zeros(size=(1, 3, 1, 1))) + self.block1 = DoubleConvBlock(input_channel=3, + output_channel=64, + layer_number=2) + self.block2 = DoubleConvBlock(input_channel=64, + output_channel=128, + layer_number=2) + self.block3 = DoubleConvBlock(input_channel=128, + output_channel=256, + layer_number=3) + self.block4 = DoubleConvBlock(input_channel=256, + output_channel=512, + layer_number=3) + self.block5 = DoubleConvBlock(input_channel=512, + output_channel=512, + layer_number=3) + + def __call__(self, x): + h = x - self.norm + h, projection1 = self.block1(h) + h, projection2 = self.block2(h, down_sampling=True) + h, projection3 = self.block3(h, down_sampling=True) + h, projection4 = self.block4(h, down_sampling=True) + h, projection5 = self.block5(h, down_sampling=True) + return projection1, projection2, projection3, projection4, projection5 + + +@ANNOTATORS.register_class() +class HedAnnotator(BaseAnnotator, metaclass=ABCMeta): + para_dict = {} + + def __init__(self, cfg, logger=None): + super().__init__(cfg, logger=logger) + self.netNetwork = ControlNetHED_Apache2().float().eval() + pretrained_model = cfg.get('PRETRAINED_MODEL', None) + if pretrained_model: + with FS.get_from(pretrained_model, wait_finish=True) as local_path: + self.netNetwork.load_state_dict(torch.load(local_path)) + + @torch.no_grad() + @torch.inference_mode() + @torch.autocast('cuda', enabled=False) + def forward(self, image): + if isinstance(image, torch.Tensor): + if len(image.shape) == 3: + image = rearrange(image, 'h w c -> 1 c h w') + B, C, H, W = image.shape + else: + raise "Unsurpport input image's shape" + elif isinstance(image, np.ndarray): + image = torch.from_numpy(image.copy()).float() + if len(image.shape) == 3: + image = rearrange(image, 'h w c -> 1 c h w') + B, C, H, W = image.shape + else: + raise "Unsurpport input image's shape" + else: + raise "Unsurpport input image's type" + edges = self.netNetwork(image.to(we.device_id)) + edges = [ + e.detach().cpu().numpy().astype(np.float32)[0, 0] for e in edges + ] + edges = [ + cv2.resize(e, (W, H), interpolation=cv2.INTER_LINEAR) + for e in edges + ] + edges = np.stack(edges, axis=2) + edge = 1 / (1 + np.exp(-np.mean(edges, axis=2).astype(np.float64))) + edge = 255 - (edge * 255.0).clip(0, 255).astype(np.uint8) + return edge[..., None].repeat(3, 2) + + @staticmethod + def get_config_template(): + return dict_to_yaml('ANNOTATORS', + __class__.__name__, + HedAnnotator.para_dict, + set_name=True) diff --git a/scepter/modules/annotator/midas/__init__.py b/scepter/modules/annotator/midas/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/modules/annotator/midas/api.py b/scepter/modules/annotator/midas/api.py new file mode 100644 index 0000000..490cd18 --- /dev/null +++ b/scepter/modules/annotator/midas/api.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +# based on https://github.com/isl-org/MiDaS + +import cv2 +import torch +import torch.nn as nn +from torchvision.transforms import Compose + +from .dpt_depth import DPTDepthModel +from .midas_net import MidasNet +from .midas_net_custom import MidasNet_small +from .transforms import NormalizeImage, PrepareForNet, Resize + +# ISL_PATHS = { +# "dpt_large": "dpt_large-midas-2f21e586.pt", +# "dpt_hybrid": "dpt_hybrid-midas-501f0c75.pt", +# "midas_v21": "", +# "midas_v21_small": "", +# } + +# remote_model_path = +# "https://huggingface.co/lllyasviel/ControlNet/resolve/main/annotator/ckpts/dpt_hybrid-midas-501f0c75.pt" + + +def disabled_train(self, mode=True): + """Overwrite model.train with this function to make sure train/eval mode + does not change anymore.""" + return self + + +def load_midas_transform(model_type): + # https://github.com/isl-org/MiDaS/blob/master/run.py + # load transform only + if model_type == 'dpt_large': # DPT-Large + net_w, net_h = 384, 384 + resize_mode = 'minimal' + normalization = NormalizeImage(mean=[0.5, 0.5, 0.5], + std=[0.5, 0.5, 0.5]) + + elif model_type == 'dpt_hybrid': # DPT-Hybrid + net_w, net_h = 384, 384 + resize_mode = 'minimal' + normalization = NormalizeImage(mean=[0.5, 0.5, 0.5], + std=[0.5, 0.5, 0.5]) + + elif model_type == 'midas_v21': + net_w, net_h = 384, 384 + resize_mode = 'upper_bound' + normalization = NormalizeImage(mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]) + + elif model_type == 'midas_v21_small': + net_w, net_h = 256, 256 + resize_mode = 'upper_bound' + normalization = NormalizeImage(mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]) + + else: + assert False, f"model_type '{model_type}' not implemented, use: --model_type large" + + transform = Compose([ + Resize( + net_w, + net_h, + resize_target=None, + keep_aspect_ratio=True, + ensure_multiple_of=32, + resize_method=resize_mode, + image_interpolation_method=cv2.INTER_CUBIC, + ), + normalization, + PrepareForNet(), + ]) + + return transform + + +def load_model(model_type, model_path): + # https://github.com/isl-org/MiDaS/blob/master/run.py + # load network + # model_path = ISL_PATHS[model_type] + if model_type == 'dpt_large': # DPT-Large + model = DPTDepthModel( + path=model_path, + backbone='vitl16_384', + non_negative=True, + ) + net_w, net_h = 384, 384 + resize_mode = 'minimal' + normalization = NormalizeImage(mean=[0.5, 0.5, 0.5], + std=[0.5, 0.5, 0.5]) + + elif model_type == 'dpt_hybrid': # DPT-Hybrid + model = DPTDepthModel( + path=model_path, + backbone='vitb_rn50_384', + non_negative=True, + ) + net_w, net_h = 384, 384 + resize_mode = 'minimal' + normalization = NormalizeImage(mean=[0.5, 0.5, 0.5], + std=[0.5, 0.5, 0.5]) + + elif model_type == 'midas_v21': + model = MidasNet(model_path, non_negative=True) + net_w, net_h = 384, 384 + resize_mode = 'upper_bound' + normalization = NormalizeImage(mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]) + + elif model_type == 'midas_v21_small': + model = MidasNet_small(model_path, + features=64, + backbone='efficientnet_lite3', + exportable=True, + non_negative=True, + blocks={'expand': True}) + net_w, net_h = 256, 256 + resize_mode = 'upper_bound' + normalization = NormalizeImage(mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]) + + else: + print( + f"model_type '{model_type}' not implemented, use: --model_type large" + ) + assert False + + transform = Compose([ + Resize( + net_w, + net_h, + resize_target=None, + keep_aspect_ratio=True, + ensure_multiple_of=32, + resize_method=resize_mode, + image_interpolation_method=cv2.INTER_CUBIC, + ), + normalization, + PrepareForNet(), + ]) + + return model.eval(), transform + + +class MiDaSInference(nn.Module): + MODEL_TYPES_TORCH_HUB = ['DPT_Large', 'DPT_Hybrid', 'MiDaS_small'] + MODEL_TYPES_ISL = [ + 'dpt_large', + 'dpt_hybrid', + 'midas_v21', + 'midas_v21_small', + ] + + def __init__(self, model_type, model_path): + super().__init__() + assert (model_type in self.MODEL_TYPES_ISL) + model, _ = load_model(model_type, model_path) + self.model = model + self.model.train = disabled_train + + def forward(self, x): + with torch.no_grad(): + prediction = self.model(x) + return prediction diff --git a/scepter/modules/annotator/midas/base_model.py b/scepter/modules/annotator/midas/base_model.py new file mode 100644 index 0000000..68d985b --- /dev/null +++ b/scepter/modules/annotator/midas/base_model.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +import torch + + +class BaseModel(torch.nn.Module): + def load(self, path): + """Load model from file. + + Args: + path (str): file path + """ + parameters = torch.load(path, map_location=torch.device('cpu')) + + if 'optimizer' in parameters: + parameters = parameters['model'] + + self.load_state_dict(parameters) diff --git a/scepter/modules/annotator/midas/blocks.py b/scepter/modules/annotator/midas/blocks.py new file mode 100644 index 0000000..472a40e --- /dev/null +++ b/scepter/modules/annotator/midas/blocks.py @@ -0,0 +1,390 @@ +# -*- coding: utf-8 -*- +import torch +import torch.nn as nn + +from .vit import (_make_pretrained_vitb16_384, _make_pretrained_vitb_rn50_384, + _make_pretrained_vitl16_384) + + +def _make_encoder( + backbone, + features, + use_pretrained, + groups=1, + expand=False, + exportable=True, + hooks=None, + use_vit_only=False, + use_readout='ignore', +): + if backbone == 'vitl16_384': + pretrained = _make_pretrained_vitl16_384(use_pretrained, + hooks=hooks, + use_readout=use_readout) + scratch = _make_scratch( + [256, 512, 1024, 1024], features, groups=groups, + expand=expand) # ViT-L/16 - 85.0% Top1 (backbone) + elif backbone == 'vitb_rn50_384': + pretrained = _make_pretrained_vitb_rn50_384( + use_pretrained, + hooks=hooks, + use_vit_only=use_vit_only, + use_readout=use_readout, + ) + scratch = _make_scratch( + [256, 512, 768, 768], features, groups=groups, + expand=expand) # ViT-H/16 - 85.0% Top1 (backbone) + elif backbone == 'vitb16_384': + pretrained = _make_pretrained_vitb16_384(use_pretrained, + hooks=hooks, + use_readout=use_readout) + scratch = _make_scratch( + [96, 192, 384, 768], features, groups=groups, + expand=expand) # ViT-B/16 - 84.6% Top1 (backbone) + elif backbone == 'resnext101_wsl': + pretrained = _make_pretrained_resnext101_wsl(use_pretrained) + scratch = _make_scratch([256, 512, 1024, 2048], + features, + groups=groups, + expand=expand) # efficientnet_lite3 + elif backbone == 'efficientnet_lite3': + pretrained = _make_pretrained_efficientnet_lite3(use_pretrained, + exportable=exportable) + scratch = _make_scratch([32, 48, 136, 384], + features, + groups=groups, + expand=expand) # efficientnet_lite3 + else: + print(f"Backbone '{backbone}' not implemented") + assert False + + return pretrained, scratch + + +def _make_scratch(in_shape, out_shape, groups=1, expand=False): + scratch = nn.Module() + + out_shape1 = out_shape + out_shape2 = out_shape + out_shape3 = out_shape + out_shape4 = out_shape + if expand is True: + out_shape1 = out_shape + out_shape2 = out_shape * 2 + out_shape3 = out_shape * 4 + out_shape4 = out_shape * 8 + + scratch.layer1_rn = nn.Conv2d(in_shape[0], + out_shape1, + kernel_size=3, + stride=1, + padding=1, + bias=False, + groups=groups) + scratch.layer2_rn = nn.Conv2d(in_shape[1], + out_shape2, + kernel_size=3, + stride=1, + padding=1, + bias=False, + groups=groups) + scratch.layer3_rn = nn.Conv2d(in_shape[2], + out_shape3, + kernel_size=3, + stride=1, + padding=1, + bias=False, + groups=groups) + scratch.layer4_rn = nn.Conv2d(in_shape[3], + out_shape4, + kernel_size=3, + stride=1, + padding=1, + bias=False, + groups=groups) + + return scratch + + +def _make_pretrained_efficientnet_lite3(use_pretrained, exportable=False): + efficientnet = torch.hub.load('rwightman/gen-efficientnet-pytorch', + 'tf_efficientnet_lite3', + pretrained=use_pretrained, + exportable=exportable) + return _make_efficientnet_backbone(efficientnet) + + +def _make_efficientnet_backbone(effnet): + pretrained = nn.Module() + + pretrained.layer1 = nn.Sequential(effnet.conv_stem, effnet.bn1, + effnet.act1, *effnet.blocks[0:2]) + pretrained.layer2 = nn.Sequential(*effnet.blocks[2:3]) + pretrained.layer3 = nn.Sequential(*effnet.blocks[3:5]) + pretrained.layer4 = nn.Sequential(*effnet.blocks[5:9]) + + return pretrained + + +def _make_resnet_backbone(resnet): + pretrained = nn.Module() + pretrained.layer1 = nn.Sequential(resnet.conv1, resnet.bn1, resnet.relu, + resnet.maxpool, resnet.layer1) + + pretrained.layer2 = resnet.layer2 + pretrained.layer3 = resnet.layer3 + pretrained.layer4 = resnet.layer4 + + return pretrained + + +def _make_pretrained_resnext101_wsl(use_pretrained): + resnet = torch.hub.load('facebookresearch/WSL-Images', + 'resnext101_32x8d_wsl') + return _make_resnet_backbone(resnet) + + +class Interpolate(nn.Module): + """Interpolation module. + """ + def __init__(self, scale_factor, mode, align_corners=False): + """Init. + + Args: + scale_factor (float): scaling + mode (str): interpolation mode + """ + super(Interpolate, self).__init__() + + self.interp = nn.functional.interpolate + self.scale_factor = scale_factor + self.mode = mode + self.align_corners = align_corners + + def forward(self, x): + """Forward pass. + + Args: + x (tensor): input + + Returns: + tensor: interpolated data + """ + + x = self.interp(x, + scale_factor=self.scale_factor, + mode=self.mode, + align_corners=self.align_corners) + + return x + + +class ResidualConvUnit(nn.Module): + """Residual convolution module. + """ + def __init__(self, features): + """Init. + + Args: + features (int): number of features + """ + super().__init__() + + self.conv1 = nn.Conv2d(features, + features, + kernel_size=3, + stride=1, + padding=1, + bias=True) + + self.conv2 = nn.Conv2d(features, + features, + kernel_size=3, + stride=1, + padding=1, + bias=True) + + self.relu = nn.ReLU(inplace=True) + + def forward(self, x): + """Forward pass. + + Args: + x (tensor): input + + Returns: + tensor: output + """ + out = self.relu(x) + out = self.conv1(out) + out = self.relu(out) + out = self.conv2(out) + + return out + x + + +class FeatureFusionBlock(nn.Module): + """Feature fusion block. + """ + def __init__(self, features): + """Init. + + Args: + features (int): number of features + """ + super(FeatureFusionBlock, self).__init__() + + self.resConfUnit1 = ResidualConvUnit(features) + self.resConfUnit2 = ResidualConvUnit(features) + + def forward(self, *xs): + """Forward pass. + + Returns: + tensor: output + """ + output = xs[0] + + if len(xs) == 2: + output += self.resConfUnit1(xs[1]) + + output = self.resConfUnit2(output) + + output = nn.functional.interpolate(output, + scale_factor=2, + mode='bilinear', + align_corners=True) + + return output + + +class ResidualConvUnit_custom(nn.Module): + """Residual convolution module. + """ + def __init__(self, features, activation, bn): + """Init. + + Args: + features (int): number of features + """ + super().__init__() + + self.bn = bn + + self.groups = 1 + + self.conv1 = nn.Conv2d(features, + features, + kernel_size=3, + stride=1, + padding=1, + bias=True, + groups=self.groups) + + self.conv2 = nn.Conv2d(features, + features, + kernel_size=3, + stride=1, + padding=1, + bias=True, + groups=self.groups) + + if self.bn is True: + self.bn1 = nn.BatchNorm2d(features) + self.bn2 = nn.BatchNorm2d(features) + + self.activation = activation + + self.skip_add = nn.quantized.FloatFunctional() + + def forward(self, x): + """Forward pass. + + Args: + x (tensor): input + + Returns: + tensor: output + """ + + out = self.activation(x) + out = self.conv1(out) + if self.bn is True: + out = self.bn1(out) + + out = self.activation(out) + out = self.conv2(out) + if self.bn is True: + out = self.bn2(out) + + if self.groups > 1: + out = self.conv_merge(out) + + return self.skip_add.add(out, x) + + # return out + x + + +class FeatureFusionBlock_custom(nn.Module): + """Feature fusion block. + """ + def __init__(self, + features, + activation, + deconv=False, + bn=False, + expand=False, + align_corners=True): + """Init. + + Args: + features (int): number of features + """ + super(FeatureFusionBlock_custom, self).__init__() + + self.deconv = deconv + self.align_corners = align_corners + + self.groups = 1 + + self.expand = expand + out_features = features + if self.expand is True: + out_features = features // 2 + + self.out_conv = nn.Conv2d(features, + out_features, + kernel_size=1, + stride=1, + padding=0, + bias=True, + groups=1) + + self.resConfUnit1 = ResidualConvUnit_custom(features, activation, bn) + self.resConfUnit2 = ResidualConvUnit_custom(features, activation, bn) + + self.skip_add = nn.quantized.FloatFunctional() + + def forward(self, *xs): + """Forward pass. + + Returns: + tensor: output + """ + output = xs[0] + + if len(xs) == 2: + res = self.resConfUnit1(xs[1]) + output = self.skip_add.add(output, res) + # output += res + + output = self.resConfUnit2(output) + + output = nn.functional.interpolate(output, + scale_factor=2, + mode='bilinear', + align_corners=self.align_corners) + + output = self.out_conv(output) + + return output diff --git a/scepter/modules/annotator/midas/dpt_depth.py b/scepter/modules/annotator/midas/dpt_depth.py new file mode 100644 index 0000000..2c25e0d --- /dev/null +++ b/scepter/modules/annotator/midas/dpt_depth.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +import torch +import torch.nn as nn + +from .base_model import BaseModel +from .blocks import FeatureFusionBlock_custom, Interpolate, _make_encoder +from .vit import forward_vit + + +def _make_fusion_block(features, use_bn): + return FeatureFusionBlock_custom( + features, + nn.ReLU(False), + deconv=False, + bn=use_bn, + expand=False, + align_corners=True, + ) + + +class DPT(BaseModel): + def __init__( + self, + head, + features=256, + backbone='vitb_rn50_384', + readout='project', + channels_last=False, + use_bn=False, + ): + + super(DPT, self).__init__() + + self.channels_last = channels_last + + hooks = { + 'vitb_rn50_384': [0, 1, 8, 11], + 'vitb16_384': [2, 5, 8, 11], + 'vitl16_384': [5, 11, 17, 23], + } + + # Instantiate backbone and reassemble blocks + self.pretrained, self.scratch = _make_encoder( + backbone, + features, + False, # Set to true of you want to train from scratch, uses ImageNet weights + groups=1, + expand=False, + exportable=False, + hooks=hooks[backbone], + use_readout=readout, + ) + + self.scratch.refinenet1 = _make_fusion_block(features, use_bn) + self.scratch.refinenet2 = _make_fusion_block(features, use_bn) + self.scratch.refinenet3 = _make_fusion_block(features, use_bn) + self.scratch.refinenet4 = _make_fusion_block(features, use_bn) + + self.scratch.output_conv = head + + def forward(self, x): + if self.channels_last is True: + x.contiguous(memory_format=torch.channels_last) + + layer_1, layer_2, layer_3, layer_4 = forward_vit(self.pretrained, x) + + layer_1_rn = self.scratch.layer1_rn(layer_1) + layer_2_rn = self.scratch.layer2_rn(layer_2) + layer_3_rn = self.scratch.layer3_rn(layer_3) + layer_4_rn = self.scratch.layer4_rn(layer_4) + + path_4 = self.scratch.refinenet4(layer_4_rn) + path_3 = self.scratch.refinenet3(path_4, layer_3_rn) + path_2 = self.scratch.refinenet2(path_3, layer_2_rn) + path_1 = self.scratch.refinenet1(path_2, layer_1_rn) + + out = self.scratch.output_conv(path_1) + + return out + + +class DPTDepthModel(DPT): + def __init__(self, path=None, non_negative=True, **kwargs): + features = kwargs['features'] if 'features' in kwargs else 256 + + head = nn.Sequential( + nn.Conv2d(features, + features // 2, + kernel_size=3, + stride=1, + padding=1), + Interpolate(scale_factor=2, mode='bilinear', align_corners=True), + nn.Conv2d(features // 2, 32, kernel_size=3, stride=1, padding=1), + nn.ReLU(True), + nn.Conv2d(32, 1, kernel_size=1, stride=1, padding=0), + nn.ReLU(True) if non_negative else nn.Identity(), + nn.Identity(), + ) + + super().__init__(head, **kwargs) + + if path is not None: + self.load(path) + + def forward(self, x): + return super().forward(x).squeeze(dim=1) diff --git a/scepter/modules/annotator/midas/midas_net.py b/scepter/modules/annotator/midas/midas_net.py new file mode 100644 index 0000000..b041646 --- /dev/null +++ b/scepter/modules/annotator/midas/midas_net.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +"""MidashNet: Network for monocular depth estimation trained by mixing several datasets. +This file contains code that is adapted from +https://github.com/thomasjpfan/pytorch_refinenet/blob/master/pytorch_refinenet/refinenet/refinenet_4cascade.py +""" +import torch +import torch.nn as nn + +from .base_model import BaseModel +from .blocks import FeatureFusionBlock, Interpolate, _make_encoder + + +class MidasNet(BaseModel): + """Network for monocular depth estimation. + """ + def __init__(self, path=None, features=256, non_negative=True): + """Init. + + Args: + path (str, optional): Path to saved model. Defaults to None. + features (int, optional): Number of features. Defaults to 256. + backbone (str, optional): Backbone network for encoder. Defaults to resnet50 + """ + print('Loading weights: ', path) + + super(MidasNet, self).__init__() + + use_pretrained = False if path is None else True + + self.pretrained, self.scratch = _make_encoder( + backbone='resnext101_wsl', + features=features, + use_pretrained=use_pretrained) + + self.scratch.refinenet4 = FeatureFusionBlock(features) + self.scratch.refinenet3 = FeatureFusionBlock(features) + self.scratch.refinenet2 = FeatureFusionBlock(features) + self.scratch.refinenet1 = FeatureFusionBlock(features) + + self.scratch.output_conv = nn.Sequential( + nn.Conv2d(features, 128, kernel_size=3, stride=1, padding=1), + Interpolate(scale_factor=2, mode='bilinear'), + nn.Conv2d(128, 32, kernel_size=3, stride=1, padding=1), + nn.ReLU(True), + nn.Conv2d(32, 1, kernel_size=1, stride=1, padding=0), + nn.ReLU(True) if non_negative else nn.Identity(), + ) + + if path: + self.load(path) + + def forward(self, x): + """Forward pass. + + Args: + x (tensor): input data (image) + + Returns: + tensor: depth + """ + + layer_1 = self.pretrained.layer1(x) + layer_2 = self.pretrained.layer2(layer_1) + layer_3 = self.pretrained.layer3(layer_2) + layer_4 = self.pretrained.layer4(layer_3) + + layer_1_rn = self.scratch.layer1_rn(layer_1) + layer_2_rn = self.scratch.layer2_rn(layer_2) + layer_3_rn = self.scratch.layer3_rn(layer_3) + layer_4_rn = self.scratch.layer4_rn(layer_4) + + path_4 = self.scratch.refinenet4(layer_4_rn) + path_3 = self.scratch.refinenet3(path_4, layer_3_rn) + path_2 = self.scratch.refinenet2(path_3, layer_2_rn) + path_1 = self.scratch.refinenet1(path_2, layer_1_rn) + + out = self.scratch.output_conv(path_1) + + return torch.squeeze(out, dim=1) diff --git a/scepter/modules/annotator/midas/midas_net_custom.py b/scepter/modules/annotator/midas/midas_net_custom.py new file mode 100644 index 0000000..fcdf78d --- /dev/null +++ b/scepter/modules/annotator/midas/midas_net_custom.py @@ -0,0 +1,166 @@ +# -*- coding: utf-8 -*- +"""MidashNet: Network for monocular depth estimation trained by mixing several datasets. +This file contains code that is adapted from +https://github.com/thomasjpfan/pytorch_refinenet/blob/master/pytorch_refinenet/refinenet/refinenet_4cascade.py +""" +import torch +import torch.nn as nn + +from .base_model import BaseModel +from .blocks import FeatureFusionBlock_custom, Interpolate, _make_encoder + + +class MidasNet_small(BaseModel): + """Network for monocular depth estimation. + """ + def __init__(self, + path=None, + features=64, + backbone='efficientnet_lite3', + non_negative=True, + exportable=True, + channels_last=False, + align_corners=True, + blocks={'expand': True}): + """Init. + + Args: + path (str, optional): Path to saved model. Defaults to None. + features (int, optional): Number of features. Defaults to 256. + backbone (str, optional): Backbone network for encoder. Defaults to resnet50 + """ + print('Loading weights: ', path) + + super(MidasNet_small, self).__init__() + + use_pretrained = False if path else True + + self.channels_last = channels_last + self.blocks = blocks + self.backbone = backbone + + self.groups = 1 + + features1 = features + features2 = features + features3 = features + features4 = features + self.expand = False + if 'expand' in self.blocks and self.blocks['expand'] is True: + self.expand = True + features1 = features + features2 = features * 2 + features3 = features * 4 + features4 = features * 8 + + self.pretrained, self.scratch = _make_encoder(self.backbone, + features, + use_pretrained, + groups=self.groups, + expand=self.expand, + exportable=exportable) + + self.scratch.activation = nn.ReLU(False) + + self.scratch.refinenet4 = FeatureFusionBlock_custom( + features4, + self.scratch.activation, + deconv=False, + bn=False, + expand=self.expand, + align_corners=align_corners) + self.scratch.refinenet3 = FeatureFusionBlock_custom( + features3, + self.scratch.activation, + deconv=False, + bn=False, + expand=self.expand, + align_corners=align_corners) + self.scratch.refinenet2 = FeatureFusionBlock_custom( + features2, + self.scratch.activation, + deconv=False, + bn=False, + expand=self.expand, + align_corners=align_corners) + self.scratch.refinenet1 = FeatureFusionBlock_custom( + features1, + self.scratch.activation, + deconv=False, + bn=False, + align_corners=align_corners) + + self.scratch.output_conv = nn.Sequential( + nn.Conv2d(features, + features // 2, + kernel_size=3, + stride=1, + padding=1, + groups=self.groups), + Interpolate(scale_factor=2, mode='bilinear'), + nn.Conv2d(features // 2, 32, kernel_size=3, stride=1, padding=1), + self.scratch.activation, + nn.Conv2d(32, 1, kernel_size=1, stride=1, padding=0), + nn.ReLU(True) if non_negative else nn.Identity(), + nn.Identity(), + ) + + if path: + self.load(path) + + def forward(self, x): + """Forward pass. + + Args: + x (tensor): input data (image) + + Returns: + tensor: depth + """ + if self.channels_last is True: + print('self.channels_last = ', self.channels_last) + x.contiguous(memory_format=torch.channels_last) + + layer_1 = self.pretrained.layer1(x) + layer_2 = self.pretrained.layer2(layer_1) + layer_3 = self.pretrained.layer3(layer_2) + layer_4 = self.pretrained.layer4(layer_3) + + layer_1_rn = self.scratch.layer1_rn(layer_1) + layer_2_rn = self.scratch.layer2_rn(layer_2) + layer_3_rn = self.scratch.layer3_rn(layer_3) + layer_4_rn = self.scratch.layer4_rn(layer_4) + + path_4 = self.scratch.refinenet4(layer_4_rn) + path_3 = self.scratch.refinenet3(path_4, layer_3_rn) + path_2 = self.scratch.refinenet2(path_3, layer_2_rn) + path_1 = self.scratch.refinenet1(path_2, layer_1_rn) + + out = self.scratch.output_conv(path_1) + + return torch.squeeze(out, dim=1) + + +def fuse_model(m): + prev_previous_type = nn.Identity() + prev_previous_name = '' + previous_type = nn.Identity() + previous_name = '' + for name, module in m.named_modules(): + if prev_previous_type == nn.Conv2d and previous_type == nn.BatchNorm2d and type( + module) == nn.ReLU: + # print("FUSED ", prev_previous_name, previous_name, name) + torch.quantization.fuse_modules( + m, [prev_previous_name, previous_name, name], inplace=True) + elif prev_previous_type == nn.Conv2d and previous_type == nn.BatchNorm2d: + # print("FUSED ", prev_previous_name, previous_name) + torch.quantization.fuse_modules( + m, [prev_previous_name, previous_name], inplace=True) + # elif previous_type == nn.Conv2d and type(module) == nn.ReLU: + # print("FUSED ", previous_name, name) + # torch.quantization.fuse_modules(m, [previous_name, name], inplace=True) + + prev_previous_type = previous_type + prev_previous_name = previous_name + previous_type = type(module) + previous_name = name diff --git a/scepter/modules/annotator/midas/transforms.py b/scepter/modules/annotator/midas/transforms.py new file mode 100644 index 0000000..c1da433 --- /dev/null +++ b/scepter/modules/annotator/midas/transforms.py @@ -0,0 +1,230 @@ +# -*- coding: utf-8 -*- +import math + +import cv2 +import numpy as np + + +def apply_min_size(sample, size, image_interpolation_method=cv2.INTER_AREA): + """Rezise the sample to ensure the given size. Keeps aspect ratio. + + Args: + sample (dict): sample + size (tuple): image size + + Returns: + tuple: new size + """ + shape = list(sample['disparity'].shape) + + if shape[0] >= size[0] and shape[1] >= size[1]: + return sample + + scale = [0, 0] + scale[0] = size[0] / shape[0] + scale[1] = size[1] / shape[1] + + scale = max(scale) + + shape[0] = math.ceil(scale * shape[0]) + shape[1] = math.ceil(scale * shape[1]) + + # resize + sample['image'] = cv2.resize(sample['image'], + tuple(shape[::-1]), + interpolation=image_interpolation_method) + + sample['disparity'] = cv2.resize(sample['disparity'], + tuple(shape[::-1]), + interpolation=cv2.INTER_NEAREST) + sample['mask'] = cv2.resize( + sample['mask'].astype(np.float32), + tuple(shape[::-1]), + interpolation=cv2.INTER_NEAREST, + ) + sample['mask'] = sample['mask'].astype(bool) + + return tuple(shape) + + +class Resize(object): + """Resize sample to given size (width, height). + """ + def __init__( + self, + width, + height, + resize_target=True, + keep_aspect_ratio=False, + ensure_multiple_of=1, + resize_method='lower_bound', + image_interpolation_method=cv2.INTER_AREA, + ): + """Init. + + Args: + width (int): desired output width + height (int): desired output height + resize_target (bool, optional): + True: Resize the full sample (image, mask, target). + False: Resize image only. + Defaults to True. + keep_aspect_ratio (bool, optional): + True: Keep the aspect ratio of the input sample. + Output sample might not have the given width and height, and + resize behaviour depends on the parameter 'resize_method'. + Defaults to False. + ensure_multiple_of (int, optional): + Output width and height is constrained to be multiple of this parameter. + Defaults to 1. + resize_method (str, optional): + "lower_bound": Output will be at least as large as the given size. + "upper_bound": Output will be at max as large as the given size. " + "(Output size might be smaller than given size.)" + "minimal": Scale as least as possible. (Output size might be smaller than given size.) + Defaults to "lower_bound". + """ + self.__width = width + self.__height = height + + self.__resize_target = resize_target + self.__keep_aspect_ratio = keep_aspect_ratio + self.__multiple_of = ensure_multiple_of + self.__resize_method = resize_method + self.__image_interpolation_method = image_interpolation_method + + def constrain_to_multiple_of(self, x, min_val=0, max_val=None): + y = (np.round(x / self.__multiple_of) * self.__multiple_of).astype(int) + + if max_val is not None and y > max_val: + y = (np.floor(x / self.__multiple_of) * + self.__multiple_of).astype(int) + + if y < min_val: + y = (np.ceil(x / self.__multiple_of) * + self.__multiple_of).astype(int) + + return y + + def get_size(self, width, height): + # determine new height and width + scale_height = self.__height / height + scale_width = self.__width / width + + if self.__keep_aspect_ratio: + if self.__resize_method == 'lower_bound': + # scale such that output size is lower bound + if scale_width > scale_height: + # fit width + scale_height = scale_width + else: + # fit height + scale_width = scale_height + elif self.__resize_method == 'upper_bound': + # scale such that output size is upper bound + if scale_width < scale_height: + # fit width + scale_height = scale_width + else: + # fit height + scale_width = scale_height + elif self.__resize_method == 'minimal': + # scale as least as possbile + if abs(1 - scale_width) < abs(1 - scale_height): + # fit width + scale_height = scale_width + else: + # fit height + scale_width = scale_height + else: + raise ValueError( + f'resize_method {self.__resize_method} not implemented') + + if self.__resize_method == 'lower_bound': + new_height = self.constrain_to_multiple_of(scale_height * height, + min_val=self.__height) + new_width = self.constrain_to_multiple_of(scale_width * width, + min_val=self.__width) + elif self.__resize_method == 'upper_bound': + new_height = self.constrain_to_multiple_of(scale_height * height, + max_val=self.__height) + new_width = self.constrain_to_multiple_of(scale_width * width, + max_val=self.__width) + elif self.__resize_method == 'minimal': + new_height = self.constrain_to_multiple_of(scale_height * height) + new_width = self.constrain_to_multiple_of(scale_width * width) + else: + raise ValueError( + f'resize_method {self.__resize_method} not implemented') + + return (new_width, new_height) + + def __call__(self, sample): + width, height = self.get_size(sample['image'].shape[1], + sample['image'].shape[0]) + + # resize sample + sample['image'] = cv2.resize( + sample['image'], + (width, height), + interpolation=self.__image_interpolation_method, + ) + + if self.__resize_target: + if 'disparity' in sample: + sample['disparity'] = cv2.resize( + sample['disparity'], + (width, height), + interpolation=cv2.INTER_NEAREST, + ) + + if 'depth' in sample: + sample['depth'] = cv2.resize(sample['depth'], (width, height), + interpolation=cv2.INTER_NEAREST) + + sample['mask'] = cv2.resize( + sample['mask'].astype(np.float32), + (width, height), + interpolation=cv2.INTER_NEAREST, + ) + sample['mask'] = sample['mask'].astype(bool) + + return sample + + +class NormalizeImage(object): + """Normlize image by given mean and std. + """ + def __init__(self, mean, std): + self.__mean = mean + self.__std = std + + def __call__(self, sample): + sample['image'] = (sample['image'] - self.__mean) / self.__std + + return sample + + +class PrepareForNet(object): + """Prepare sample for usage as network input. + """ + def __init__(self): + pass + + def __call__(self, sample): + image = np.transpose(sample['image'], (2, 0, 1)) + sample['image'] = np.ascontiguousarray(image).astype(np.float32) + + if 'mask' in sample: + sample['mask'] = sample['mask'].astype(np.float32) + sample['mask'] = np.ascontiguousarray(sample['mask']) + + if 'disparity' in sample: + disparity = sample['disparity'].astype(np.float32) + sample['disparity'] = np.ascontiguousarray(disparity) + + if 'depth' in sample: + depth = sample['depth'].astype(np.float32) + sample['depth'] = np.ascontiguousarray(depth) + + return sample diff --git a/scepter/modules/annotator/midas/utils.py b/scepter/modules/annotator/midas/utils.py new file mode 100644 index 0000000..6bf792a --- /dev/null +++ b/scepter/modules/annotator/midas/utils.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +"""Utils for monoDepth.""" +import re +import sys + +import cv2 +import numpy as np +import torch + + +def read_pfm(path): + """Read pfm file. + + Args: + path (str): path to file + + Returns: + tuple: (data, scale) + """ + with open(path, 'rb') as file: + + color = None + width = None + height = None + scale = None + endian = None + + header = file.readline().rstrip() + if header.decode('ascii') == 'PF': + color = True + elif header.decode('ascii') == 'Pf': + color = False + else: + raise Exception('Not a PFM file: ' + path) + + dim_match = re.match(r'^(\d+)\s(\d+)\s$', + file.readline().decode('ascii')) + if dim_match: + width, height = list(map(int, dim_match.groups())) + else: + raise Exception('Malformed PFM header.') + + scale = float(file.readline().decode('ascii').rstrip()) + if scale < 0: + # little-endian + endian = '<' + scale = -scale + else: + # big-endian + endian = '>' + + data = np.fromfile(file, endian + 'f') + shape = (height, width, 3) if color else (height, width) + + data = np.reshape(data, shape) + data = np.flipud(data) + + return data, scale + + +def write_pfm(path, image, scale=1): + """Write pfm file. + + Args: + path (str): pathto file + image (array): data + scale (int, optional): Scale. Defaults to 1. + """ + + with open(path, 'wb') as file: + color = None + + if image.dtype.name != 'float32': + raise Exception('Image dtype must be float32.') + + image = np.flipud(image) + + if len(image.shape) == 3 and image.shape[2] == 3: # color image + color = True + elif (len(image.shape) == 2 + or len(image.shape) == 3 and image.shape[2] == 1): # greyscale + color = False + else: + raise Exception( + 'Image must have H x W x 3, H x W x 1 or H x W dimensions.') + + file.write('PF\n' if color else 'Pf\n'.encode()) + file.write('%d %d\n'.encode() % (image.shape[1], image.shape[0])) + + endian = image.dtype.byteorder + + if endian == '<' or endian == '=' and sys.byteorder == 'little': + scale = -scale + + file.write('%f\n'.encode() % scale) + + image.tofile(file) + + +def read_image(path): + """Read image and output RGB image (0-1). + + Args: + path (str): path to file + + Returns: + array: RGB image (0-1) + """ + img = cv2.imread(path) + + if img.ndim == 2: + img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) + + img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) / 255.0 + + return img + + +def resize_image(img): + """Resize image and make it fit for network. + + Args: + img (array): image + + Returns: + tensor: data ready for network + """ + height_orig = img.shape[0] + width_orig = img.shape[1] + + if width_orig > height_orig: + scale = width_orig / 384 + else: + scale = height_orig / 384 + + height = (np.ceil(height_orig / scale / 32) * 32).astype(int) + width = (np.ceil(width_orig / scale / 32) * 32).astype(int) + + img_resized = cv2.resize(img, (width, height), + interpolation=cv2.INTER_AREA) + + img_resized = (torch.from_numpy(np.transpose( + img_resized, (2, 0, 1))).contiguous().float()) + img_resized = img_resized.unsqueeze(0) + + return img_resized + + +def resize_depth(depth, width, height): + """Resize depth map and bring to CPU (numpy). + + Args: + depth (tensor): depth + width (int): image width + height (int): image height + + Returns: + array: processed depth + """ + depth = torch.squeeze(depth[0, :, :, :]).to('cpu') + + depth_resized = cv2.resize(depth.numpy(), (width, height), + interpolation=cv2.INTER_CUBIC) + + return depth_resized + + +def write_depth(path, depth, bits=1): + """Write depth map to pfm and png file. + + Args: + path (str): filepath without extension + depth (array): depth + """ + write_pfm(path + '.pfm', depth.astype(np.float32)) + + depth_min = depth.min() + depth_max = depth.max() + + max_val = (2**(8 * bits)) - 1 + + if depth_max - depth_min > np.finfo('float').eps: + out = max_val * (depth - depth_min) / (depth_max - depth_min) + else: + out = np.zeros(depth.shape, dtype=depth.type) + + if bits == 1: + cv2.imwrite(path + '.png', out.astype('uint8')) + elif bits == 2: + cv2.imwrite(path + '.png', out.astype('uint16')) + + return diff --git a/scepter/modules/annotator/midas/vit.py b/scepter/modules/annotator/midas/vit.py new file mode 100644 index 0000000..4729b4b --- /dev/null +++ b/scepter/modules/annotator/midas/vit.py @@ -0,0 +1,509 @@ +# -*- coding: utf-8 -*- +import math +import types + +import timm +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class Slice(nn.Module): + def __init__(self, start_index=1): + super(Slice, self).__init__() + self.start_index = start_index + + def forward(self, x): + return x[:, self.start_index:] + + +class AddReadout(nn.Module): + def __init__(self, start_index=1): + super(AddReadout, self).__init__() + self.start_index = start_index + + def forward(self, x): + if self.start_index == 2: + readout = (x[:, 0] + x[:, 1]) / 2 + else: + readout = x[:, 0] + return x[:, self.start_index:] + readout.unsqueeze(1) + + +class ProjectReadout(nn.Module): + def __init__(self, in_features, start_index=1): + super(ProjectReadout, self).__init__() + self.start_index = start_index + + self.project = nn.Sequential(nn.Linear(2 * in_features, in_features), + nn.GELU()) + + def forward(self, x): + readout = x[:, 0].unsqueeze(1).expand_as(x[:, self.start_index:]) + features = torch.cat((x[:, self.start_index:], readout), -1) + + return self.project(features) + + +class Transpose(nn.Module): + def __init__(self, dim0, dim1): + super(Transpose, self).__init__() + self.dim0 = dim0 + self.dim1 = dim1 + + def forward(self, x): + x = x.transpose(self.dim0, self.dim1) + return x + + +def forward_vit(pretrained, x): + b, c, h, w = x.shape + + _ = pretrained.model.forward_flex(x) + + layer_1 = pretrained.activations['1'] + layer_2 = pretrained.activations['2'] + layer_3 = pretrained.activations['3'] + layer_4 = pretrained.activations['4'] + + layer_1 = pretrained.act_postprocess1[0:2](layer_1) + layer_2 = pretrained.act_postprocess2[0:2](layer_2) + layer_3 = pretrained.act_postprocess3[0:2](layer_3) + layer_4 = pretrained.act_postprocess4[0:2](layer_4) + + unflatten = nn.Sequential( + nn.Unflatten( + 2, + torch.Size([ + h // pretrained.model.patch_size[1], + w // pretrained.model.patch_size[0], + ]), + )) + + if layer_1.ndim == 3: + layer_1 = unflatten(layer_1) + if layer_2.ndim == 3: + layer_2 = unflatten(layer_2) + if layer_3.ndim == 3: + layer_3 = unflatten(layer_3) + if layer_4.ndim == 3: + layer_4 = unflatten(layer_4) + + layer_1 = pretrained.act_postprocess1[3:len(pretrained.act_postprocess1)]( + layer_1) + layer_2 = pretrained.act_postprocess2[3:len(pretrained.act_postprocess2)]( + layer_2) + layer_3 = pretrained.act_postprocess3[3:len(pretrained.act_postprocess3)]( + layer_3) + layer_4 = pretrained.act_postprocess4[3:len(pretrained.act_postprocess4)]( + layer_4) + + return layer_1, layer_2, layer_3, layer_4 + + +def _resize_pos_embed(self, posemb, gs_h, gs_w): + posemb_tok, posemb_grid = ( + posemb[:, :self.start_index], + posemb[0, self.start_index:], + ) + + gs_old = int(math.sqrt(len(posemb_grid))) + + posemb_grid = posemb_grid.reshape(1, gs_old, gs_old, + -1).permute(0, 3, 1, 2) + posemb_grid = F.interpolate(posemb_grid, + size=(gs_h, gs_w), + mode='bilinear') + posemb_grid = posemb_grid.permute(0, 2, 3, 1).reshape(1, gs_h * gs_w, -1) + + posemb = torch.cat([posemb_tok, posemb_grid], dim=1) + + return posemb + + +def forward_flex(self, x): + b, c, h, w = x.shape + + pos_embed = self._resize_pos_embed(self.pos_embed, h // self.patch_size[1], + w // self.patch_size[0]) + + B = x.shape[0] + + if hasattr(self.patch_embed, 'backbone'): + x = self.patch_embed.backbone(x) + if isinstance(x, (list, tuple)): + x = x[ + -1] # last feature if backbone outputs list/tuple of features + + x = self.patch_embed.proj(x).flatten(2).transpose(1, 2) + + if getattr(self, 'dist_token', None) is not None: + cls_tokens = self.cls_token.expand( + B, -1, -1) # stole cls_tokens impl from Phil Wang, thanks + dist_token = self.dist_token.expand(B, -1, -1) + x = torch.cat((cls_tokens, dist_token, x), dim=1) + else: + cls_tokens = self.cls_token.expand( + B, -1, -1) # stole cls_tokens impl from Phil Wang, thanks + x = torch.cat((cls_tokens, x), dim=1) + + x = x + pos_embed + x = self.pos_drop(x) + + for blk in self.blocks: + x = blk(x) + + x = self.norm(x) + + return x + + +activations = {} + + +def get_activation(name): + def hook(model, input, output): + activations[name] = output + + return hook + + +def get_readout_oper(vit_features, features, use_readout, start_index=1): + if use_readout == 'ignore': + readout_oper = [Slice(start_index)] * len(features) + elif use_readout == 'add': + readout_oper = [AddReadout(start_index)] * len(features) + elif use_readout == 'project': + readout_oper = [ + ProjectReadout(vit_features, start_index) for out_feat in features + ] + else: + assert ( + False + ), "wrong operation for readout token, use_readout can be 'ignore', 'add', or 'project'" + + return readout_oper + + +def _make_vit_b16_backbone( + model, + features=[96, 192, 384, 768], + size=[384, 384], + hooks=[2, 5, 8, 11], + vit_features=768, + use_readout='ignore', + start_index=1, +): + pretrained = nn.Module() + + pretrained.model = model + pretrained.model.blocks[hooks[0]].register_forward_hook( + get_activation('1')) + pretrained.model.blocks[hooks[1]].register_forward_hook( + get_activation('2')) + pretrained.model.blocks[hooks[2]].register_forward_hook( + get_activation('3')) + pretrained.model.blocks[hooks[3]].register_forward_hook( + get_activation('4')) + + pretrained.activations = activations + + readout_oper = get_readout_oper(vit_features, features, use_readout, + start_index) + + # 32, 48, 136, 384 + pretrained.act_postprocess1 = nn.Sequential( + readout_oper[0], + Transpose(1, 2), + nn.Unflatten(2, torch.Size([size[0] // 16, size[1] // 16])), + nn.Conv2d( + in_channels=vit_features, + out_channels=features[0], + kernel_size=1, + stride=1, + padding=0, + ), + nn.ConvTranspose2d( + in_channels=features[0], + out_channels=features[0], + kernel_size=4, + stride=4, + padding=0, + bias=True, + dilation=1, + groups=1, + ), + ) + + pretrained.act_postprocess2 = nn.Sequential( + readout_oper[1], + Transpose(1, 2), + nn.Unflatten(2, torch.Size([size[0] // 16, size[1] // 16])), + nn.Conv2d( + in_channels=vit_features, + out_channels=features[1], + kernel_size=1, + stride=1, + padding=0, + ), + nn.ConvTranspose2d( + in_channels=features[1], + out_channels=features[1], + kernel_size=2, + stride=2, + padding=0, + bias=True, + dilation=1, + groups=1, + ), + ) + + pretrained.act_postprocess3 = nn.Sequential( + readout_oper[2], + Transpose(1, 2), + nn.Unflatten(2, torch.Size([size[0] // 16, size[1] // 16])), + nn.Conv2d( + in_channels=vit_features, + out_channels=features[2], + kernel_size=1, + stride=1, + padding=0, + ), + ) + + pretrained.act_postprocess4 = nn.Sequential( + readout_oper[3], + Transpose(1, 2), + nn.Unflatten(2, torch.Size([size[0] // 16, size[1] // 16])), + nn.Conv2d( + in_channels=vit_features, + out_channels=features[3], + kernel_size=1, + stride=1, + padding=0, + ), + nn.Conv2d( + in_channels=features[3], + out_channels=features[3], + kernel_size=3, + stride=2, + padding=1, + ), + ) + + pretrained.model.start_index = start_index + pretrained.model.patch_size = [16, 16] + + # We inject this function into the VisionTransformer instances so that + # we can use it with interpolated position embeddings without modifying the library source. + pretrained.model.forward_flex = types.MethodType(forward_flex, + pretrained.model) + pretrained.model._resize_pos_embed = types.MethodType( + _resize_pos_embed, pretrained.model) + + return pretrained + + +def _make_pretrained_vitl16_384(pretrained, use_readout='ignore', hooks=None): + model = timm.create_model('vit_large_patch16_384', pretrained=pretrained) + + hooks = [5, 11, 17, 23] if hooks is None else hooks + return _make_vit_b16_backbone( + model, + features=[256, 512, 1024, 1024], + hooks=hooks, + vit_features=1024, + use_readout=use_readout, + ) + + +def _make_pretrained_vitb16_384(pretrained, use_readout='ignore', hooks=None): + model = timm.create_model('vit_base_patch16_384', pretrained=pretrained) + + hooks = [2, 5, 8, 11] if hooks is None else hooks + return _make_vit_b16_backbone(model, + features=[96, 192, 384, 768], + hooks=hooks, + use_readout=use_readout) + + +def _make_pretrained_deitb16_384(pretrained, use_readout='ignore', hooks=None): + model = timm.create_model('vit_deit_base_patch16_384', + pretrained=pretrained) + + hooks = [2, 5, 8, 11] if hooks is None else hooks + return _make_vit_b16_backbone(model, + features=[96, 192, 384, 768], + hooks=hooks, + use_readout=use_readout) + + +def _make_pretrained_deitb16_distil_384(pretrained, + use_readout='ignore', + hooks=None): + model = timm.create_model('vit_deit_base_distilled_patch16_384', + pretrained=pretrained) + + hooks = [2, 5, 8, 11] if hooks is None else hooks + return _make_vit_b16_backbone( + model, + features=[96, 192, 384, 768], + hooks=hooks, + use_readout=use_readout, + start_index=2, + ) + + +def _make_vit_b_rn50_backbone( + model, + features=[256, 512, 768, 768], + size=[384, 384], + hooks=[0, 1, 8, 11], + vit_features=768, + use_vit_only=False, + use_readout='ignore', + start_index=1, +): + pretrained = nn.Module() + + pretrained.model = model + + if use_vit_only is True: + pretrained.model.blocks[hooks[0]].register_forward_hook( + get_activation('1')) + pretrained.model.blocks[hooks[1]].register_forward_hook( + get_activation('2')) + else: + pretrained.model.patch_embed.backbone.stages[0].register_forward_hook( + get_activation('1')) + pretrained.model.patch_embed.backbone.stages[1].register_forward_hook( + get_activation('2')) + + pretrained.model.blocks[hooks[2]].register_forward_hook( + get_activation('3')) + pretrained.model.blocks[hooks[3]].register_forward_hook( + get_activation('4')) + + pretrained.activations = activations + + readout_oper = get_readout_oper(vit_features, features, use_readout, + start_index) + + if use_vit_only is True: + pretrained.act_postprocess1 = nn.Sequential( + readout_oper[0], + Transpose(1, 2), + nn.Unflatten(2, torch.Size([size[0] // 16, size[1] // 16])), + nn.Conv2d( + in_channels=vit_features, + out_channels=features[0], + kernel_size=1, + stride=1, + padding=0, + ), + nn.ConvTranspose2d( + in_channels=features[0], + out_channels=features[0], + kernel_size=4, + stride=4, + padding=0, + bias=True, + dilation=1, + groups=1, + ), + ) + + pretrained.act_postprocess2 = nn.Sequential( + readout_oper[1], + Transpose(1, 2), + nn.Unflatten(2, torch.Size([size[0] // 16, size[1] // 16])), + nn.Conv2d( + in_channels=vit_features, + out_channels=features[1], + kernel_size=1, + stride=1, + padding=0, + ), + nn.ConvTranspose2d( + in_channels=features[1], + out_channels=features[1], + kernel_size=2, + stride=2, + padding=0, + bias=True, + dilation=1, + groups=1, + ), + ) + else: + pretrained.act_postprocess1 = nn.Sequential(nn.Identity(), + nn.Identity(), + nn.Identity()) + pretrained.act_postprocess2 = nn.Sequential(nn.Identity(), + nn.Identity(), + nn.Identity()) + + pretrained.act_postprocess3 = nn.Sequential( + readout_oper[2], + Transpose(1, 2), + nn.Unflatten(2, torch.Size([size[0] // 16, size[1] // 16])), + nn.Conv2d( + in_channels=vit_features, + out_channels=features[2], + kernel_size=1, + stride=1, + padding=0, + ), + ) + + pretrained.act_postprocess4 = nn.Sequential( + readout_oper[3], + Transpose(1, 2), + nn.Unflatten(2, torch.Size([size[0] // 16, size[1] // 16])), + nn.Conv2d( + in_channels=vit_features, + out_channels=features[3], + kernel_size=1, + stride=1, + padding=0, + ), + nn.Conv2d( + in_channels=features[3], + out_channels=features[3], + kernel_size=3, + stride=2, + padding=1, + ), + ) + + pretrained.model.start_index = start_index + pretrained.model.patch_size = [16, 16] + + # We inject this function into the VisionTransformer instances so that + # we can use it with interpolated position embeddings without modifying the library source. + pretrained.model.forward_flex = types.MethodType(forward_flex, + pretrained.model) + + # We inject this function into the VisionTransformer instances so that + # we can use it with interpolated position embeddings without modifying the library source. + pretrained.model._resize_pos_embed = types.MethodType( + _resize_pos_embed, pretrained.model) + + return pretrained + + +def _make_pretrained_vitb_rn50_384(pretrained, + use_readout='ignore', + hooks=None, + use_vit_only=False): + model = timm.create_model('vit_base_resnet50_384', pretrained=pretrained) + + hooks = [0, 1, 8, 11] if hooks is None else hooks + return _make_vit_b_rn50_backbone( + model, + features=[256, 512, 768, 768], + size=[384, 384], + hooks=hooks, + use_vit_only=use_vit_only, + use_readout=use_readout, + ) diff --git a/scepter/modules/annotator/midas_op.py b/scepter/modules/annotator/midas_op.py new file mode 100644 index 0000000..09a883d --- /dev/null +++ b/scepter/modules/annotator/midas_op.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Midas Depth Estimation +# From https://github.com/isl-org/MiDaS +# MIT LICENSE +from abc import ABCMeta + +import numpy as np +import torch +from einops import rearrange +from PIL import Image + +from scepter.modules.annotator.base_annotator import BaseAnnotator +from scepter.modules.annotator.midas.api import MiDaSInference +from scepter.modules.annotator.registry import ANNOTATORS +from scepter.modules.annotator.utils import resize_image, resize_image_ori +from scepter.modules.utils.config import dict_to_yaml +from scepter.modules.utils.distribute import we +from scepter.modules.utils.file_system import FS + + +@ANNOTATORS.register_class() +class MidasDetector(BaseAnnotator, metaclass=ABCMeta): + def __init__(self, cfg, logger=None): + super().__init__(cfg, logger=logger) + pretrained_model = cfg.get('PRETRAINED_MODEL', None) + if pretrained_model: + with FS.get_from(pretrained_model, wait_finish=True) as local_path: + self.model = MiDaSInference(model_type='dpt_hybrid', + model_path=local_path) + self.a = cfg.get('A', np.pi * 2.0) + self.bg_th = cfg.get('BG_TH', 0.1) + + @torch.no_grad() + @torch.inference_mode() + @torch.autocast('cuda', enabled=False) + def forward(self, image): + if isinstance(image, Image.Image): + image = np.array(image) + elif isinstance(image, torch.Tensor): + image = image.detach().cpu().numpy() + elif isinstance(image, np.ndarray): + image = image.copy() + else: + raise f'Unsurpport datatype{type(image)}, only surpport np.ndarray, torch.Tensor, Pillow Image.' + image_depth = image + h, w, c = image.shape + image_depth, k = resize_image(image_depth, + 1024 if min(h, w) > 1024 else min(h, w)) + image_depth = torch.from_numpy(image_depth).float().to(we.device_id) + image_depth = image_depth / 127.5 - 1.0 + image_depth = rearrange(image_depth, 'h w c -> 1 c h w') + depth = self.model(image_depth)[0] + + depth_pt = depth.clone() + depth_pt -= torch.min(depth_pt) + depth_pt /= torch.max(depth_pt) + depth_pt = depth_pt.cpu().numpy() + depth_image = (depth_pt * 255.0).clip(0, 255).astype(np.uint8) + depth_image = depth_image[..., None].repeat(3, 2) + + # depth_np = depth.cpu().numpy() # float16 error + # x = cv2.Sobel(depth_np, cv2.CV_32F, 1, 0, ksize=3) + # y = cv2.Sobel(depth_np, cv2.CV_32F, 0, 1, ksize=3) + # z = np.ones_like(x) * self.a + # x[depth_pt < self.bg_th] = 0 + # y[depth_pt < self.bg_th] = 0 + # normal = np.stack([x, y, z], axis=2) + # normal /= np.sum(normal**2.0, axis=2, keepdims=True)**0.5 + # normal_image = (normal * 127.5 + 127.5).clip(0, 255).astype(np.uint8) + depth_image = resize_image_ori(h, w, depth_image, k) + return depth_image + + @staticmethod + def get_config_template(): + return dict_to_yaml('ANNOTATORS', + __class__.__name__, + MidasDetector.para_dict, + set_name=True) diff --git a/scepter/modules/annotator/mlsd/__init__.py b/scepter/modules/annotator/mlsd/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/modules/annotator/mlsd/mbv2_mlsd_large.py b/scepter/modules/annotator/mlsd/mbv2_mlsd_large.py new file mode 100644 index 0000000..7555e93 --- /dev/null +++ b/scepter/modules/annotator/mlsd/mbv2_mlsd_large.py @@ -0,0 +1,303 @@ +# -*- coding: utf-8 -*- + +import torch +import torch.nn as nn +import torch.utils.model_zoo as model_zoo +from torch.nn import functional as F + + +class BlockTypeA(nn.Module): + def __init__(self, in_c1, in_c2, out_c1, out_c2, upscale=True): + super(BlockTypeA, self).__init__() + self.conv1 = nn.Sequential(nn.Conv2d(in_c2, out_c2, kernel_size=1), + nn.BatchNorm2d(out_c2), + nn.ReLU(inplace=True)) + self.conv2 = nn.Sequential(nn.Conv2d(in_c1, out_c1, kernel_size=1), + nn.BatchNorm2d(out_c1), + nn.ReLU(inplace=True)) + self.upscale = upscale + + def forward(self, a, b): + b = self.conv1(b) + a = self.conv2(a) + if self.upscale: + b = F.interpolate(b, + scale_factor=2.0, + mode='bilinear', + align_corners=True) + return torch.cat((a, b), dim=1) + + +class BlockTypeB(nn.Module): + def __init__(self, in_c, out_c): + super(BlockTypeB, self).__init__() + self.conv1 = nn.Sequential( + nn.Conv2d(in_c, in_c, kernel_size=3, padding=1), + nn.BatchNorm2d(in_c), nn.ReLU()) + self.conv2 = nn.Sequential( + nn.Conv2d(in_c, out_c, kernel_size=3, padding=1), + nn.BatchNorm2d(out_c), nn.ReLU()) + + def forward(self, x): + x = self.conv1(x) + x + x = self.conv2(x) + return x + + +class BlockTypeC(nn.Module): + def __init__(self, in_c, out_c): + super(BlockTypeC, self).__init__() + self.conv1 = nn.Sequential( + nn.Conv2d(in_c, in_c, kernel_size=3, padding=5, dilation=5), + nn.BatchNorm2d(in_c), nn.ReLU()) + self.conv2 = nn.Sequential( + nn.Conv2d(in_c, in_c, kernel_size=3, padding=1), + nn.BatchNorm2d(in_c), nn.ReLU()) + self.conv3 = nn.Conv2d(in_c, out_c, kernel_size=1) + + def forward(self, x): + x = self.conv1(x) + x = self.conv2(x) + x = self.conv3(x) + return x + + +def _make_divisible(v, divisor, min_value=None): + """ + This function is taken from the original tf repo. + It ensures that all layers have a channel number that is divisible by 8 + It can be seen here: + https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py + :param v: + :param divisor: + :param min_value: + :return: + """ + if min_value is None: + min_value = divisor + new_v = max(min_value, int(v + divisor / 2) // divisor * divisor) + # Make sure that round down does not go down by more than 10%. + if new_v < 0.9 * v: + new_v += divisor + return new_v + + +class ConvBNReLU(nn.Sequential): + def __init__(self, + in_planes, + out_planes, + kernel_size=3, + stride=1, + groups=1): + self.channel_pad = out_planes - in_planes + self.stride = stride + # padding = (kernel_size - 1) // 2 + + # TFLite uses slightly different padding than PyTorch + if stride == 2: + padding = 0 + else: + padding = (kernel_size - 1) // 2 + + super(ConvBNReLU, self).__init__( + nn.Conv2d(in_planes, + out_planes, + kernel_size, + stride, + padding, + groups=groups, + bias=False), nn.BatchNorm2d(out_planes), + nn.ReLU6(inplace=True)) + self.max_pool = nn.MaxPool2d(kernel_size=stride, stride=stride) + + def forward(self, x): + # TFLite uses different padding + if self.stride == 2: + x = F.pad(x, (0, 1, 0, 1), 'constant', 0) + # print(x.shape) + + for module in self: + if not isinstance(module, nn.MaxPool2d): + x = module(x) + return x + + +class InvertedResidual(nn.Module): + def __init__(self, inp, oup, stride, expand_ratio): + super(InvertedResidual, self).__init__() + self.stride = stride + assert stride in [1, 2] + + hidden_dim = int(round(inp * expand_ratio)) + self.use_res_connect = self.stride == 1 and inp == oup + + layers = [] + if expand_ratio != 1: + # pw + layers.append(ConvBNReLU(inp, hidden_dim, kernel_size=1)) + layers.extend([ + # dw + ConvBNReLU(hidden_dim, + hidden_dim, + stride=stride, + groups=hidden_dim), + # pw-linear + nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False), + nn.BatchNorm2d(oup), + ]) + self.conv = nn.Sequential(*layers) + + def forward(self, x): + if self.use_res_connect: + return x + self.conv(x) + else: + return self.conv(x) + + +class MobileNetV2(nn.Module): + def __init__(self, pretrained=True): + """ + MobileNet V2 main class + Args: + num_classes (int): Number of classes + width_mult (float): Width multiplier - adjusts number of channels in each layer by this amount + inverted_residual_setting: Network structure + round_nearest (int): Round the number of channels in each layer to be a multiple of this number + Set to 1 to turn off rounding + block: Module specifying inverted residual building block for mobilenet + """ + super(MobileNetV2, self).__init__() + + block = InvertedResidual + input_channel = 32 + last_channel = 1280 + width_mult = 1.0 + round_nearest = 8 + + inverted_residual_setting = [ + # t, c, n, s + [1, 16, 1, 1], + [6, 24, 2, 2], + [6, 32, 3, 2], + [6, 64, 4, 2], + [6, 96, 3, 1], + # [6, 160, 3, 2], + # [6, 320, 1, 1], + ] + + # only check the first element, assuming user knows t,c,n,s are required + if len(inverted_residual_setting) == 0 or len( + inverted_residual_setting[0]) != 4: + raise ValueError('inverted_residual_setting should be non-empty ' + 'or a 4-element list, got {}'.format( + inverted_residual_setting)) + + # building first layer + input_channel = _make_divisible(input_channel * width_mult, + round_nearest) + self.last_channel = _make_divisible( + last_channel * max(1.0, width_mult), round_nearest) + features = [ConvBNReLU(4, input_channel, stride=2)] + # building inverted residual blocks + for t, c, n, s in inverted_residual_setting: + output_channel = _make_divisible(c * width_mult, round_nearest) + for i in range(n): + stride = s if i == 0 else 1 + features.append( + block(input_channel, + output_channel, + stride, + expand_ratio=t)) + input_channel = output_channel + + self.features = nn.Sequential(*features) + self.fpn_selected = [1, 3, 6, 10, 13] + # weight initialization + for m in self.modules(): + if isinstance(m, nn.Conv2d): + nn.init.kaiming_normal_(m.weight, mode='fan_out') + if m.bias is not None: + nn.init.zeros_(m.bias) + elif isinstance(m, nn.BatchNorm2d): + nn.init.ones_(m.weight) + nn.init.zeros_(m.bias) + elif isinstance(m, nn.Linear): + nn.init.normal_(m.weight, 0, 0.01) + nn.init.zeros_(m.bias) + if pretrained: + self._load_pretrained_model() + + def _forward_impl(self, x): + # This exists since TorchScript doesn't support inheritance, so the superclass method + # (this one) needs to have a name other than `forward` that can be accessed in a subclass + fpn_features = [] + for i, f in enumerate(self.features): + if i > self.fpn_selected[-1]: + break + x = f(x) + if i in self.fpn_selected: + fpn_features.append(x) + + c1, c2, c3, c4, c5 = fpn_features + return c1, c2, c3, c4, c5 + + def forward(self, x): + return self._forward_impl(x) + + def _load_pretrained_model(self): + pretrain_dict = model_zoo.load_url( + 'https://download.pytorch.org/models/mobilenet_v2-b0353104.pth') + model_dict = {} + state_dict = self.state_dict() + for k, v in pretrain_dict.items(): + if k in state_dict: + model_dict[k] = v + state_dict.update(model_dict) + self.load_state_dict(state_dict) + + +class MobileV2_MLSD_Large(nn.Module): + def __init__(self): + super(MobileV2_MLSD_Large, self).__init__() + + self.backbone = MobileNetV2(pretrained=False) + # A, B + self.block15 = BlockTypeA(in_c1=64, + in_c2=96, + out_c1=64, + out_c2=64, + upscale=False) + self.block16 = BlockTypeB(128, 64) + + # A, B + self.block17 = BlockTypeA(in_c1=32, in_c2=64, out_c1=64, out_c2=64) + self.block18 = BlockTypeB(128, 64) + + # A, B + self.block19 = BlockTypeA(in_c1=24, in_c2=64, out_c1=64, out_c2=64) + self.block20 = BlockTypeB(128, 64) + + # A, B, C + self.block21 = BlockTypeA(in_c1=16, in_c2=64, out_c1=64, out_c2=64) + self.block22 = BlockTypeB(128, 64) + + self.block23 = BlockTypeC(64, 16) + + def forward(self, x): + c1, c2, c3, c4, c5 = self.backbone(x) + + x = self.block15(c4, c5) + x = self.block16(x) + + x = self.block17(c3, x) + x = self.block18(x) + + x = self.block19(c2, x) + x = self.block20(x) + + x = self.block21(c1, x) + x = self.block22(x) + x = self.block23(x) + x = x[:, 7:, :, :] + + return x diff --git a/scepter/modules/annotator/mlsd/mbv2_mlsd_tiny.py b/scepter/modules/annotator/mlsd/mbv2_mlsd_tiny.py new file mode 100644 index 0000000..4e906c5 --- /dev/null +++ b/scepter/modules/annotator/mlsd/mbv2_mlsd_tiny.py @@ -0,0 +1,287 @@ +# -*- coding: utf-8 -*- +import torch +import torch.nn as nn +import torch.utils.model_zoo as model_zoo +from torch.nn import functional as F + + +class BlockTypeA(nn.Module): + def __init__(self, in_c1, in_c2, out_c1, out_c2, upscale=True): + super(BlockTypeA, self).__init__() + self.conv1 = nn.Sequential(nn.Conv2d(in_c2, out_c2, kernel_size=1), + nn.BatchNorm2d(out_c2), + nn.ReLU(inplace=True)) + self.conv2 = nn.Sequential(nn.Conv2d(in_c1, out_c1, kernel_size=1), + nn.BatchNorm2d(out_c1), + nn.ReLU(inplace=True)) + self.upscale = upscale + + def forward(self, a, b): + b = self.conv1(b) + a = self.conv2(a) + b = F.interpolate(b, + scale_factor=2.0, + mode='bilinear', + align_corners=True) + return torch.cat((a, b), dim=1) + + +class BlockTypeB(nn.Module): + def __init__(self, in_c, out_c): + super(BlockTypeB, self).__init__() + self.conv1 = nn.Sequential( + nn.Conv2d(in_c, in_c, kernel_size=3, padding=1), + nn.BatchNorm2d(in_c), nn.ReLU()) + self.conv2 = nn.Sequential( + nn.Conv2d(in_c, out_c, kernel_size=3, padding=1), + nn.BatchNorm2d(out_c), nn.ReLU()) + + def forward(self, x): + x = self.conv1(x) + x + x = self.conv2(x) + return x + + +class BlockTypeC(nn.Module): + def __init__(self, in_c, out_c): + super(BlockTypeC, self).__init__() + self.conv1 = nn.Sequential( + nn.Conv2d(in_c, in_c, kernel_size=3, padding=5, dilation=5), + nn.BatchNorm2d(in_c), nn.ReLU()) + self.conv2 = nn.Sequential( + nn.Conv2d(in_c, in_c, kernel_size=3, padding=1), + nn.BatchNorm2d(in_c), nn.ReLU()) + self.conv3 = nn.Conv2d(in_c, out_c, kernel_size=1) + + def forward(self, x): + x = self.conv1(x) + x = self.conv2(x) + x = self.conv3(x) + return x + + +def _make_divisible(v, divisor, min_value=None): + """ + This function is taken from the original tf repo. + It ensures that all layers have a channel number that is divisible by 8 + It can be seen here: + https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py + :param v: + :param divisor: + :param min_value: + :return: + """ + if min_value is None: + min_value = divisor + new_v = max(min_value, int(v + divisor / 2) // divisor * divisor) + # Make sure that round down does not go down by more than 10%. + if new_v < 0.9 * v: + new_v += divisor + return new_v + + +class ConvBNReLU(nn.Sequential): + def __init__(self, + in_planes, + out_planes, + kernel_size=3, + stride=1, + groups=1): + self.channel_pad = out_planes - in_planes + self.stride = stride + # padding = (kernel_size - 1) // 2 + + # TFLite uses slightly different padding than PyTorch + if stride == 2: + padding = 0 + else: + padding = (kernel_size - 1) // 2 + + super(ConvBNReLU, self).__init__( + nn.Conv2d(in_planes, + out_planes, + kernel_size, + stride, + padding, + groups=groups, + bias=False), nn.BatchNorm2d(out_planes), + nn.ReLU6(inplace=True)) + self.max_pool = nn.MaxPool2d(kernel_size=stride, stride=stride) + + def forward(self, x): + # TFLite uses different padding + if self.stride == 2: + x = F.pad(x, (0, 1, 0, 1), 'constant', 0) + # print(x.shape) + + for module in self: + if not isinstance(module, nn.MaxPool2d): + x = module(x) + return x + + +class InvertedResidual(nn.Module): + def __init__(self, inp, oup, stride, expand_ratio): + super(InvertedResidual, self).__init__() + self.stride = stride + assert stride in [1, 2] + + hidden_dim = int(round(inp * expand_ratio)) + self.use_res_connect = self.stride == 1 and inp == oup + + layers = [] + if expand_ratio != 1: + # pw + layers.append(ConvBNReLU(inp, hidden_dim, kernel_size=1)) + layers.extend([ + # dw + ConvBNReLU(hidden_dim, + hidden_dim, + stride=stride, + groups=hidden_dim), + # pw-linear + nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False), + nn.BatchNorm2d(oup), + ]) + self.conv = nn.Sequential(*layers) + + def forward(self, x): + if self.use_res_connect: + return x + self.conv(x) + else: + return self.conv(x) + + +class MobileNetV2(nn.Module): + def __init__(self, pretrained=True): + """ + MobileNet V2 main class + Args: + num_classes (int): Number of classes + width_mult (float): Width multiplier - adjusts number of channels in each layer by this amount + inverted_residual_setting: Network structure + round_nearest (int): Round the number of channels in each layer to be a multiple of this number + Set to 1 to turn off rounding + block: Module specifying inverted residual building block for mobilenet + """ + super(MobileNetV2, self).__init__() + + block = InvertedResidual + input_channel = 32 + last_channel = 1280 + width_mult = 1.0 + round_nearest = 8 + + inverted_residual_setting = [ + # t, c, n, s + [1, 16, 1, 1], + [6, 24, 2, 2], + [6, 32, 3, 2], + [6, 64, 4, 2], + # [6, 96, 3, 1], + # [6, 160, 3, 2], + # [6, 320, 1, 1], + ] + + # only check the first element, assuming user knows t,c,n,s are required + if len(inverted_residual_setting) == 0 or len( + inverted_residual_setting[0]) != 4: + raise ValueError('inverted_residual_setting should be non-empty ' + 'or a 4-element list, got {}'.format( + inverted_residual_setting)) + + # building first layer + input_channel = _make_divisible(input_channel * width_mult, + round_nearest) + self.last_channel = _make_divisible( + last_channel * max(1.0, width_mult), round_nearest) + features = [ConvBNReLU(4, input_channel, stride=2)] + # building inverted residual blocks + for t, c, n, s in inverted_residual_setting: + output_channel = _make_divisible(c * width_mult, round_nearest) + for i in range(n): + stride = s if i == 0 else 1 + features.append( + block(input_channel, + output_channel, + stride, + expand_ratio=t)) + input_channel = output_channel + self.features = nn.Sequential(*features) + + self.fpn_selected = [3, 6, 10] + # weight initialization + for m in self.modules(): + if isinstance(m, nn.Conv2d): + nn.init.kaiming_normal_(m.weight, mode='fan_out') + if m.bias is not None: + nn.init.zeros_(m.bias) + elif isinstance(m, nn.BatchNorm2d): + nn.init.ones_(m.weight) + nn.init.zeros_(m.bias) + elif isinstance(m, nn.Linear): + nn.init.normal_(m.weight, 0, 0.01) + nn.init.zeros_(m.bias) + + # if pretrained: + # self._load_pretrained_model() + + def _forward_impl(self, x): + # This exists since TorchScript doesn't support inheritance, so the superclass method + # (this one) needs to have a name other than `forward` that can be accessed in a subclass + fpn_features = [] + for i, f in enumerate(self.features): + if i > self.fpn_selected[-1]: + break + x = f(x) + if i in self.fpn_selected: + fpn_features.append(x) + + c2, c3, c4 = fpn_features + return c2, c3, c4 + + def forward(self, x): + return self._forward_impl(x) + + def _load_pretrained_model(self): + pretrain_dict = model_zoo.load_url( + 'https://download.pytorch.org/models/mobilenet_v2-b0353104.pth') + model_dict = {} + state_dict = self.state_dict() + for k, v in pretrain_dict.items(): + if k in state_dict: + model_dict[k] = v + state_dict.update(model_dict) + self.load_state_dict(state_dict) + + +class MobileV2_MLSD_Tiny(nn.Module): + def __init__(self): + super(MobileV2_MLSD_Tiny, self).__init__() + + self.backbone = MobileNetV2(pretrained=True) + + self.block12 = BlockTypeA(in_c1=32, in_c2=64, out_c1=64, out_c2=64) + self.block13 = BlockTypeB(128, 64) + + self.block14 = BlockTypeA(in_c1=24, in_c2=64, out_c1=32, out_c2=32) + self.block15 = BlockTypeB(64, 64) + + self.block16 = BlockTypeC(64, 16) + + def forward(self, x): + c2, c3, c4 = self.backbone(x) + + x = self.block12(c3, c4) + x = self.block13(x) + x = self.block14(c2, x) + x = self.block15(x) + x = self.block16(x) + x = x[:, 7:, :, :] + # print(x.shape) + x = F.interpolate(x, + scale_factor=2.0, + mode='bilinear', + align_corners=True) + + return x diff --git a/scepter/modules/annotator/mlsd/utils.py b/scepter/modules/annotator/mlsd/utils.py new file mode 100644 index 0000000..83bad84 --- /dev/null +++ b/scepter/modules/annotator/mlsd/utils.py @@ -0,0 +1,638 @@ +# -*- coding: utf-8 -*- + +# modified by lihaoweicv +# pytorch version +# +# M-LSD +# Copyright 2021-present NAVER Corp. +# Apache License v2.0 + +import cv2 +import numpy as np +import torch +from torch.nn import functional as F + + +def deccode_output_score_and_ptss(tpMap, topk_n=200, ksize=5): + ''' + tpMap: + center: tpMap[1, 0, :, :] + displacement: tpMap[1, 1:5, :, :] + ''' + b, c, h, w = tpMap.shape + assert b == 1, 'only support bsize==1' + displacement = tpMap[:, 1:5, :, :][0] + center = tpMap[:, 0, :, :] + heat = torch.sigmoid(center) + hmax = F.max_pool2d(heat, (ksize, ksize), + stride=1, + padding=(ksize - 1) // 2) + keep = (hmax == heat).float() + heat = heat * keep + heat = heat.reshape(-1, ) + + scores, indices = torch.topk(heat, topk_n, dim=-1, largest=True) + yy = torch.floor_divide(indices, w).unsqueeze(-1) + xx = torch.fmod(indices, w).unsqueeze(-1) + ptss = torch.cat((yy, xx), dim=-1) + + ptss = ptss.detach().cpu().numpy() + scores = scores.detach().cpu().numpy() + displacement = displacement.detach().cpu().numpy() + displacement = displacement.transpose((1, 2, 0)) + return ptss, scores, displacement + + +def pred_lines(image, + model, + input_shape=[512, 512], + score_thr=0.10, + dist_thr=20.0, + device='cuda'): + h, w, _ = image.shape + h_ratio, w_ratio = [h / input_shape[0], w / input_shape[1]] + + resized_image = np.concatenate([ + cv2.resize(image, (input_shape[1], input_shape[0]), + interpolation=cv2.INTER_AREA), + np.ones([input_shape[0], input_shape[1], 1]) + ], + axis=-1) + + resized_image = resized_image.transpose((2, 0, 1)) + batch_image = np.expand_dims(resized_image, axis=0).astype('float32') + batch_image = (batch_image / 127.5) - 1.0 + + batch_image = torch.from_numpy(batch_image).float().to(device) + outputs = model(batch_image) + pts, pts_score, vmap = deccode_output_score_and_ptss(outputs, 200, 3) + start = vmap[:, :, :2] + end = vmap[:, :, 2:] + dist_map = np.sqrt(np.sum((start - end)**2, axis=-1)) + + segments_list = [] + for center, score in zip(pts, pts_score): + y, x = center + distance = dist_map[y, x] + if score > score_thr and distance > dist_thr: + disp_x_start, disp_y_start, disp_x_end, disp_y_end = vmap[y, x, :] + x_start = x + disp_x_start + y_start = y + disp_y_start + x_end = x + disp_x_end + y_end = y + disp_y_end + segments_list.append([x_start, y_start, x_end, y_end]) + + lines = 2 * np.array(segments_list) # 256 > 512 + lines[:, 0] = lines[:, 0] * w_ratio + lines[:, 1] = lines[:, 1] * h_ratio + lines[:, 2] = lines[:, 2] * w_ratio + lines[:, 3] = lines[:, 3] * h_ratio + + return lines + + +def pred_squares( + image, + model, + input_shape=[512, 512], + device='cuda', + params={ + 'score': 0.06, + 'outside_ratio': 0.28, + 'inside_ratio': 0.45, + 'w_overlap': 0.0, + 'w_degree': 1.95, + 'w_length': 0.0, + 'w_area': 1.86, + 'w_center': 0.14 + }): # noqa + # shape = [height, width] + h, w, _ = image.shape + original_shape = [h, w] + + resized_image = np.concatenate([ + cv2.resize(image, (input_shape[0], input_shape[1]), + interpolation=cv2.INTER_AREA), + np.ones([input_shape[0], input_shape[1], 1]) + ], + axis=-1) + resized_image = resized_image.transpose((2, 0, 1)) + batch_image = np.expand_dims(resized_image, axis=0).astype('float32') + batch_image = (batch_image / 127.5) - 1.0 + + batch_image = torch.from_numpy(batch_image).float().to(device) + outputs = model(batch_image) + + pts, pts_score, vmap = deccode_output_score_and_ptss(outputs, 200, 3) + start = vmap[:, :, :2] # (x, y) + end = vmap[:, :, 2:] # (x, y) + dist_map = np.sqrt(np.sum((start - end)**2, axis=-1)) + + junc_list = [] + segments_list = [] + for junc, score in zip(pts, pts_score): + y, x = junc + distance = dist_map[y, x] + if score > params['score'] and distance > 20.0: + junc_list.append([x, y]) + disp_x_start, disp_y_start, disp_x_end, disp_y_end = vmap[y, x, :] + d_arrow = 1.0 + x_start = x + d_arrow * disp_x_start + y_start = y + d_arrow * disp_y_start + x_end = x + d_arrow * disp_x_end + y_end = y + d_arrow * disp_y_end + segments_list.append([x_start, y_start, x_end, y_end]) + + segments = np.array(segments_list) + + # post processing for squares + # 1. get unique lines + point = np.array([[0, 0]]) + point = point[0] + start = segments[:, :2] + end = segments[:, 2:] + diff = start - end + a = diff[:, 1] + b = -diff[:, 0] + c = a * start[:, 0] + b * start[:, 1] + + d = np.abs(a * point[0] + b * point[1] - c) / np.sqrt(a**2 + b**2 + 1e-10) + theta = np.arctan2(diff[:, 0], diff[:, 1]) * 180 / np.pi + theta[theta < 0.0] += 180 + hough = np.concatenate([d[:, None], theta[:, None]], axis=-1) + + d_quant = 1 + theta_quant = 2 + hough[:, 0] //= d_quant + hough[:, 1] //= theta_quant + _, indices, counts = np.unique(hough, + axis=0, + return_index=True, + return_counts=True) + + acc_map = np.zeros([512 // d_quant + 1, 360 // theta_quant + 1], + dtype='float32') + idx_map = np.zeros([512 // d_quant + 1, 360 // theta_quant + 1], + dtype='int32') - 1 + yx_indices = hough[indices, :].astype('int32') + acc_map[yx_indices[:, 0], yx_indices[:, 1]] = counts + idx_map[yx_indices[:, 0], yx_indices[:, 1]] = indices + + acc_map_np = acc_map + # acc_map = acc_map[None, :, :, None] + # + # ### fast suppression using tensorflow op + # acc_map = tf.constant(acc_map, dtype=tf.float32) + # max_acc_map = tf.keras.layers.MaxPool2D(pool_size=(5, 5), strides=1, padding='same')(acc_map) + # acc_map = acc_map * tf.cast(tf.math.equal(acc_map, max_acc_map), tf.float32) + # flatten_acc_map = tf.reshape(acc_map, [1, -1]) + # topk_values, topk_indices = tf.math.top_k(flatten_acc_map, k=len(pts)) + # _, h, w, _ = acc_map.shape + # y = tf.expand_dims(topk_indices // w, axis=-1) + # x = tf.expand_dims(topk_indices % w, axis=-1) + # yx = tf.concat([y, x], axis=-1) + + # fast suppression using pytorch op + acc_map = torch.from_numpy(acc_map_np).unsqueeze(0).unsqueeze(0) + _, _, h, w = acc_map.shape + max_acc_map = F.max_pool2d(acc_map, kernel_size=5, stride=1, padding=2) + acc_map = acc_map * ((acc_map == max_acc_map).float()) + flatten_acc_map = acc_map.reshape([ + -1, + ]) + + scores, indices = torch.topk(flatten_acc_map, + len(pts), + dim=-1, + largest=True) + yy = torch.div(indices, w, rounding_mode='floor').unsqueeze(-1) + xx = torch.fmod(indices, w).unsqueeze(-1) + yx = torch.cat((yy, xx), dim=-1) + + yx = yx.detach().cpu().numpy() + + topk_values = scores.detach().cpu().numpy() + indices = idx_map[yx[:, 0], yx[:, 1]] + basis = 5 // 2 + + merged_segments = [] + for yx_pt, max_indice, value in zip(yx, indices, topk_values): + y, x = yx_pt + if max_indice == -1 or value == 0: + continue + segment_list = [] + for y_offset in range(-basis, basis + 1): + for x_offset in range(-basis, basis + 1): + indice = idx_map[y + y_offset, x + x_offset] + cnt = int(acc_map_np[y + y_offset, x + x_offset]) + if indice != -1: + segment_list.append(segments[indice]) + if cnt > 1: + check_cnt = 1 + current_hough = hough[indice] + for new_indice, new_hough in enumerate(hough): + if (current_hough + == new_hough).all() and indice != new_indice: + segment_list.append(segments[new_indice]) + check_cnt += 1 + if check_cnt == cnt: + break + group_segments = np.array(segment_list).reshape([-1, 2]) + sorted_group_segments = np.sort(group_segments, axis=0) + x_min, y_min = sorted_group_segments[0, :] + x_max, y_max = sorted_group_segments[-1, :] + + deg = theta[max_indice] + if deg >= 90: + merged_segments.append([x_min, y_max, x_max, y_min]) + else: + merged_segments.append([x_min, y_min, x_max, y_max]) + + # 2. get intersections + new_segments = np.array(merged_segments) # (x1, y1, x2, y2) + start = new_segments[:, :2] # (x1, y1) + end = new_segments[:, 2:] # (x2, y2) + new_centers = (start + end) / 2.0 + diff = start - end + dist_segments = np.sqrt(np.sum(diff**2, axis=-1)) + + # ax + by = c + a = diff[:, 1] + b = -diff[:, 0] + c = a * start[:, 0] + b * start[:, 1] + pre_det = a[:, None] * b[None, :] + det = pre_det - np.transpose(pre_det) + + pre_inter_y = a[:, None] * c[None, :] + inter_y = (pre_inter_y - np.transpose(pre_inter_y)) / (det + 1e-10) + pre_inter_x = c[:, None] * b[None, :] + inter_x = (pre_inter_x - np.transpose(pre_inter_x)) / (det + 1e-10) + inter_pts = np.concatenate([inter_x[:, :, None], inter_y[:, :, None]], + axis=-1).astype('int32') + + # 3. get corner information + # 3.1 get distance + ''' + dist_segments: + | dist(0), dist(1), dist(2), ...| + dist_inter_to_segment1: + | dist(inter,0), dist(inter,0), dist(inter,0), ... | + | dist(inter,1), dist(inter,1), dist(inter,1), ... | + ... + dist_inter_to_semgnet2: + | dist(inter,0), dist(inter,1), dist(inter,2), ... | + | dist(inter,0), dist(inter,1), dist(inter,2), ... | + ... + ''' + + dist_inter_to_segment1_start = np.sqrt( + np.sum(((inter_pts - start[:, None, :])**2), axis=-1, + keepdims=True)) # [n_batch, n_batch, 1] + dist_inter_to_segment1_end = np.sqrt( + np.sum(((inter_pts - end[:, None, :])**2), axis=-1, + keepdims=True)) # [n_batch, n_batch, 1] + dist_inter_to_segment2_start = np.sqrt( + np.sum(((inter_pts - start[None, :, :])**2), axis=-1, + keepdims=True)) # [n_batch, n_batch, 1] + dist_inter_to_segment2_end = np.sqrt( + np.sum(((inter_pts - end[None, :, :])**2), axis=-1, + keepdims=True)) # [n_batch, n_batch, 1] + + # sort ascending + dist_inter_to_segment1 = np.sort(np.concatenate( + [dist_inter_to_segment1_start, dist_inter_to_segment1_end], axis=-1), + axis=-1) # [n_batch, n_batch, 2] + dist_inter_to_segment2 = np.sort(np.concatenate( + [dist_inter_to_segment2_start, dist_inter_to_segment2_end], axis=-1), + axis=-1) # [n_batch, n_batch, 2] + + # 3.2 get degree + inter_to_start = new_centers[:, None, :] - inter_pts + deg_inter_to_start = np.arctan2(inter_to_start[:, :, 1], + inter_to_start[:, :, 0]) * 180 / np.pi + deg_inter_to_start[deg_inter_to_start < 0.0] += 360 + inter_to_end = new_centers[None, :, :] - inter_pts + deg_inter_to_end = np.arctan2(inter_to_end[:, :, 1], + inter_to_end[:, :, 0]) * 180 / np.pi + deg_inter_to_end[deg_inter_to_end < 0.0] += 360 + ''' + B -- G + | | + C -- R + B : blue / G: green / C: cyan / R: red + + 0 -- 1 + | | + 3 -- 2 + ''' + # rename variables + deg1_map, deg2_map = deg_inter_to_start, deg_inter_to_end + # sort deg ascending + deg_sort = np.sort(np.concatenate( + [deg1_map[:, :, None], deg2_map[:, :, None]], axis=-1), + axis=-1) + + deg_diff_map = np.abs(deg1_map - deg2_map) + # we only consider the smallest degree of intersect + deg_diff_map[deg_diff_map > 180] = 360 - deg_diff_map[deg_diff_map > 180] + + # define available degree range + deg_range = [60, 120] + + corner_dict = {corner_info: [] for corner_info in range(4)} + inter_points = [] + for i in range(inter_pts.shape[0]): + for j in range(i + 1, inter_pts.shape[1]): + # i, j > line index, always i < j + x, y = inter_pts[i, j, :] + deg1, deg2 = deg_sort[i, j, :] + deg_diff = deg_diff_map[i, j] + + check_degree = deg_diff > deg_range[0] and deg_diff < deg_range[1] + + outside_ratio = params['outside_ratio'] # over ratio >>> drop it! + inside_ratio = params['inside_ratio'] # over ratio >>> drop it! + check_distance = ((dist_inter_to_segment1[i, j, 1] >= dist_segments[i] and + dist_inter_to_segment1[i, j, 0] <= dist_segments[i] * outside_ratio) or + (dist_inter_to_segment1[i, j, 1] <= dist_segments[i] and + dist_inter_to_segment1[i, j, 0] <= dist_segments[i] * inside_ratio)) and \ + ((dist_inter_to_segment2[i, j, 1] >= dist_segments[j] and + dist_inter_to_segment2[i, j, 0] <= dist_segments[j] * outside_ratio) or + (dist_inter_to_segment2[i, j, 1] <= dist_segments[j] and + dist_inter_to_segment2[i, j, 0] <= dist_segments[j] * inside_ratio)) + + if check_degree and check_distance: + corner_info = None # noqa + + if (deg1 >= 0 and deg1 <= 45 and deg2 >= 45 and deg2 <= 120) or \ + (deg2 >= 315 and deg1 >= 45 and deg1 <= 120): + corner_info, color_info = 0, 'blue' + elif (deg1 >= 45 and deg1 <= 125 and deg2 >= 125 + and deg2 <= 225): + corner_info, color_info = 1, 'green' + elif (deg1 >= 125 and deg1 <= 225 and deg2 >= 225 + and deg2 <= 315): + corner_info, color_info = 2, 'black' + elif (deg1 >= 0 and deg1 <= 45 and deg2 >= 225 and deg2 <= 315) or \ + (deg2 >= 315 and deg1 >= 225 and deg1 <= 315): + corner_info, color_info = 3, 'cyan' + else: + corner_info, color_info = 4, 'red' # we don't use it # noqa + continue + + corner_dict[corner_info].append([x, y, i, j]) + inter_points.append([x, y]) + + square_list = [] + connect_list = [] + segments_list = [] + for corner0 in corner_dict[0]: + for corner1 in corner_dict[1]: + connect01 = False + for corner0_line in corner0[2:]: + if corner0_line in corner1[2:]: + connect01 = True + break + if connect01: + for corner2 in corner_dict[2]: + connect12 = False + for corner1_line in corner1[2:]: + if corner1_line in corner2[2:]: + connect12 = True + break + if connect12: + for corner3 in corner_dict[3]: + connect23 = False + for corner2_line in corner2[2:]: + if corner2_line in corner3[2:]: + connect23 = True + break + if connect23: + for corner3_line in corner3[2:]: + if corner3_line in corner0[2:]: + # SQUARE!!! + ''' + 0 -- 1 + | | + 3 -- 2 + square_list: + order: 0 > 1 > 2 > 3 + | x0, y0, x1, y1, x2, y2, x3, y3 | + | x0, y0, x1, y1, x2, y2, x3, y3 | + ... + connect_list: + order: 01 > 12 > 23 > 30 + | line_idx01, line_idx12, line_idx23, line_idx30 | + | line_idx01, line_idx12, line_idx23, line_idx30 | + ... + segments_list: + order: 0 > 1 > 2 > 3 + | line_idx0_i, line_idx0_j, line_idx1_i, line_idx1_j, line_idx2_i, + line_idx2_j, line_idx3_i, line_idx3_j | + | line_idx0_i, line_idx0_j, line_idx1_i, line_idx1_j, line_idx2_i, + line_idx2_j, line_idx3_i, line_idx3_j | + ... + ''' + square_list.append(corner0[:2] + + corner1[:2] + + corner2[:2] + + corner3[:2]) + connect_list.append([ + corner0_line, corner1_line, + corner2_line, corner3_line + ]) + segments_list.append(corner0[2:] + + corner1[2:] + + corner2[2:] + + corner3[2:]) + + def check_outside_inside(segments_info, connect_idx): + # return 'outside or inside', min distance, cover_param, peri_param + if connect_idx == segments_info[0]: + check_dist_mat = dist_inter_to_segment1 + else: + check_dist_mat = dist_inter_to_segment2 + + i, j = segments_info + min_dist, max_dist = check_dist_mat[i, j, :] + connect_dist = dist_segments[connect_idx] + if max_dist > connect_dist: + return 'outside', min_dist, 0, 1 + else: + return 'inside', min_dist, -1, -1 + + top_square = None # noqa + + try: + map_size = input_shape[0] / 2 + squares = np.array(square_list).reshape([-1, 4, 2]) + score_array = [] + connect_array = np.array(connect_list) + segments_array = np.array(segments_list).reshape([-1, 4, 2]) + + # get degree of corners: + squares_rollup = np.roll(squares, 1, axis=1) + squares_rolldown = np.roll(squares, -1, axis=1) + vec1 = squares_rollup - squares + normalized_vec1 = vec1 / ( + np.linalg.norm(vec1, axis=-1, keepdims=True) + 1e-10) + vec2 = squares_rolldown - squares + normalized_vec2 = vec2 / ( + np.linalg.norm(vec2, axis=-1, keepdims=True) + 1e-10) + inner_products = np.sum(normalized_vec1 * normalized_vec2, + axis=-1) # [n_squares, 4] + squares_degree = np.arccos( + inner_products) * 180 / np.pi # [n_squares, 4] + + # get square score + overlap_scores = [] + degree_scores = [] + length_scores = [] + + for connects, segments, square, degree in zip(connect_array, + segments_array, squares, + squares_degree): + ''' + 0 -- 1 + | | + 3 -- 2 + + # segments: [4, 2] + # connects: [4] + ''' + + # OVERLAP SCORES + cover = 0 + perimeter = 0 + # check 0 > 1 > 2 > 3 + square_length = [] + + for start_idx in range(4): + end_idx = (start_idx + 1) % 4 + + connect_idx = connects[start_idx] # segment idx of segment01 + start_segments = segments[start_idx] + end_segments = segments[end_idx] + + start_point = square[start_idx] # noqa + end_point = square[end_idx] # noqa + + # check whether outside or inside + start_position, start_min, start_cover_param, start_peri_param = check_outside_inside( + start_segments, connect_idx) + end_position, end_min, end_cover_param, end_peri_param = check_outside_inside( + end_segments, connect_idx) + + cover += dist_segments[ + connect_idx] + start_cover_param * start_min + end_cover_param * end_min + perimeter += dist_segments[ + connect_idx] + start_peri_param * start_min + end_peri_param * end_min + + square_length.append(dist_segments[connect_idx] + + start_peri_param * start_min + + end_peri_param * end_min) + + overlap_scores.append(cover / perimeter) + # DEGREE SCORES + ''' + deg0 vs deg2 + deg1 vs deg3 + ''' + deg0, deg1, deg2, deg3 = degree + deg_ratio1 = deg0 / deg2 + if deg_ratio1 > 1.0: + deg_ratio1 = 1 / deg_ratio1 + deg_ratio2 = deg1 / deg3 + if deg_ratio2 > 1.0: + deg_ratio2 = 1 / deg_ratio2 + degree_scores.append((deg_ratio1 + deg_ratio2) / 2) + # LENGTH SCORES + ''' + len0 vs len2 + len1 vs len3 + ''' + len0, len1, len2, len3 = square_length + len_ratio1 = len0 / len2 if len2 > len0 else len2 / len0 + len_ratio2 = len1 / len3 if len3 > len1 else len3 / len1 + length_scores.append((len_ratio1 + len_ratio2) / 2) + + ###################################### + + overlap_scores = np.array(overlap_scores) + overlap_scores /= np.max(overlap_scores) + + degree_scores = np.array(degree_scores) + # degree_scores /= np.max(degree_scores) + + length_scores = np.array(length_scores) + + # AREA SCORES + area_scores = np.reshape(squares, [-1, 4, 2]) + area_x = area_scores[:, :, 0] + area_y = area_scores[:, :, 1] + correction = area_x[:, -1] * area_y[:, 0] - area_y[:, -1] * area_x[:, + 0] + area_scores = np.sum(area_x[:, :-1] * area_y[:, 1:], axis=-1) - np.sum( + area_y[:, :-1] * area_x[:, 1:], axis=-1) + area_scores = 0.5 * np.abs(area_scores + correction) + area_scores /= (map_size * map_size) # np.max(area_scores) + + # CENTER SCORES + centers = np.array([[256 // 2, 256 // 2]], dtype='float32') # [1, 2] + # squares: [n, 4, 2] + square_centers = np.mean(squares, axis=1) # [n, 2] + center2center = np.sqrt(np.sum((centers - square_centers)**2)) + center_scores = center2center / (map_size / np.sqrt(2.0)) + ''' + score_w = [overlap, degree, area, center, length] + ''' + score_w = [0.0, 1.0, 10.0, 0.5, 1.0] # noqa + score_array = (params['w_overlap'] * overlap_scores + + params['w_degree'] * degree_scores + + params['w_area'] * area_scores - + params['w_center'] * center_scores + + params['w_length'] * length_scores) + + best_square = [] # noqa + + sorted_idx = np.argsort(score_array)[::-1] + score_array = score_array[sorted_idx] + squares = squares[sorted_idx] + + except Exception: + pass + '''return list + merged_lines, squares, scores + ''' + + try: + new_segments[:, 0] = new_segments[:, 0] * 2 / input_shape[ + 1] * original_shape[1] + new_segments[:, 1] = new_segments[:, 1] * 2 / input_shape[ + 0] * original_shape[0] + new_segments[:, 2] = new_segments[:, 2] * 2 / input_shape[ + 1] * original_shape[1] + new_segments[:, 3] = new_segments[:, 3] * 2 / input_shape[ + 0] * original_shape[0] + except Exception: + new_segments = [] + + try: + squares[:, :, + 0] = squares[:, :, 0] * 2 / input_shape[1] * original_shape[1] + squares[:, :, + 1] = squares[:, :, 1] * 2 / input_shape[0] * original_shape[0] + except Exception: + squares = [] + score_array = [] + + try: + inter_points = np.array(inter_points) + inter_points[:, 0] = inter_points[:, 0] * 2 / input_shape[ + 1] * original_shape[1] + inter_points[:, 1] = inter_points[:, 1] * 2 / input_shape[ + 0] * original_shape[0] + except Exception: + inter_points = [] + + return new_segments, squares, score_array, inter_points diff --git a/scepter/modules/annotator/mlsd_op.py b/scepter/modules/annotator/mlsd_op.py new file mode 100644 index 0000000..fbab416 --- /dev/null +++ b/scepter/modules/annotator/mlsd_op.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# MLSD Line Detection +# From https://github.com/navervision/mlsd +# Apache-2.0 license + +import warnings +from abc import ABCMeta + +import cv2 +import numpy as np +import torch +from PIL import Image + +from scepter.modules.annotator.base_annotator import BaseAnnotator +from scepter.modules.annotator.mlsd.mbv2_mlsd_large import MobileV2_MLSD_Large +from scepter.modules.annotator.mlsd.utils import pred_lines +from scepter.modules.annotator.registry import ANNOTATORS +from scepter.modules.annotator.utils import resize_image, resize_image_ori +from scepter.modules.utils.config import dict_to_yaml +from scepter.modules.utils.distribute import we +from scepter.modules.utils.file_system import FS + + +@ANNOTATORS.register_class() +class MLSDdetector(BaseAnnotator, metaclass=ABCMeta): + def __init__(self, cfg, logger=None): + super().__init__(cfg, logger=logger) + model = MobileV2_MLSD_Large() + pretrained_model = cfg.get('PRETRAINED_MODEL', None) + if pretrained_model: + with FS.get_from(pretrained_model, wait_finish=True) as local_path: + model.load_state_dict(torch.load(local_path), strict=True) + self.model = model.eval() + self.thr_v = cfg.get('THR_V', 0.1) + self.thr_d = cfg.get('THR_D', 0.1) + + @torch.no_grad() + @torch.inference_mode() + @torch.autocast('cuda', enabled=False) + def forward(self, image): + if isinstance(image, Image.Image): + image = np.array(image) + elif isinstance(image, torch.Tensor): + image = image.detach().cpu().numpy() + elif isinstance(image, np.ndarray): + image = image.copy() + else: + raise f'Unsurpport datatype{type(image)}, only surpport np.ndarray, torch.Tensor, Pillow Image.' + h, w, c = image.shape + image, k = resize_image(image, 1024 if min(h, w) > 1024 else min(h, w)) + img_output = np.zeros_like(image) + try: + lines = pred_lines(image, + self.model, [image.shape[0], image.shape[1]], + self.thr_v, + self.thr_d, + device=we.device_id) + for line in lines: + x_start, y_start, x_end, y_end = [int(val) for val in line] + cv2.line(img_output, (x_start, y_start), (x_end, y_end), + [255, 255, 255], 1) + except Exception as e: + warnings.warn(f'{e}') + return None + img_output = resize_image_ori(h, w, img_output, k) + return img_output[:, :, 0] + + @staticmethod + def get_config_template(): + return dict_to_yaml('ANNOTATORS', + __class__.__name__, + MLSDdetector.para_dict, + set_name=True) diff --git a/scepter/modules/annotator/openpose.py b/scepter/modules/annotator/openpose.py new file mode 100644 index 0000000..0c3b608 --- /dev/null +++ b/scepter/modules/annotator/openpose.py @@ -0,0 +1,811 @@ +# -*- coding: utf-8 -*- +# Openpose +# Original from CMU https://github.com/CMU-Perceptual-Computing-Lab/openpose +# 2nd Edited by https://github.com/Hzzone/pytorch-openpose +# The implementation is modified from 3rd Edited Version by ControlNet +import math +import os +from abc import ABCMeta +from collections import OrderedDict + +import cv2 +import matplotlib +import numpy as np +import torch +import torch.nn as nn +from PIL import Image +from scipy.ndimage.filters import gaussian_filter +from skimage.measure import label + +from scepter.modules.annotator.base_annotator import BaseAnnotator +from scepter.modules.annotator.registry import ANNOTATORS +from scepter.modules.utils.config import dict_to_yaml +from scepter.modules.utils.file_system import FS + +os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE' + + +def padRightDownCorner(img, stride, padValue): + h = img.shape[0] + w = img.shape[1] + + pad = 4 * [None] + pad[0] = 0 # up + pad[1] = 0 # left + pad[2] = 0 if (h % stride == 0) else stride - (h % stride) # down + pad[3] = 0 if (w % stride == 0) else stride - (w % stride) # right + + img_padded = img + pad_up = np.tile(img_padded[0:1, :, :] * 0 + padValue, (pad[0], 1, 1)) + img_padded = np.concatenate((pad_up, img_padded), axis=0) + pad_left = np.tile(img_padded[:, 0:1, :] * 0 + padValue, (1, pad[1], 1)) + img_padded = np.concatenate((pad_left, img_padded), axis=1) + pad_down = np.tile(img_padded[-2:-1, :, :] * 0 + padValue, (pad[2], 1, 1)) + img_padded = np.concatenate((img_padded, pad_down), axis=0) + pad_right = np.tile(img_padded[:, -2:-1, :] * 0 + padValue, (1, pad[3], 1)) + img_padded = np.concatenate((img_padded, pad_right), axis=1) + + return img_padded, pad + + +# transfer caffe model to pytorch which will match the layer name +def transfer(model, model_weights): + transfered_model_weights = {} + for weights_name in model.state_dict().keys(): + transfered_model_weights[weights_name] = model_weights['.'.join( + weights_name.split('.')[1:])] + return transfered_model_weights + + +# draw the body keypoint and lims +def draw_bodypose(canvas, candidate, subset): + stickwidth = 4 + limbSeq = [[2, 3], [2, 6], [3, 4], [4, 5], [6, 7], [7, 8], [2, 9], [9, 10], + [10, 11], [2, 12], [12, 13], [13, 14], [2, 1], [1, 15], + [15, 17], [1, 16], [16, 18], [3, 17], [6, 18]] + + colors = [[255, 0, 0], [255, 85, 0], [255, 170, 0], [255, 255, 0], + [170, 255, 0], [85, 255, 0], [0, 255, 0], [0, 255, 85], + [0, 255, 170], [0, 255, 255], [0, 170, 255], [0, 85, 255], + [0, 0, 255], [85, 0, 255], [170, 0, 255], [255, 0, 255], + [255, 0, 170], [255, 0, 85]] + for i in range(18): + for n in range(len(subset)): + index = int(subset[n][i]) + if index == -1: + continue + x, y = candidate[index][0:2] + cv2.circle(canvas, (int(x), int(y)), 4, colors[i], thickness=-1) + for i in range(17): + for n in range(len(subset)): + index = subset[n][np.array(limbSeq[i]) - 1] + if -1 in index: + continue + cur_canvas = canvas.copy() + Y = candidate[index.astype(int), 0] + X = candidate[index.astype(int), 1] + mX = np.mean(X) + mY = np.mean(Y) + length = ((X[0] - X[1])**2 + (Y[0] - Y[1])**2)**0.5 + angle = math.degrees(math.atan2(X[0] - X[1], Y[0] - Y[1])) + polygon = cv2.ellipse2Poly( + (int(mY), int(mX)), (int(length / 2), stickwidth), int(angle), + 0, 360, 1) + cv2.fillConvexPoly(cur_canvas, polygon, colors[i]) + canvas = cv2.addWeighted(canvas, 0.4, cur_canvas, 0.6, 0) + # plt.imsave("preview.jpg", canvas[:, :, [2, 1, 0]]) + # plt.imshow(canvas[:, :, [2, 1, 0]]) + return canvas + + +# image drawed by opencv is not good. +def draw_handpose(canvas, all_hand_peaks, show_number=False): + edges = [[0, 1], [1, 2], [2, 3], [3, 4], [0, 5], [5, 6], [6, 7], [7, 8], + [0, 9], [9, 10], [10, 11], [11, 12], [0, 13], [13, 14], [14, 15], + [15, 16], [0, 17], [17, 18], [18, 19], [19, 20]] + + for peaks in all_hand_peaks: + for ie, e in enumerate(edges): + if np.sum(np.all(peaks[e], axis=1) == 0) == 0: + x1, y1 = peaks[e[0]] + x2, y2 = peaks[e[1]] + cv2.line(canvas, (x1, y1), (x2, y2), + matplotlib.colors.hsv_to_rgb( + [ie / float(len(edges)), 1.0, 1.0]) * 255, + thickness=2) + + for i, keyponit in enumerate(peaks): + x, y = keyponit + cv2.circle(canvas, (x, y), 4, (0, 0, 255), thickness=-1) + if show_number: + cv2.putText(canvas, + str(i), (x, y), + cv2.FONT_HERSHEY_SIMPLEX, + 0.3, (0, 0, 0), + lineType=cv2.LINE_AA) + return canvas + + +# detect hand according to body pose keypoints +# please refer to https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/ +# master/src/openpose/hand/handDetector.cpp +def handDetect(candidate, subset, oriImg): + # right hand: wrist 4, elbow 3, shoulder 2 + # left hand: wrist 7, elbow 6, shoulder 5 + ratioWristElbow = 0.33 + detect_result = [] + image_height, image_width = oriImg.shape[0:2] + for person in subset.astype(int): + # if any of three not detected + has_left = np.sum(person[[5, 6, 7]] == -1) == 0 + has_right = np.sum(person[[2, 3, 4]] == -1) == 0 + if not (has_left or has_right): + continue + hands = [] + # left hand + if has_left: + left_shoulder_index, left_elbow_index, left_wrist_index = person[[ + 5, 6, 7 + ]] + x1, y1 = candidate[left_shoulder_index][:2] + x2, y2 = candidate[left_elbow_index][:2] + x3, y3 = candidate[left_wrist_index][:2] + hands.append([x1, y1, x2, y2, x3, y3, True]) + # right hand + if has_right: + right_shoulder_index, right_elbow_index, right_wrist_index = person[ + [2, 3, 4]] + x1, y1 = candidate[right_shoulder_index][:2] + x2, y2 = candidate[right_elbow_index][:2] + x3, y3 = candidate[right_wrist_index][:2] + hands.append([x1, y1, x2, y2, x3, y3, False]) + + for x1, y1, x2, y2, x3, y3, is_left in hands: + # pos_hand = pos_wrist + ratio * (pos_wrist - pos_elbox) = (1 + ratio) * pos_wrist - ratio * pos_elbox + # handRectangle.x = posePtr[wrist*3] + ratioWristElbow * (posePtr[wrist*3] - posePtr[elbow*3]); + # handRectangle.y = posePtr[wrist*3+1] + ratioWristElbow * (posePtr[wrist*3+1] - posePtr[elbow*3+1]); + # const auto distanceWristElbow = getDistance(poseKeypoints, person, wrist, elbow); + # const auto distanceElbowShoulder = getDistance(poseKeypoints, person, elbow, shoulder); + # handRectangle.width = 1.5f * fastMax(distanceWristElbow, 0.9f * distanceElbowShoulder); + x = x3 + ratioWristElbow * (x3 - x2) + y = y3 + ratioWristElbow * (y3 - y2) + distanceWristElbow = math.sqrt((x3 - x2)**2 + (y3 - y2)**2) + distanceElbowShoulder = math.sqrt((x2 - x1)**2 + (y2 - y1)**2) + width = 1.5 * max(distanceWristElbow, 0.9 * distanceElbowShoulder) + # x-y refers to the center --> offset to topLeft point + # handRectangle.x -= handRectangle.width / 2.f; + # handRectangle.y -= handRectangle.height / 2.f; + x -= width / 2 + y -= width / 2 # width = height + # overflow the image + if x < 0: + x = 0 + if y < 0: + y = 0 + width1 = width + width2 = width + if x + width > image_width: + width1 = image_width - x + if y + width > image_height: + width2 = image_height - y + width = min(width1, width2) + # the max hand box value is 20 pixels + if width >= 20: + detect_result.append([int(x), int(y), int(width), is_left]) + ''' + return value: [[x, y, w, True if left hand else False]]. + width=height since the network require squared input. + x, y is the coordinate of top left + ''' + return detect_result + + +# get max index of 2d array +def npmax(array): + arrayindex = array.argmax(1) + arrayvalue = array.max(1) + i = arrayvalue.argmax() + j = arrayindex[i] + return i, j + + +def make_layers(block, no_relu_layers): + layers = [] + for layer_name, v in block.items(): + if 'pool' in layer_name: + layer = nn.MaxPool2d(kernel_size=v[0], stride=v[1], padding=v[2]) + layers.append((layer_name, layer)) + else: + conv2d = nn.Conv2d(in_channels=v[0], + out_channels=v[1], + kernel_size=v[2], + stride=v[3], + padding=v[4]) + layers.append((layer_name, conv2d)) + if layer_name not in no_relu_layers: + layers.append(('relu_' + layer_name, nn.ReLU(inplace=True))) + + return nn.Sequential(OrderedDict(layers)) + + +class bodypose_model(nn.Module): + def __init__(self): + super(bodypose_model, self).__init__() + + # these layers have no relu layer + no_relu_layers = [ + 'conv5_5_CPM_L1', 'conv5_5_CPM_L2', 'Mconv7_stage2_L1', + 'Mconv7_stage2_L2', 'Mconv7_stage3_L1', 'Mconv7_stage3_L2', + 'Mconv7_stage4_L1', 'Mconv7_stage4_L2', 'Mconv7_stage5_L1', + 'Mconv7_stage5_L2', 'Mconv7_stage6_L1', 'Mconv7_stage6_L1' + ] + blocks = {} + block0 = OrderedDict([('conv1_1', [3, 64, 3, 1, 1]), + ('conv1_2', [64, 64, 3, 1, 1]), + ('pool1_stage1', [2, 2, 0]), + ('conv2_1', [64, 128, 3, 1, 1]), + ('conv2_2', [128, 128, 3, 1, 1]), + ('pool2_stage1', [2, 2, 0]), + ('conv3_1', [128, 256, 3, 1, 1]), + ('conv3_2', [256, 256, 3, 1, 1]), + ('conv3_3', [256, 256, 3, 1, 1]), + ('conv3_4', [256, 256, 3, 1, 1]), + ('pool3_stage1', [2, 2, 0]), + ('conv4_1', [256, 512, 3, 1, 1]), + ('conv4_2', [512, 512, 3, 1, 1]), + ('conv4_3_CPM', [512, 256, 3, 1, 1]), + ('conv4_4_CPM', [256, 128, 3, 1, 1])]) + + # Stage 1 + block1_1 = OrderedDict([('conv5_1_CPM_L1', [128, 128, 3, 1, 1]), + ('conv5_2_CPM_L1', [128, 128, 3, 1, 1]), + ('conv5_3_CPM_L1', [128, 128, 3, 1, 1]), + ('conv5_4_CPM_L1', [128, 512, 1, 1, 0]), + ('conv5_5_CPM_L1', [512, 38, 1, 1, 0])]) + + block1_2 = OrderedDict([('conv5_1_CPM_L2', [128, 128, 3, 1, 1]), + ('conv5_2_CPM_L2', [128, 128, 3, 1, 1]), + ('conv5_3_CPM_L2', [128, 128, 3, 1, 1]), + ('conv5_4_CPM_L2', [128, 512, 1, 1, 0]), + ('conv5_5_CPM_L2', [512, 19, 1, 1, 0])]) + blocks['block1_1'] = block1_1 + blocks['block1_2'] = block1_2 + + self.model0 = make_layers(block0, no_relu_layers) + + # Stages 2 - 6 + for i in range(2, 7): + blocks['block%d_1' % i] = OrderedDict([ + ('Mconv1_stage%d_L1' % i, [185, 128, 7, 1, 3]), + ('Mconv2_stage%d_L1' % i, [128, 128, 7, 1, 3]), + ('Mconv3_stage%d_L1' % i, [128, 128, 7, 1, 3]), + ('Mconv4_stage%d_L1' % i, [128, 128, 7, 1, 3]), + ('Mconv5_stage%d_L1' % i, [128, 128, 7, 1, 3]), + ('Mconv6_stage%d_L1' % i, [128, 128, 1, 1, 0]), + ('Mconv7_stage%d_L1' % i, [128, 38, 1, 1, 0]) + ]) + + blocks['block%d_2' % i] = OrderedDict([ + ('Mconv1_stage%d_L2' % i, [185, 128, 7, 1, 3]), + ('Mconv2_stage%d_L2' % i, [128, 128, 7, 1, 3]), + ('Mconv3_stage%d_L2' % i, [128, 128, 7, 1, 3]), + ('Mconv4_stage%d_L2' % i, [128, 128, 7, 1, 3]), + ('Mconv5_stage%d_L2' % i, [128, 128, 7, 1, 3]), + ('Mconv6_stage%d_L2' % i, [128, 128, 1, 1, 0]), + ('Mconv7_stage%d_L2' % i, [128, 19, 1, 1, 0]) + ]) + + for k in blocks.keys(): + blocks[k] = make_layers(blocks[k], no_relu_layers) + + self.model1_1 = blocks['block1_1'] + self.model2_1 = blocks['block2_1'] + self.model3_1 = blocks['block3_1'] + self.model4_1 = blocks['block4_1'] + self.model5_1 = blocks['block5_1'] + self.model6_1 = blocks['block6_1'] + + self.model1_2 = blocks['block1_2'] + self.model2_2 = blocks['block2_2'] + self.model3_2 = blocks['block3_2'] + self.model4_2 = blocks['block4_2'] + self.model5_2 = blocks['block5_2'] + self.model6_2 = blocks['block6_2'] + + def forward(self, x): + + out1 = self.model0(x) + + out1_1 = self.model1_1(out1) + out1_2 = self.model1_2(out1) + out2 = torch.cat([out1_1, out1_2, out1], 1) + + out2_1 = self.model2_1(out2) + out2_2 = self.model2_2(out2) + out3 = torch.cat([out2_1, out2_2, out1], 1) + + out3_1 = self.model3_1(out3) + out3_2 = self.model3_2(out3) + out4 = torch.cat([out3_1, out3_2, out1], 1) + + out4_1 = self.model4_1(out4) + out4_2 = self.model4_2(out4) + out5 = torch.cat([out4_1, out4_2, out1], 1) + + out5_1 = self.model5_1(out5) + out5_2 = self.model5_2(out5) + out6 = torch.cat([out5_1, out5_2, out1], 1) + + out6_1 = self.model6_1(out6) + out6_2 = self.model6_2(out6) + + return out6_1, out6_2 + + +class handpose_model(nn.Module): + def __init__(self): + super(handpose_model, self).__init__() + + # these layers have no relu layer + no_relu_layers = [ + 'conv6_2_CPM', 'Mconv7_stage2', 'Mconv7_stage3', 'Mconv7_stage4', + 'Mconv7_stage5', 'Mconv7_stage6' + ] + # stage 1 + block1_0 = OrderedDict([('conv1_1', [3, 64, 3, 1, 1]), + ('conv1_2', [64, 64, 3, 1, 1]), + ('pool1_stage1', [2, 2, 0]), + ('conv2_1', [64, 128, 3, 1, 1]), + ('conv2_2', [128, 128, 3, 1, 1]), + ('pool2_stage1', [2, 2, 0]), + ('conv3_1', [128, 256, 3, 1, 1]), + ('conv3_2', [256, 256, 3, 1, 1]), + ('conv3_3', [256, 256, 3, 1, 1]), + ('conv3_4', [256, 256, 3, 1, 1]), + ('pool3_stage1', [2, 2, 0]), + ('conv4_1', [256, 512, 3, 1, 1]), + ('conv4_2', [512, 512, 3, 1, 1]), + ('conv4_3', [512, 512, 3, 1, 1]), + ('conv4_4', [512, 512, 3, 1, 1]), + ('conv5_1', [512, 512, 3, 1, 1]), + ('conv5_2', [512, 512, 3, 1, 1]), + ('conv5_3_CPM', [512, 128, 3, 1, 1])]) + + block1_1 = OrderedDict([('conv6_1_CPM', [128, 512, 1, 1, 0]), + ('conv6_2_CPM', [512, 22, 1, 1, 0])]) + + blocks = {} + blocks['block1_0'] = block1_0 + blocks['block1_1'] = block1_1 + + # stage 2-6 + for i in range(2, 7): + blocks['block%d' % i] = OrderedDict([ + ('Mconv1_stage%d' % i, [150, 128, 7, 1, 3]), + ('Mconv2_stage%d' % i, [128, 128, 7, 1, 3]), + ('Mconv3_stage%d' % i, [128, 128, 7, 1, 3]), + ('Mconv4_stage%d' % i, [128, 128, 7, 1, 3]), + ('Mconv5_stage%d' % i, [128, 128, 7, 1, 3]), + ('Mconv6_stage%d' % i, [128, 128, 1, 1, 0]), + ('Mconv7_stage%d' % i, [128, 22, 1, 1, 0]) + ]) + + for k in blocks.keys(): + blocks[k] = make_layers(blocks[k], no_relu_layers) + + self.model1_0 = blocks['block1_0'] + self.model1_1 = blocks['block1_1'] + self.model2 = blocks['block2'] + self.model3 = blocks['block3'] + self.model4 = blocks['block4'] + self.model5 = blocks['block5'] + self.model6 = blocks['block6'] + + def forward(self, x): + out1_0 = self.model1_0(x) + out1_1 = self.model1_1(out1_0) + concat_stage2 = torch.cat([out1_1, out1_0], 1) + out_stage2 = self.model2(concat_stage2) + concat_stage3 = torch.cat([out_stage2, out1_0], 1) + out_stage3 = self.model3(concat_stage3) + concat_stage4 = torch.cat([out_stage3, out1_0], 1) + out_stage4 = self.model4(concat_stage4) + concat_stage5 = torch.cat([out_stage4, out1_0], 1) + out_stage5 = self.model5(concat_stage5) + concat_stage6 = torch.cat([out_stage5, out1_0], 1) + out_stage6 = self.model6(concat_stage6) + return out_stage6 + + +class Hand(object): + def __init__(self, model_path, device='cuda'): + self.model = handpose_model() + if torch.cuda.is_available(): + self.model = self.model.to(device) + model_dict = transfer(self.model, torch.load(model_path)) + self.model.load_state_dict(model_dict) + self.model.eval() + self.device = device + + def __call__(self, oriImg): + scale_search = [0.5, 1.0, 1.5, 2.0] + # scale_search = [0.5] + boxsize = 368 + stride = 8 + padValue = 128 + thre = 0.05 + multiplier = [x * boxsize / oriImg.shape[0] for x in scale_search] + heatmap_avg = np.zeros((oriImg.shape[0], oriImg.shape[1], 22)) + # paf_avg = np.zeros((oriImg.shape[0], oriImg.shape[1], 38)) + + for m in range(len(multiplier)): + scale = multiplier[m] + imageToTest = cv2.resize(oriImg, (0, 0), + fx=scale, + fy=scale, + interpolation=cv2.INTER_CUBIC) + imageToTest_padded, pad = padRightDownCorner( + imageToTest, stride, padValue) + im = np.transpose( + np.float32(imageToTest_padded[:, :, :, np.newaxis]), + (3, 2, 0, 1)) / 256 - 0.5 + im = np.ascontiguousarray(im) + + data = torch.from_numpy(im).float() + if torch.cuda.is_available(): + data = data.to(self.device) + # data = data.permute([2, 0, 1]).unsqueeze(0).float() + with torch.no_grad(): + output = self.model(data).cpu().numpy() + # output = self.model(data).numpy()q + + # extract outputs, resize, and remove padding + heatmap = np.transpose(np.squeeze(output), + (1, 2, 0)) # output 1 is heatmaps + heatmap = cv2.resize(heatmap, (0, 0), + fx=stride, + fy=stride, + interpolation=cv2.INTER_CUBIC) + heatmap = heatmap[:imageToTest_padded.shape[0] - + pad[2], :imageToTest_padded.shape[1] - pad[3], :] + heatmap = cv2.resize(heatmap, (oriImg.shape[1], oriImg.shape[0]), + interpolation=cv2.INTER_CUBIC) + + heatmap_avg += heatmap / len(multiplier) + + all_peaks = [] + for part in range(21): + map_ori = heatmap_avg[:, :, part] + one_heatmap = gaussian_filter(map_ori, sigma=3) + binary = np.ascontiguousarray(one_heatmap > thre, dtype=np.uint8) + # 全部小于阈值 + if np.sum(binary) == 0: + all_peaks.append([0, 0]) + continue + label_img, label_numbers = label(binary, + return_num=True, + connectivity=binary.ndim) + max_index = np.argmax([ + np.sum(map_ori[label_img == i]) + for i in range(1, label_numbers + 1) + ]) + 1 + label_img[label_img != max_index] = 0 + map_ori[label_img == 0] = 0 + + y, x = npmax(map_ori) + all_peaks.append([x, y]) + return np.array(all_peaks) + + +class Body(object): + def __init__(self, model_path, device='cuda'): + self.model = bodypose_model() + if torch.cuda.is_available(): + self.model = self.model.to(device) + model_dict = transfer(self.model, torch.load(model_path)) + self.model.load_state_dict(model_dict) + self.model.eval() + self.device = device + + def __call__(self, oriImg): + # scale_search = [0.5, 1.0, 1.5, 2.0] + scale_search = [0.5] + boxsize = 368 + stride = 8 + padValue = 128 + thre1 = 0.1 + thre2 = 0.05 + multiplier = [x * boxsize / oriImg.shape[0] for x in scale_search] + heatmap_avg = np.zeros((oriImg.shape[0], oriImg.shape[1], 19)) + paf_avg = np.zeros((oriImg.shape[0], oriImg.shape[1], 38)) + + for m in range(len(multiplier)): + scale = multiplier[m] + imageToTest = cv2.resize(oriImg, (0, 0), + fx=scale, + fy=scale, + interpolation=cv2.INTER_CUBIC) + imageToTest_padded, pad = padRightDownCorner( + imageToTest, stride, padValue) + im = np.transpose( + np.float32(imageToTest_padded[:, :, :, np.newaxis]), + (3, 2, 0, 1)) / 256 - 0.5 + im = np.ascontiguousarray(im) + + data = torch.from_numpy(im).float() + if torch.cuda.is_available(): + data = data.to(self.device) + # data = data.permute([2, 0, 1]).unsqueeze(0).float() + with torch.no_grad(): + Mconv7_stage6_L1, Mconv7_stage6_L2 = self.model(data) + Mconv7_stage6_L1 = Mconv7_stage6_L1.cpu().numpy() + Mconv7_stage6_L2 = Mconv7_stage6_L2.cpu().numpy() + + # extract outputs, resize, and remove padding + # heatmap = np.transpose(np.squeeze(net.blobs[output_blobs.keys()[1]].data), (1, 2, 0)) + # output 1 is heatmaps + heatmap = np.transpose(np.squeeze(Mconv7_stage6_L2), + (1, 2, 0)) # output 1 is heatmaps + heatmap = cv2.resize(heatmap, (0, 0), + fx=stride, + fy=stride, + interpolation=cv2.INTER_CUBIC) + heatmap = heatmap[:imageToTest_padded.shape[0] - + pad[2], :imageToTest_padded.shape[1] - pad[3], :] + heatmap = cv2.resize(heatmap, (oriImg.shape[1], oriImg.shape[0]), + interpolation=cv2.INTER_CUBIC) + + # paf = np.transpose(np.squeeze(net.blobs[output_blobs.keys()[0]].data), (1, 2, 0)) # output 0 is PAFs + paf = np.transpose(np.squeeze(Mconv7_stage6_L1), + (1, 2, 0)) # output 0 is PAFs + paf = cv2.resize(paf, (0, 0), + fx=stride, + fy=stride, + interpolation=cv2.INTER_CUBIC) + paf = paf[:imageToTest_padded.shape[0] - + pad[2], :imageToTest_padded.shape[1] - pad[3], :] + paf = cv2.resize(paf, (oriImg.shape[1], oriImg.shape[0]), + interpolation=cv2.INTER_CUBIC) + + heatmap_avg += heatmap_avg + heatmap / len(multiplier) + paf_avg += +paf / len(multiplier) + + all_peaks = [] + peak_counter = 0 + + for part in range(18): + map_ori = heatmap_avg[:, :, part] + one_heatmap = gaussian_filter(map_ori, sigma=3) + + map_left = np.zeros(one_heatmap.shape) + map_left[1:, :] = one_heatmap[:-1, :] + map_right = np.zeros(one_heatmap.shape) + map_right[:-1, :] = one_heatmap[1:, :] + map_up = np.zeros(one_heatmap.shape) + map_up[:, 1:] = one_heatmap[:, :-1] + map_down = np.zeros(one_heatmap.shape) + map_down[:, :-1] = one_heatmap[:, 1:] + + peaks_binary = np.logical_and.reduce( + (one_heatmap >= map_left, one_heatmap >= map_right, + one_heatmap >= map_up, one_heatmap >= map_down, + one_heatmap > thre1)) + peaks = list( + zip(np.nonzero(peaks_binary)[1], + np.nonzero(peaks_binary)[0])) # note reverse + peaks_with_score = [x + (map_ori[x[1], x[0]], ) for x in peaks] + peak_id = range(peak_counter, peak_counter + len(peaks)) + peaks_with_score_and_id = [ + peaks_with_score[i] + (peak_id[i], ) + for i in range(len(peak_id)) + ] + + all_peaks.append(peaks_with_score_and_id) + peak_counter += len(peaks) + + # find connection in the specified sequence, center 29 is in the position 15 + limbSeq = [[2, 3], [2, 6], [3, 4], [4, 5], [6, 7], [7, 8], [2, 9], + [9, 10], [10, 11], [2, 12], [12, 13], [13, 14], [2, 1], + [1, 15], [15, 17], [1, 16], [16, 18], [3, 17], [6, 18]] + # the middle joints heatmap correpondence + mapIdx = [[31, 32], [39, 40], [33, 34], [35, 36], [41, 42], [43, 44], + [19, 20], [21, 22], [23, 24], [25, 26], [27, 28], [29, 30], + [47, 48], [49, 50], [53, 54], [51, 52], [55, 56], [37, 38], + [45, 46]] + + connection_all = [] + special_k = [] + mid_num = 10 + + for k in range(len(mapIdx)): + score_mid = paf_avg[:, :, [x - 19 for x in mapIdx[k]]] + candA = all_peaks[limbSeq[k][0] - 1] + candB = all_peaks[limbSeq[k][1] - 1] + nA = len(candA) + nB = len(candB) + indexA, indexB = limbSeq[k] + if (nA != 0 and nB != 0): + connection_candidate = [] + for i in range(nA): + for j in range(nB): + vec = np.subtract(candB[j][:2], candA[i][:2]) + norm = math.sqrt(vec[0] * vec[0] + vec[1] * vec[1]) + norm = max(0.001, norm) + vec = np.divide(vec, norm) + + startend = list( + zip( + np.linspace(candA[i][0], + candB[j][0], + num=mid_num), + np.linspace(candA[i][1], + candB[j][1], + num=mid_num))) + + vec_x = np.array([ + score_mid[int(round(startend[ii][1])), + int(round(startend[ii][0])), 0] + for ii in range(len(startend)) + ]) + vec_y = np.array([ + score_mid[int(round(startend[ii][1])), + int(round(startend[ii][0])), 1] + for ii in range(len(startend)) + ]) + + score_midpts = np.multiply( + vec_x, vec[0]) + np.multiply(vec_y, vec[1]) + score_with_dist_prior = sum(score_midpts) / len( + score_midpts) + min( + 0.5 * oriImg.shape[0] / norm - 1, 0) + criterion1 = len(np.nonzero( + score_midpts > thre2)[0]) > 0.8 * len(score_midpts) + criterion2 = score_with_dist_prior > 0 + if criterion1 and criterion2: + connection_candidate.append([ + i, j, score_with_dist_prior, + score_with_dist_prior + candA[i][2] + + candB[j][2] + ]) + + connection_candidate = sorted(connection_candidate, + key=lambda x: x[2], + reverse=True) + connection = np.zeros((0, 5)) + for c in range(len(connection_candidate)): + i, j, s = connection_candidate[c][0:3] + if (i not in connection[:, 3] + and j not in connection[:, 4]): + connection = np.vstack( + [connection, [candA[i][3], candB[j][3], s, i, j]]) + if (len(connection) >= min(nA, nB)): + break + + connection_all.append(connection) + else: + special_k.append(k) + connection_all.append([]) + + # last number in each row is the total parts number of that person + # the second last number in each row is the score of the overall configuration + subset = -1 * np.ones((0, 20)) + candidate = np.array( + [item for sublist in all_peaks for item in sublist]) + + for k in range(len(mapIdx)): + if k not in special_k: + partAs = connection_all[k][:, 0] + partBs = connection_all[k][:, 1] + indexA, indexB = np.array(limbSeq[k]) - 1 + + for i in range(len(connection_all[k])): # = 1:size(temp,1) + found = 0 + subset_idx = [-1, -1] + for j in range(len(subset)): # 1:size(subset,1): + if subset[j][indexA] == partAs[i] or subset[j][ + indexB] == partBs[i]: + subset_idx[found] = j + found += 1 + + if found == 1: + j = subset_idx[0] + if subset[j][indexB] != partBs[i]: + subset[j][indexB] = partBs[i] + subset[j][-1] += 1 + subset[j][-2] += candidate[ + partBs[i].astype(int), + 2] + connection_all[k][i][2] + elif found == 2: # if found 2 and disjoint, merge them + j1, j2 = subset_idx + membership = ((subset[j1] >= 0).astype(int) + + (subset[j2] >= 0).astype(int))[:-2] + if len(np.nonzero(membership == 2)[0]) == 0: # merge + subset[j1][:-2] += (subset[j2][:-2] + 1) + subset[j1][-2:] += subset[j2][-2:] + subset[j1][-2] += connection_all[k][i][2] + subset = np.delete(subset, j2, 0) + else: # as like found == 1 + subset[j1][indexB] = partBs[i] + subset[j1][-1] += 1 + subset[j1][-2] += candidate[ + partBs[i].astype(int), + 2] + connection_all[k][i][2] + + # if find no partA in the subset, create a new subset + elif not found and k < 17: + row = -1 * np.ones(20) + row[indexA] = partAs[i] + row[indexB] = partBs[i] + row[-1] = 2 + row[-2] = sum( + candidate[connection_all[k][i, :2].astype(int), + 2]) + connection_all[k][i][2] + subset = np.vstack([subset, row]) + # delete some rows of subset which has few parts occur + deleteIdx = [] + for i in range(len(subset)): + if subset[i][-1] < 4 or subset[i][-2] / subset[i][-1] < 0.4: + deleteIdx.append(i) + subset = np.delete(subset, deleteIdx, axis=0) + + # subset: n*20 array, 0-17 is the index in candidate, 18 is the total score, 19 is the total parts + # candidate: x, y, score, id + return candidate, subset + + +@ANNOTATORS.register_class() +class OpenposeAnnotator(BaseAnnotator, metaclass=ABCMeta): + para_dict = {} + + def __init__(self, cfg, logger=None): + super().__init__(cfg, logger=logger) + with FS.get_from(cfg.BODY_MODEL_PATH, + wait_finish=True) as body_model_path: + self.body_estimation = Body(body_model_path, device='cpu') + with FS.get_from(cfg.HAND_MODEL_PATH, + wait_finish=True) as hand_model_path: + self.hand_estimation = Hand(hand_model_path, device='cpu') + self.use_hand = cfg.get('USE_HAND', False) + + def to(self, device): + self.body_estimation.model = self.body_estimation.model.to(device) + self.body_estimation.device = device + self.hand_estimation.model = self.hand_estimation.model.to(device) + self.hand_estimation.device = device + return self + + @torch.no_grad() + @torch.inference_mode() + @torch.autocast('cuda', enabled=False) + def forward(self, image): + if isinstance(image, Image.Image): + image = np.array(image) + elif isinstance(image, torch.Tensor): + image = image.detach().cpu().numpy() + elif isinstance(image, np.ndarray): + image = image.copy() + else: + raise f'Unsurpport datatype{type(image)}, only surpport np.ndarray, torch.Tensor, Pillow Image.' + image = image[:, :, ::-1] + candidate, subset = self.body_estimation(image) + canvas = np.zeros_like(image) + canvas = draw_bodypose(canvas, candidate, subset) + if self.use_hand: + hands_list = handDetect(candidate, subset, image) + all_hand_peaks = [] + for x, y, w, is_left in hands_list: + peaks = self.hand_estimation(image[y:y + w, x:x + w, :]) + peaks[:, 0] = np.where(peaks[:, 0] == 0, peaks[:, 0], + peaks[:, 0] + x) + peaks[:, 1] = np.where(peaks[:, 1] == 0, peaks[:, 1], + peaks[:, 1] + y) + all_hand_peaks.append(peaks) + canvas = draw_handpose(canvas, all_hand_peaks) + return canvas + + @staticmethod + def get_config_template(): + return dict_to_yaml('ANNOTATORS', + __class__.__name__, + OpenposeAnnotator.para_dict, + set_name=True) diff --git a/scepter/modules/annotator/registry.py b/scepter/modules/annotator/registry.py new file mode 100644 index 0000000..d141bb6 --- /dev/null +++ b/scepter/modules/annotator/registry.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright (c) Alibaba, Inc. and its affiliates. +from scepter.modules.utils.config import Config +from scepter.modules.utils.registry import Registry, build_from_config + + +def build_annotator(cfg, registry, logger=None, *args, **kwargs): + """ After build model, load pretrained model if exists key `pretrain`. + + pretrain (str, dict): Describes how to load pretrained model. + str, treat pretrain as model path; + dict: should contains key `path`, and other parameters token by function load_pretrained(); + """ + if not isinstance(cfg, Config): + raise TypeError(f'Config must be type dict, got {type(cfg)}') + if cfg.have('PRETRAINED_MODEL'): + pretrain_cfg = cfg.PRETRAINED_MODEL + if pretrain_cfg is not None and not isinstance(pretrain_cfg, (str)): + raise TypeError('Pretrain parameter must be a string') + else: + pretrain_cfg = None + + model = build_from_config(cfg, registry, logger=logger, *args, **kwargs) + if pretrain_cfg is not None: + if hasattr(model, 'load_pretrained_model'): + model.load_pretrained_model(pretrain_cfg) + return model + + +ANNOTATORS = Registry('ANNOTATORS', build_func=build_annotator) diff --git a/scepter/modules/annotator/utils.py b/scepter/modules/annotator/utils.py new file mode 100644 index 0000000..672e921 --- /dev/null +++ b/scepter/modules/annotator/utils.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +import cv2 +import numpy as np + + +def resize_image(input_image, resolution): + H, W, C = input_image.shape + H = float(H) + W = float(W) + k = float(resolution) / min(H, W) + H *= k + W *= k + H = int(np.round(H / 64.0)) * 64 + W = int(np.round(W / 64.0)) * 64 + img = cv2.resize( + input_image, (W, H), + interpolation=cv2.INTER_LANCZOS4 if k > 1 else cv2.INTER_AREA) + return img, k + + +def resize_image_ori(h, w, image, k): + img = cv2.resize( + image, (w, h), + interpolation=cv2.INTER_LANCZOS4 if k > 1 else cv2.INTER_AREA) + return img + + +class AnnotatorProcessor(): + canny_cfg = { + 'NAME': 'CannyAnnotator', + 'LOW_THRESHOLD': 100, + 'HIGH_THRESHOLD': 200, + 'INPUT_KEYS': ['img'], + 'OUTPUT_KEYS': ['canny'] + } + hed_cfg = { + 'NAME': 'HedAnnotator', + 'PRETRAINED_MODEL': + 'ms://damo/scepter_scedit@annotator/ckpts/ControlNetHED.pth', + 'INPUT_KEYS': ['img'], + 'OUTPUT_KEYS': ['hed'] + } + openpose_cfg = { + 'NAME': 'OpenposeAnnotator', + 'BODY_MODEL_PATH': + 'ms://damo/scepter_scedit@annotator/ckpts/body_pose_model.pth', + 'HAND_MODEL_PATH': + 'ms://damo/scepter_scedit@annotator/ckpts/hand_pose_model.pth', + 'INPUT_KEYS': ['img'], + 'OUTPUT_KEYS': ['openpose'] + } + midas_cfg = { + 'NAME': 'MidasDetector', + 'PRETRAINED_MODEL': + 'ms://damo/scepter_scedit@annotator/ckpts/dpt_hybrid-midas-501f0c75.pt', + 'INPUT_KEYS': ['img'], + 'OUTPUT_KEYS': ['depth'] + } + mlsd_cfg = { + 'NAME': 'MLSDdetector', + 'PRETRAINED_MODEL': + 'ms://damo/scepter_scedit@annotator/ckpts/mlsd_large_512_fp32.pth', + 'INPUT_KEYS': ['img'], + 'OUTPUT_KEYS': ['mlsd'] + } + color_cfg = { + 'NAME': 'ColorAnnotator', + 'RATIO': 64, + 'INPUT_KEYS': ['img'], + 'OUTPUT_KEYS': ['color'] + } + + anno_type_map = { + 'canny': canny_cfg, + 'hed': hed_cfg, + 'pose': openpose_cfg, + 'depth': midas_cfg, + 'mlsd': mlsd_cfg, + 'color': color_cfg + } + + def __init__(self, anno_type): + from scepter.modules.annotator.registry import ANNOTATORS + from scepter.modules.utils.config import Config + from scepter.modules.utils.distribute import we + + if isinstance(anno_type, str): + assert anno_type in self.anno_type_map.keys() + anno_type = [anno_type] + elif isinstance(anno_type, (list, tuple)): + assert all(tp in self.anno_type_map.keys() for tp in anno_type) + else: + raise Exception(f'Error anno_type: {anno_type}') + + general_dict = { + 'NAME': 'GeneralAnnotator', + 'ANNOTATORS': [self.anno_type_map[tp] for tp in anno_type] + } + general_anno = Config(cfg_dict=general_dict, load=False) + self.general_ins = ANNOTATORS.build(general_anno).to(we.device_id) + + def run(self, image, anno_type=None): + output_image = self.general_ins({'img': image}) + if anno_type is not None: + if isinstance(anno_type, str) and anno_type in output_image: + return output_image[anno_type] + else: + return { + tp: output_image[tp] + for tp in anno_type if tp in output_image + } + else: + return output_image diff --git a/scepter/modules/data/dataset/__init__.py b/scepter/modules/data/dataset/__init__.py index f513bb1..1bde76b 100644 --- a/scepter/modules/data/dataset/__init__.py +++ b/scepter/modules/data/dataset/__init__.py @@ -6,5 +6,6 @@ from scepter.modules.data.dataset.dataset import (Image2ImageDataset, ImageClassifyPublicDataset, ImageTextPairDataset, Text2ImageDataset) -from scepter.modules.data.dataset.ms_dataset import ImageTextPairMSDataset +from scepter.modules.data.dataset.ms_dataset import ( + ImageTextPairFolderDataset, ImageTextPairMSDataset) from scepter.modules.data.dataset.registry import DATASETS diff --git a/scepter/modules/data/dataset/dataset.py b/scepter/modules/data/dataset/dataset.py index c82c50b..5fb7942 100644 --- a/scepter/modules/data/dataset/dataset.py +++ b/scepter/modules/data/dataset/dataset.py @@ -2,6 +2,7 @@ # Copyright (c) Alibaba, Inc. and its affiliates. import numbers +import os import sys from collections.abc import Iterable @@ -235,6 +236,7 @@ class Text2ImageDataset(BaseDataset): delimiter = cfg.get('DELIMITER', ',') fields = cfg.get('FIELDS', ['row_key', 'prompt']) prompt_prefix = cfg.get('PROMPT_PREFIX', '') + path_prefix = cfg.get('PATH_PREFIX', '') use_num = cfg.get('USE_NUM', -1) image_size = cfg.get('IMAGE_SIZE', 1024) @@ -257,11 +259,14 @@ class Text2ImageDataset(BaseDataset): if key in ['prompt', 'caption', 'text']: item['ori_prompt'] = value item['prompt'] = prompt_prefix + value + elif key in ['oss_key', 'path', 'img_path', 'target_img_path']: + item['meta']['img_path'] = os.path.join(path_prefix, value) + elif key in ['width', 'height']: + item['meta'][key] = int(value) elif key != 'meta': item[key] = value else: continue - self.items.append(item) if use_num > 0: self.items = self.items[:use_num] diff --git a/scepter/modules/data/dataset/ms_dataset.py b/scepter/modules/data/dataset/ms_dataset.py index 190135c..12b29aa 100644 --- a/scepter/modules/data/dataset/ms_dataset.py +++ b/scepter/modules/data/dataset/ms_dataset.py @@ -9,6 +9,7 @@ from scepter.modules.data.dataset.base_dataset import BaseDataset from scepter.modules.data.dataset.registry import DATASETS from scepter.modules.utils.config import dict_to_yaml from scepter.modules.utils.distribute import we +from scepter.modules.utils.file_system import FS @DATASETS.register_class() @@ -105,14 +106,17 @@ class ImageTextPairMSDataset(BaseDataset): raise ( 'Your must set MS_DATASET_NAME as modelscope dataset or your local dataset orignized ' 'as modelscope dataset.') + if FS.exists(ms_dataset_name): + ms_dataset_name = FS.get_dir_to_local_dir(ms_dataset_name) + ms_remap_path = ms_dataset_name try: self.data = MsDataset.load(str(ms_dataset_name), namespace=ms_dataset_namespace, subset_name=ms_dataset_subname, split=ms_dataset_split) - except Exception as e: + except Exception: self.logger.info( - f"Load Modelscope dataset failed with {e}, retry with download_mode='force_redownload'." + "Load Modelscope dataset failed, retry with download_mode='force_redownload'." ) try: self.data = MsDataset.load( @@ -177,3 +181,119 @@ class ImageTextPairMSDataset(BaseDataset): __class__.__name__, ImageTextPairMSDataset.para_dict, set_name=True) + + +@DATASETS.register_class() +class ImageTextPairFolderDataset(BaseDataset): + para_dict = { + 'DATA_FOLDER': { + 'value': '', + 'description': 'Dataset folder.' + }, + 'TRIGGER_WORDS': { + 'value': + '', + 'description': + 'The words used to describe the common features of your data, especially when you customize a ' + 'tuner. Use these words you can get what you want.' + }, + 'REPLACE_STYLE': { + 'value': + False, + 'description': + 'Whether use the MS_DATASET_SUBNAME to replace the word in your description, default is False.' + }, + 'HIGHLIGHT_KEYWORDS': { + 'value': + '', + 'description': + 'The keywords you want to highlight in prompt, which will be replace by .' + }, + 'KEYWORDS_SIGN': { + 'value': + '', + 'description': + 'The keywords sign you want to add, which is like <{HIGHLIGHT_KEYWORDS}{KEYWORDS_SIGN}>' + }, + 'OUTPUT_SIZE': { + 'value': + None, + 'description': + 'If you use the FlexibleResize transforms, this filed will output the image_size as [h, w],' + 'which will be used to set the output size of images used to train the model.' + }, + } + + def __init__(self, cfg, logger=None): + super().__init__(cfg=cfg, logger=logger) + data_folder = cfg.get('DATA_FOLDER', None) + self.replace_style = cfg.get('REPLACE_STYLE', False) + self.trigger_words = cfg.get('TRIGGER_WORDS', '') + self.replace_keywords = cfg.get('HIGHLIGHT_KEYWORDS', '') + self.keywords_sign = cfg.get('KEYWORDS_SIGN', '') + self.output_size = cfg.get('OUTPUT_SIZE', None) + if self.output_size is not None: + if isinstance(self.output_size, numbers.Number): + self.output_size = [self.output_size, self.output_size] + # Use modelscope dataset + if not data_folder or not FS.exists(data_folder): + raise ('Your must set datafolder for local dataset.') + data_folder = FS.get_dir_to_local_dir(data_folder) + all_lines = open(os.path.join(data_folder, 'train.csv'), + 'r').read().split('\n') + assert all_lines[0] == 'Target:FILE,Prompt' + self.data = [] + for line in all_lines[1:]: + line = line.strip() + if line == '': + continue + self.data.append({ + 'Target:FILE': + os.path.join(data_folder, + line.split(',', 1)[0]), + 'Prompt': + line.split(',', 1)[1] + }) + self.real_number = len(self.data) + + def __len__(self): + if self.mode == 'train': + return sys.maxsize + else: + return len(self.data) + + def _get(self, index: int): + current_data = self.data[index % len(self.data)] + # print(current_data.keys()) + image_path = current_data['Target:FILE'] + prompt = current_data['Prompt'] + style = current_data['Style'] if 'Style' in current_data else '' + # print(prompt, style) + if self.replace_style and not style == '': + prompt = prompt.replace(style, f'<{self.keywords_sign}>') + elif not self.replace_keywords.strip() == '': + prompt = prompt.replace( + self.replace_keywords, + '<' + self.replace_keywords + f'{self.keywords_sign}>') + if not self.trigger_words == '': + prompt = self.trigger_words.strip() + ' ' + prompt + if we.debug: + print(prompt, self.replace_keywords.strip()) + ret_item = { + 'meta': { + 'img_path': image_path, + 'data_key': style, + 'data_num': self.real_number + }, + 'prompt': prompt + } + if self.output_size is not None: + ret_item['meta']['image_size'] = self.output_size + return ret_item + + @staticmethod + def get_config_template(): + return dict_to_yaml('DATASet', + __class__.__name__, + ImageTextPairMSDataset.para_dict, + set_name=True) diff --git a/scepter/modules/data/dataset/utils.py b/scepter/modules/data/dataset/utils.py new file mode 100644 index 0000000..f34ab63 --- /dev/null +++ b/scepter/modules/data/dataset/utils.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Copyright (c) Alibaba, Inc. and its affiliates. + +from PIL import Image +from torch.utils.data.dataloader import default_collate + + +def pil_collate_fn(self, batch): + batch_data = {} + for items in batch: + for key, item in items.items(): + if isinstance(item, Image.Image): + if key not in batch_data: + batch_data[key] = [] + batch_data[key].append(item) + else: + if key not in batch_data: + batch_data[key] = [] + batch_data[key].append(item) + + for key, item in batch_data.items(): + if not all(isinstance(x, Image.Image) for x in item): + batch_data[key] = default_collate(item) + + return batch_data diff --git a/scepter/modules/inference/__init__.py b/scepter/modules/inference/__init__.py new file mode 100644 index 0000000..6c8b984 --- /dev/null +++ b/scepter/modules/inference/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from scepter.modules.inference.diffusion_inference import DiffusionInference diff --git a/scepter/modules/inference/diffusion_inference.py b/scepter/modules/inference/diffusion_inference.py new file mode 100644 index 0000000..0bd925c --- /dev/null +++ b/scepter/modules/inference/diffusion_inference.py @@ -0,0 +1,848 @@ +# -*- coding: utf-8 -*- +import copy +import hashlib +import json +import os.path +import random +from collections import OrderedDict + +import torch +import torch.nn as nn +import torch.nn.functional as F +import torchvision.transforms as TT +from peft.utils import CONFIG_NAME, SAFETENSORS_WEIGHTS_NAME, WEIGHTS_NAME +from PIL.Image import Image +from swift import Swift, SwiftModel + +from scepter.modules.model.network.diffusion.diffusion import GaussianDiffusion +from scepter.modules.model.network.diffusion.schedules import noise_schedule +from scepter.modules.model.registry import (BACKBONES, EMBEDDERS, MODELS, + TOKENIZERS, TUNERS) +from scepter.modules.utils.config import Config +from scepter.modules.utils.distribute import we +from scepter.modules.utils.file_system import FS + + +def get_model(model_tuple): + assert 'model' in model_tuple + return model_tuple['model'] + + +class DiffusionInference(): + ''' + define vae, unet, text-encoder, tuner, refiner components + support to load the components dynamicly. + create and load model when run this model at the first time. + ''' + def __init__(self, logger=None): + self.logger = logger + + def init_from_cfg(self, cfg): + self.name = cfg.NAME + self.is_default = cfg.get('IS_DEFAULT', False) + module_paras = self.load_default(cfg.get('DEFAULT_PARAS', None)) + assert cfg.have('MODEL') + cfg.MODEL = self.redefine_paras(cfg.MODEL) + self.diffusion = self.load_schedule(cfg.MODEL.SCHEDULE) + self.diffusion_model = self.infer_model( + cfg.MODEL.DIFFUSION_MODEL, module_paras.get( + 'DIFFUSION_MODEL', + None)) if cfg.MODEL.have('DIFFUSION_MODEL') else None + self.first_stage_model = self.infer_model( + cfg.MODEL.FIRST_STAGE_MODEL, + module_paras.get( + 'FIRST_STAGE_MODEL', + None)) if cfg.MODEL.have('FIRST_STAGE_MODEL') else None + self.cond_stage_model = self.infer_model( + cfg.MODEL.COND_STAGE_MODEL, + module_paras.get( + 'COND_STAGE_MODEL', + None)) if cfg.MODEL.have('COND_STAGE_MODEL') else None + self.refiner_cond_model = self.infer_model( + cfg.MODEL.REFINER_COND_MODEL, + module_paras.get( + 'REFINER_COND_MODEL', + None)) if cfg.MODEL.have('REFINER_COND_MODEL') else None + self.refiner_diffusion_model = self.infer_model( + cfg.MODEL.REFINER_MODEL, module_paras.get( + 'REFINER_MODEL', + None)) if cfg.MODEL.have('REFINER_MODEL') else None + self.tokenizer = TOKENIZERS.build( + cfg.MODEL.TOKENIZER, + logger=self.logger) if cfg.MODEL.have('TOKENIZER') else None + + if self.tokenizer is not None: + self.cond_stage_model['cfg'].KWARGS = { + 'vocab_size': self.tokenizer.vocab_size + } + + def register_tuner(self, tuner_model_list): + if len(tuner_model_list) < 1: + if isinstance(self.diffusion_model['model'], SwiftModel): + for adapter_name in self.diffusion_model['model'].adapters: + self.diffusion_model['model'].deactivate_adapter( + adapter_name, offload='cpu') + if isinstance(self.cond_stage_model['model'], SwiftModel): + for adapter_name in self.cond_stage_model['model'].adapters: + self.cond_stage_model['model'].deactivate_adapter( + adapter_name, offload='cpu') + return + all_diffusion_tuner = {} + all_cond_tuner = {} + save_root_dir = '.cache_tuner' + for tuner_model in tuner_model_list: + tunner_model_folder = tuner_model.MODEL_PATH + local_tuner_model = FS.get_dir_to_local_dir(tunner_model_folder) + all_tuner_datas = os.listdir(local_tuner_model) + cur_tuner_md5 = hashlib.md5( + tunner_model_folder.encode('utf-8')).hexdigest() + + local_diffusion_cache = os.path.join( + save_root_dir, cur_tuner_md5 + '_' + 'diffusion') + local_cond_cache = os.path.join(save_root_dir, + cur_tuner_md5 + '_' + 'cond') + + meta_file = os.path.join(save_root_dir, + cur_tuner_md5 + '_meta.json') + if not os.path.exists(meta_file): + diffusion_tuner = {} + cond_tuner = {} + for sub in all_tuner_datas: + sub_file = os.path.join(local_tuner_model, sub) + config_file = os.path.join(sub_file, CONFIG_NAME) + safe_file = os.path.join(sub_file, + SAFETENSORS_WEIGHTS_NAME) + bin_file = os.path.join(sub_file, WEIGHTS_NAME) + if os.path.isdir(sub_file) and os.path.isfile(config_file): + # diffusion or cond + cfg = json.load(open(config_file, 'r')) + if 'cond_stage_model.' in cfg['target_modules']: + cond_cfg = copy.deepcopy(cfg) + if 'cond_stage_model.*' in cond_cfg[ + 'target_modules']: + cond_cfg['target_modules'] = cond_cfg[ + 'target_modules'].replace( + 'cond_stage_model.*', '.*') + else: + cond_cfg['target_modules'] = cond_cfg[ + 'target_modules'].replace( + 'cond_stage_model.', '') + if cond_cfg['target_modules'].startswith('*'): + cond_cfg['target_modules'] = '.' + cond_cfg[ + 'target_modules'] + os.makedirs(local_cond_cache + '_' + sub, + exist_ok=True) + cond_tuner[os.path.basename(local_cond_cache) + + '_' + sub] = hashlib.md5( + (local_cond_cache + '_' + + sub).encode('utf-8')).hexdigest() + os.makedirs(local_cond_cache + '_' + sub, + exist_ok=True) + + json.dump( + cond_cfg, + open( + os.path.join(local_cond_cache + '_' + sub, + CONFIG_NAME), 'w')) + if 'model.' in cfg['target_modules'].replace( + 'cond_stage_model.', ''): + diffusion_cfg = copy.deepcopy(cfg) + if 'model.*' in diffusion_cfg['target_modules']: + diffusion_cfg[ + 'target_modules'] = diffusion_cfg[ + 'target_modules'].replace( + 'model.*', '.*') + else: + diffusion_cfg[ + 'target_modules'] = diffusion_cfg[ + 'target_modules'].replace( + 'model.', '') + if diffusion_cfg['target_modules'].startswith('*'): + diffusion_cfg[ + 'target_modules'] = '.' + diffusion_cfg[ + 'target_modules'] + os.makedirs(local_diffusion_cache + '_' + sub, + exist_ok=True) + diffusion_tuner[ + os.path.basename(local_diffusion_cache) + '_' + + sub] = hashlib.md5( + (local_diffusion_cache + '_' + + sub).encode('utf-8')).hexdigest() + json.dump( + diffusion_cfg, + open( + os.path.join( + local_diffusion_cache + '_' + sub, + CONFIG_NAME), 'w')) + + state_dict = {} + is_bin_file = True + if os.path.isfile(bin_file): + state_dict = torch.load(bin_file) + elif os.path.isfile(safe_file): + is_bin_file = False + from safetensors.torch import \ + load_file as safe_load_file + state_dict = safe_load_file( + safe_file, + device='cuda' + if torch.cuda.is_available() else 'cpu') + save_diffusion_state_dict = {} + save_cond_state_dict = {} + for key, value in state_dict.items(): + if key.startswith('model.'): + save_diffusion_state_dict[ + key[len('model.'):].replace( + sub, + os.path.basename(local_diffusion_cache) + + '_' + sub)] = value + elif key.startswith('cond_stage_model.'): + save_cond_state_dict[ + key[len('cond_stage_model.'):].replace( + sub, + os.path.basename(local_cond_cache) + + '_' + sub)] = value + + if is_bin_file: + if len(save_diffusion_state_dict) > 0: + torch.save( + save_diffusion_state_dict, + os.path.join( + local_diffusion_cache + '_' + sub, + WEIGHTS_NAME)) + if len(save_cond_state_dict) > 0: + torch.save( + save_cond_state_dict, + os.path.join(local_cond_cache + '_' + sub, + WEIGHTS_NAME)) + else: + from safetensors.torch import \ + save_file as safe_save_file + if len(save_diffusion_state_dict) > 0: + safe_save_file( + save_diffusion_state_dict, + os.path.join( + local_diffusion_cache + '_' + sub, + SAFETENSORS_WEIGHTS_NAME), + metadata={'format': 'pt'}) + if len(save_cond_state_dict) > 0: + safe_save_file( + save_cond_state_dict, + os.path.join(local_cond_cache + '_' + sub, + SAFETENSORS_WEIGHTS_NAME), + metadata={'format': 'pt'}) + json.dump( + { + 'diffusion_tuner': diffusion_tuner, + 'cond_tuner': cond_tuner + }, open(meta_file, 'w')) + else: + meta_conf = json.load(open(meta_file, 'r')) + diffusion_tuner = meta_conf['diffusion_tuner'] + cond_tuner = meta_conf['cond_tuner'] + all_diffusion_tuner.update(diffusion_tuner) + all_cond_tuner.update(cond_tuner) + if len(all_diffusion_tuner) > 0: + self.load(self.diffusion_model) + self.diffusion_model['model'] = Swift.from_pretrained( + self.diffusion_model['model'], + save_root_dir, + adapter_name=all_diffusion_tuner) + self.diffusion_model['model'].set_active_adapters( + list(all_diffusion_tuner.values())) + self.unload(self.diffusion_model) + if len(all_cond_tuner) > 0: + self.load(self.cond_stage_model) + self.cond_stage_model['model'] = Swift.from_pretrained( + self.cond_stage_model['model'], + save_root_dir, + adapter_name=all_cond_tuner) + self.cond_stage_model['model'].set_active_adapters( + list(all_cond_tuner.values())) + self.unload(self.cond_stage_model) + + def register_controllers(self, control_model_ins): + if control_model_ins is None or control_model_ins == '': + if isinstance(self.diffusion_model['model'], SwiftModel): + if (hasattr(self.diffusion_model['model'].base_model, + 'control_blocks') and + self.diffusion_model['model'].base_model.control_blocks + ): # noqa + del self.diffusion_model['model'].base_model.control_blocks + self.diffusion_model[ + 'model'].base_model.control_blocks = None + self.diffusion_model['model'].base_model.control_name = [] + else: + del self.diffusion_model['model'].control_blocks + self.diffusion_model['model'].control_blocks = None + self.diffusion_model['model'].control_name = [] + return + if not isinstance(control_model_ins, list): + control_model_ins = [control_model_ins] + control_model = nn.ModuleList([]) + control_model_folder = [] + for one_control in control_model_ins: + one_control_model_folder = one_control.MODEL_PATH + control_model_folder.append(one_control_model_folder) + have_list = getattr(self.diffusion_model['model'], 'control_name', + []) + if one_control_model_folder in have_list: + ind = have_list.index(one_control_model_folder) + csc_tuners = copy.deepcopy( + self.diffusion_model['model'].control_blocks[ind]) + else: + one_local_control_model = FS.get_dir_to_local_dir( + one_control_model_folder) + control_cfg = Config(cfg_file=os.path.join( + one_local_control_model, 'configuration.json')) + assert hasattr(control_cfg, 'CONTROL_MODEL') + control_cfg.CONTROL_MODEL[ + 'INPUT_BLOCK_CHANS'] = self.diffusion_model[ + 'model']._input_block_chans + control_cfg.CONTROL_MODEL[ + 'INPUT_DOWN_FLAG'] = self.diffusion_model[ + 'model']._input_down_flag + control_cfg.CONTROL_MODEL.PRETRAINED_MODEL = os.path.join( + one_local_control_model, 'pytorch_model.bin') + csc_tuners = TUNERS.build(control_cfg.CONTROL_MODEL, + logger=self.logger) + control_model.append(csc_tuners) + if isinstance(self.diffusion_model['model'], SwiftModel): + del self.diffusion_model['model'].base_model.control_blocks + self.diffusion_model[ + 'model'].base_model.control_blocks = control_model + self.diffusion_model[ + 'model'].base_model.control_name = control_model_folder + else: + del self.diffusion_model['model'].control_blocks + self.diffusion_model['model'].control_blocks = control_model + self.diffusion_model['model'].control_name = control_model_folder + + def redefine_paras(self, cfg): + if cfg.get('PRETRAINED_MODEL', None): + assert FS.isfile(cfg.PRETRAINED_MODEL) + with FS.get_from(cfg.PRETRAINED_MODEL, + wait_finish=True) as local_path: + if local_path.endswith('safetensors'): + from safetensors.torch import load_file as load_safetensors + sd = load_safetensors(local_path) + else: + sd = torch.load(local_path, map_location='cpu') + first_stage_model_path = os.path.join( + os.path.dirname(local_path), 'first_stage_model.pth') + cond_stage_model_path = os.path.join( + os.path.dirname(local_path), 'cond_stage_model.pth') + diffusion_model_path = os.path.join( + os.path.dirname(local_path), 'diffusion_model.pth') + if (not os.path.exists(first_stage_model_path) + or not os.path.exists(cond_stage_model_path) + or not os.path.exists(diffusion_model_path)): + self.logger.info( + 'Now read the whole model and rearrange the modules, it may take several mins.' + ) + first_stage_model = OrderedDict() + cond_stage_model = OrderedDict() + diffusion_model = OrderedDict() + for k, v in sd.items(): + if k.startswith('first_stage_model.'): + first_stage_model[k.replace( + 'first_stage_model.', '')] = v + elif k.startswith('conditioner.'): + cond_stage_model[k.replace('conditioner.', '')] = v + elif k.startswith('cond_stage_model.'): + if k.startswith('cond_stage_model.model.'): + cond_stage_model[k.replace( + 'cond_stage_model.model.', '')] = v + else: + cond_stage_model[k.replace( + 'cond_stage_model.', '')] = v + elif k.startswith('model.diffusion_model.'): + diffusion_model[k.replace('model.diffusion_model.', + '')] = v + else: + continue + if cfg.have('FIRST_STAGE_MODEL'): + with open(first_stage_model_path + 'cache', 'wb') as f: + torch.save(first_stage_model, f) + os.rename(first_stage_model_path + 'cache', + first_stage_model_path) + self.logger.info( + 'First stage model has been processed.') + if cfg.have('COND_STAGE_MODEL'): + with open(cond_stage_model_path + 'cache', 'wb') as f: + torch.save(cond_stage_model, f) + os.rename(cond_stage_model_path + 'cache', + cond_stage_model_path) + self.logger.info( + 'Cond stage model has been processed.') + if cfg.have('DIFFUSION_MODEL'): + with open(diffusion_model_path + 'cache', 'wb') as f: + torch.save(diffusion_model, f) + os.rename(diffusion_model_path + 'cache', + diffusion_model_path) + self.logger.info('Diffusion model has been processed.') + if not cfg.FIRST_STAGE_MODEL.get('PRETRAINED_MODEL', None): + cfg.FIRST_STAGE_MODEL.PRETRAINED_MODEL = first_stage_model_path + else: + cfg.FIRST_STAGE_MODEL.RELOAD_MODEL = first_stage_model_path + if not cfg.COND_STAGE_MODEL.get('PRETRAINED_MODEL', None): + cfg.COND_STAGE_MODEL.PRETRAINED_MODEL = cond_stage_model_path + else: + cfg.COND_STAGE_MODEL.RELOAD_MODEL = cond_stage_model_path + if not cfg.DIFFUSION_MODEL.get('PRETRAINED_MODEL', None): + cfg.DIFFUSION_MODEL.PRETRAINED_MODEL = diffusion_model_path + else: + cfg.DIFFUSION_MODEL.RELOAD_MODEL = diffusion_model_path + return cfg + + def init_from_modules(self, modules): + for k, v in modules.items(): + self.__setattr__(k, v) + + def infer_model(self, cfg, module_paras=None): + module = { + 'model': None, + 'cfg': cfg, + 'device': 'offline', + 'name': cfg.NAME, + 'function_info': {}, + 'paras': {} + } + if module_paras is None: + return module + function_info = {} + paras = { + k.lower(): v + for k, v in module_paras.get('PARAS', {}).items() + } + for function in module_paras.get('FUNCTION', []): + input_dict = {} + for inp in function.get('INPUT', []): + if inp.lower() in self.input: + input_dict[inp.lower()] = self.input[inp.lower()] + function_info[function.NAME] = { + 'dtype': function.get('DTYPE', 'float32'), + 'input': input_dict + } + module['paras'] = paras + module['function_info'] = function_info + return module + + def init_from_ckpt(self, path, model, ignore_keys=list()): + if path.endswith('safetensors'): + from safetensors.torch import load_file as load_safetensors + sd = load_safetensors(path) + else: + sd = torch.load(path, map_location='cpu') + + new_sd = OrderedDict() + for k, v in sd.items(): + ignored = False + for ik in ignore_keys: + if ik in k: + if we.rank == 0: + self.logger.info( + 'Ignore key {} from state_dict.'.format(k)) + ignored = True + break + if not ignored: + new_sd[k] = v + + missing, unexpected = model.load_state_dict(new_sd, strict=False) + if we.rank == 0: + self.logger.info( + f'Restored from {path} with {len(missing)} missing and {len(unexpected)} unexpected keys' + ) + if len(missing) > 0: + self.logger.info(f'Missing Keys:\n {missing}') + if len(unexpected) > 0: + self.logger.info(f'\nUnexpected Keys:\n {unexpected}') + + def load(self, module): + if module['device'] == 'offline': + if module['cfg'].NAME in MODELS.class_map: + model = MODELS.build(module['cfg'], logger=self.logger).eval() + elif module['cfg'].NAME in BACKBONES.class_map: + model = BACKBONES.build(module['cfg'], + logger=self.logger).eval() + elif module['cfg'].NAME in EMBEDDERS.class_map: + model = EMBEDDERS.build(module['cfg'], + logger=self.logger).eval() + else: + raise NotImplementedError + if module['cfg'].get('RELOAD_MODEL', None): + self.init_from_ckpt(module['cfg'].RELOAD_MODEL, model) + module['model'] = model + module['device'] = 'cpu' + if module['device'] == 'cpu': + module['device'] = we.device_id + module['model'] = module['model'].to(we.device_id) + return module + + def unload(self, module): + module['model'] = module['model'].to('cpu') + module['device'] = 'cpu' + torch.cuda.empty_cache() + torch.cuda.ipc_collect() + return module + + def load_default(self, cfg): + module_paras = {} + if cfg is not None: + self.paras = cfg.PARAS + self.input = {k.lower(): v for k, v in cfg.INPUT.items()} + self.output = {k.lower(): v for k, v in cfg.OUTPUT.items()} + module_paras = cfg.MODULES_PARAS + return module_paras + + def load_schedule(self, cfg): + parameterization = cfg.get('PARAMETERIZATION', 'eps') + assert parameterization in [ + 'eps', 'x0', 'v' + ], 'currently only supporting "eps" and "x0" and "v"' + num_timesteps = cfg.get('TIMESTEPS', 1000) + + schedule_args = { + k.lower(): v + for k, v in cfg.get('SCHEDULE_ARGS', { + 'NAME': 'logsnr_cosine_interp', + 'SCALE_MIN': 2.0, + 'SCALE_MAX': 4.0 + }).items() + } + + zero_terminal_snr = cfg.get('ZERO_TERMINAL_SNR', False) + if zero_terminal_snr: + assert parameterization == 'v', 'Now zero_terminal_snr only support v-prediction mode.' + sigmas = noise_schedule(schedule=schedule_args.pop('name'), + n=num_timesteps, + zero_terminal_snr=zero_terminal_snr, + **schedule_args) + diffusion = GaussianDiffusion(sigmas=sigmas, + prediction_type=parameterization) + return diffusion + + def get_batch(self, value_dict, num_samples=1): + batch = {} + batch_uc = {} + N = num_samples + device = we.device_id + for key in value_dict: + if key == 'prompt': + if not self.tokenizer: + batch['prompt'] = value_dict['prompt'] + batch_uc['prompt'] = value_dict['negative_prompt'] + else: + batch['tokens'] = self.tokenizer(value_dict['prompt']).to( + we.device_id) + batch_uc['tokens'] = self.tokenizer( + value_dict['negative_prompt']).to(we.device_id) + elif key == 'original_size_as_tuple': + batch['original_size_as_tuple'] = (torch.tensor( + value_dict['original_size_as_tuple']).to(device).repeat( + N, 1)) + elif key == 'crop_coords_top_left': + batch['crop_coords_top_left'] = (torch.tensor( + value_dict['crop_coords_top_left']).to(device).repeat( + N, 1)) + elif key == 'aesthetic_score': + batch['aesthetic_score'] = (torch.tensor( + [value_dict['aesthetic_score']]).to(device).repeat(N, 1)) + batch_uc['aesthetic_score'] = (torch.tensor([ + value_dict['negative_aesthetic_score'] + ]).to(device).repeat(N, 1)) + + elif key == 'target_size_as_tuple': + batch['target_size_as_tuple'] = (torch.tensor( + value_dict['target_size_as_tuple']).to(device).repeat( + N, 1)) + elif key == 'image': + batch[key] = self.load_image(value_dict[key], num_samples=N) + else: + batch[key] = value_dict[key] + + for key in batch.keys(): + if key not in batch_uc and isinstance(batch[key], torch.Tensor): + batch_uc[key] = torch.clone(batch[key]) + return batch, batch_uc + + def load_image(self, image, num_samples=1): + if isinstance(image, torch.Tensor): + pass + elif isinstance(image, Image): + pass + elif isinstance(image, Image): + pass + + def get_function_info(self, module, function_name=None): + all_function = module['function_info'] + if function_name in all_function: + return function_name, all_function[function_name]['dtype'] + if function_name is None and len(all_function) == 1: + for k, v in all_function.items(): + return k, v['dtype'] + + def encode_first_stage(self, x, **kwargs): + _, dtype = self.get_function_info(self.first_stage_model, 'encode') + with torch.autocast('cuda', + enabled=dtype == 'float16', + dtype=getattr(torch, dtype)): + z = get_model(self.first_stage_model).encode(x) + return self.first_stage_model['paras']['scale_factor'] * z + + def decode_first_stage(self, z): + _, dtype = self.get_function_info(self.first_stage_model, 'encode') + with torch.autocast('cuda', + enabled=dtype == 'float16', + dtype=getattr(torch, dtype)): + z = 1. / self.first_stage_model['paras']['scale_factor'] * z + return get_model(self.first_stage_model).decode(z) + + @torch.no_grad() + def __call__(self, + input, + num_samples=1, + intermediate_callback=None, + refine_strength=0, + img_to_img_strength=0, + cat_uc=True, + tuner_model=None, + control_model=None, + **kwargs): + + value_input = copy.deepcopy(self.input) + value_input.update(input) + print(value_input) + height, width = value_input['target_size_as_tuple'] + value_output = copy.deepcopy(self.output) + batch, batch_uc = self.get_batch(value_input, num_samples=1) + # + if not isinstance(tuner_model, list): + tuner_model = [tuner_model] + for tuner in tuner_model: + if tuner is None or tuner == '': + tuner_model.remove(tuner) + self.register_tuner(tuner_model) + # control_cond_image + control_cond_image = kwargs.pop('control_cond_image', None) + # crop_type = kwargs.pop('crop_type', 'center_crop') + hints = [] + if control_cond_image and control_model: + if not isinstance(control_model, list): + control_model = [control_model] + if not isinstance(control_cond_image, list): + control_cond_image = [control_cond_image] + assert len(control_cond_image) == len(control_model) + for img in control_cond_image: + if isinstance(img, Image): + w, h = img.size + if not h == height or not w == width: + img = TT.Resize(min(height, width))(img) + img = TT.CenterCrop((height, width))(img) + hint = TT.ToTensor()(img) + hints.append(hint) + else: + raise NotImplementedError + if len(hints) > 0: + hints = torch.stack(hints).to(we.device_id) + else: + hints = None + + # first stage encode + image = input.pop('image', None) + if image is not None and img_to_img_strength > 0: + # run image2image + b, c, ori_width, ori_height = image.shape + if not (ori_width == width and ori_height == height): + image = F.interpolate(image, (width, height), mode='bicubic') + self.first_stage_model = self.load(self.first_stage_model) + input_latent = self.encode_first_stage(image) + self.first_stage_model = self.unload(self.first_stage_model) + else: + input_latent = None + if 'input_latent' in value_output and input_latent is not None: + value_output['input_latent'] = input_latent + # cond stage + self.cond_stage_model = self.load(self.cond_stage_model) + function_name, dtype = self.get_function_info(self.cond_stage_model) + with torch.autocast('cuda', + enabled=dtype == 'float16', + dtype=getattr(torch, dtype)): + if self.tokenizer: + context = getattr(get_model(self.cond_stage_model), + function_name)(batch['tokens']) + null_context = getattr(get_model(self.cond_stage_model), + function_name)(batch_uc['tokens']) + else: + context = getattr(get_model(self.cond_stage_model), + function_name)(batch) + null_context = getattr(get_model(self.cond_stage_model), + function_name)(batch_uc) + self.cond_stage_model = self.unload(self.cond_stage_model) + + if refine_strength > 0 and self.refiner_diffusion_model is not None: + assert self.refiner_cond_model is not None + self.refiner_cond_model = self.load(self.refiner_cond_model) + function_name, dtype = self.get_function_info( + self.refiner_cond_model) + with torch.autocast('cuda', + enabled=dtype == 'float16', + dtype=getattr(torch, dtype)): + if self.tokenizer: + refine_context = getattr( + get_model(self.refiner_cond_model), + function_name)(batch['tokens']) + refine_null_context = getattr( + get_model(self.refiner_cond_model), + function_name)(batch_uc['tokens']) + else: + refine_context = getattr( + get_model(self.refiner_cond_model), + function_name)(batch) + refine_null_context = getattr( + get_model(self.refiner_cond_model), + function_name)(batch_uc) + self.refiner_cond_model = self.unload(self.refiner_cond_model) + self.load(self.diffusion_model) + self.register_controllers(control_model) + self.unload(self.diffusion_model) + # get noise + seed = kwargs.pop('seed', -1) + g = torch.Generator(device=we.device_id) + seed = seed if seed >= 0 else random.randint(0, 2**32 - 1) + g.manual_seed(seed) + if 'seed' in value_output: + value_output['seed'] = seed + for sample_id in range(num_samples): + if self.diffusion_model is not None: + noise = torch.empty( + 1, + 4, + height // self.first_stage_model['paras']['size_factor'], + width // self.first_stage_model['paras']['size_factor'], + device=we.device_id).normal_(generator=g) + # + self.load(self.diffusion_model) + # UNet use input n_prompt + function_name, dtype = self.get_function_info( + self.diffusion_model) + with torch.autocast('cuda', + enabled=dtype == 'float16', + dtype=getattr(torch, dtype)): + latent = self.diffusion.sample( + noise=noise, + x=input_latent, + denoising_strength=img_to_img_strength + if input_latent is not None else 1.0, + refine_strength=refine_strength, + solver=value_input.get('sample', 'ddim'), + model=get_model(self.diffusion_model), + model_kwargs=[{ + 'cond': context, + 'hint': hints + }, { + 'cond': null_context, + 'hint': hints + }], + steps=value_input.get('sample_steps', 50), + guide_scale=value_input.get('guide_scale', 7.5), + guide_rescale=value_input.get('guide_rescale', 0.5), + discretization=value_input.get('discretization', + 'trailing'), + show_progress=True, + seed=seed, + condition_fn=None, + clamp=None, + percentile=None, + t_max=None, + t_min=None, + discard_penultimate_step=None, + intermediate_callback=intermediate_callback, + cat_uc=cat_uc, + **kwargs) + self.diffusion_model = self.unload(self.diffusion_model) + + # apply refiner + if refine_strength > 0 and self.refiner_diffusion_model is not None: + assert self.refiner_diffusion_model is not None + # decode intermidiet latent before refine + self.first_stage_model = self.load(self.first_stage_model) + before_refiner_samples = self.decode_first_stage( + latent).float() + self.first_stage_model = self.unload(self.first_stage_model) + + before_refiner_samples = torch.clamp( + (before_refiner_samples + 1.0) / 2.0, min=0.0, max=1.0) + if 'before_refine_images' in value_output: + if value_output['before_refine_images'] is None or ( + isinstance(value_output['before_refine_images'], + list) + and len(value_output['before_refine_images']) < 1): + value_output['before_refine_images'] = [] + value_output['before_refine_images'].append( + before_refiner_samples) + self.refiner_model = self.load(self.refiner_diffusion_model) + function_name, dtype = self.get_function_info( + self.refiner_model) + with torch.autocast('cuda', + enabled=dtype == 'float16', + dtype=getattr(torch, dtype)): + latent = self.diffusion.sample( + noise=noise, + x=latent, + denoising_strength=img_to_img_strength + if input_latent is not None else 1.0, + refine_strength=refine_strength, + refine_stage=True, + solver=value_input.get('refine_sample', 'ddim'), + model=get_model(self.refiner_model), + model_kwargs=[{ + 'cond': refine_context + }, { + 'cond': refine_null_context + }], + steps=value_input.get('sample_steps', 50), + guide_scale=value_input.get('refine_guide_scale', 7.5), + guide_rescale=value_input.get('refine_guide_rescale', + 0.5), + discretization=value_input.get('refine_discretization', + 'trailing'), + show_progress=True, + seed=seed, + condition_fn=None, + clamp=None, + percentile=None, + t_max=None, + t_min=None, + discard_penultimate_step=None, + return_intermediate=None, + intermediate_callback=intermediate_callback, + cat_uc=cat_uc, + **kwargs) + self.refiner_model = self.unload(self.refiner_model) + + if 'latent' in value_output: + if value_output['latent'] is None or ( + isinstance(value_output['latent'], list) + and len(value_output['latent']) < 1): + value_output['latent'] = [] + value_output['latent'].append(latent) + + self.first_stage_model = self.load(self.first_stage_model) + x_samples = self.decode_first_stage(latent).float() + self.first_stage_model = self.unload(self.first_stage_model) + + images = torch.clamp((x_samples + 1.0) / 2.0, min=0.0, max=1.0) + if 'images' in value_output: + if value_output['images'] is None or ( + isinstance(value_output['images'], list) + and len(value_output['images']) < 1): + value_output['images'] = [] + value_output['images'].append(images) + + for k, v in value_output.items(): + if isinstance(v, list): + value_output[k] = torch.cat(v, dim=0) + if isinstance(v, torch.Tensor): + value_output[k] = v.cpu() + return value_output diff --git a/scepter/modules/model/backbone/unet/unet_module.py b/scepter/modules/model/backbone/unet/unet_module.py index b7e399e..9fcb98a 100644 --- a/scepter/modules/model/backbone/unet/unet_module.py +++ b/scepter/modules/model/backbone/unet/unet_module.py @@ -190,6 +190,7 @@ class DiffusionUNet(BaseModel): super().__init__(cfg, logger=logger) self.init_params(cfg) self.construct_network() + self.control_blocks = None def init_params(self, cfg): self.in_channels = cfg.IN_CHANNELS @@ -285,6 +286,7 @@ class DiffusionUNet(BaseModel): ]) self._feature_size = model_channels input_block_chans = [model_channels] + input_down_flag = [False] ch = model_channels ds = 1 for level, mult in enumerate(channel_mult): @@ -323,6 +325,7 @@ class DiffusionUNet(BaseModel): self.input_blocks.append(TimestepEmbedSequential(*layers)) self._feature_size += ch input_block_chans.append(ch) + input_down_flag.append(False) if level != len(channel_mult) - 1: out_ch = ch self.input_blocks.append( @@ -341,9 +344,11 @@ class DiffusionUNet(BaseModel): ) ch = out_ch input_block_chans.append(ch) + input_down_flag.append(True) ds *= 2 self._feature_size += ch self._input_block_chans = copy.deepcopy(input_block_chans) + self._input_down_flag = input_down_flag if num_head_channels == -1: dim_head = ch // num_heads @@ -479,22 +484,7 @@ class DiffusionUNet(BaseModel): if len(unexpected) > 0: self.logger.info(f'\nUnexpected Keys:\n {unexpected}') - def forward(self, x, t=None, cond=dict()): - t_emb = timestep_embedding(t, self.model_channels, repeat_only=False) - emb = self.time_embed(t_emb) - - if isinstance(cond, dict): - if 'y' in cond and cond['y'] is not None: - assert self.num_classes is not None - emb = emb + self.label_emb(cond['y']) - if 'concat' in cond: - c = cond['concat'] - x = torch.cat([x, c], dim=1) - - context = cond.get('crossattn', None) - else: - context = cond - + def _forward_origin(self, x, emb, context, hint=None): hs = [] h = x for module in self.input_blocks: @@ -505,8 +495,76 @@ class DiffusionUNet(BaseModel): h = torch.cat([h, self.lsc_identity[m_id](hs.pop())], dim=1) target_size = hs[-1].shape[-2:] if len(hs) > 0 else None h = module(h, emb, context, target_size) + out = self.out(h) + return out - return self.out(h) + def _forward_control(self, x, emb, context, hint, alpha=0.5): + multi_csc_tuners = self.control_blocks + # hints + multi_hint_hs = [] + for sc_id, csc_tuners in enumerate(multi_csc_tuners): + hint_input = hint[sc_id] if isinstance(hint, list) else hint + hint_h = csc_tuners.pre_hint_blocks(hint_input) + hint_hs = [] + for dsh_blk in csc_tuners.dense_hint_blocks: + hint_h = dsh_blk(hint_h) + hint_hs.append(hint_h) + multi_hint_hs.append(hint_hs) + # unet + hs = [] + h = x + for module in self.input_blocks: + h = module(h, emb, context) + hs.append(h) + h = self.middle_block(h, emb, context) + for m_id, module in enumerate(self.output_blocks): + skip_h = hs.pop() + multi_control_h = 0 + for sc_id, csc_tuners in enumerate(multi_csc_tuners): + hint_h = multi_hint_hs[sc_id][::-1][m_id] + control_h = csc_tuners.lsc_tuner_blocks[m_id]( + skip_h + hint_h, x_shortcut=hint_h) + multi_control_h += csc_tuners.scale * control_h + tuner_h = self.lsc_identity[m_id](skip_h) - skip_h + if torch.all( + torch.isclose(tuner_h, + torch.zeros_like(tuner_h), + atol=1e-6)): + # csc-tuner + skip_h_new = skip_h + multi_control_h + else: + # csc-tuner + sc-tuner + skip_h_new = skip_h + alpha * multi_control_h + ( + 1 - alpha) * tuner_h + h = torch.cat([h, skip_h_new], dim=1) + target_size = hs[-1].shape[-2:] if len(hs) > 0 else None + h = module(h, emb, context, target_size) + out = self.out(h) + return out + + def forward(self, x, t=None, cond=dict(), **kwargs): + t_emb = timestep_embedding(t, self.model_channels, repeat_only=False) + emb = self.time_embed(t_emb) + hint = None + if isinstance(cond, dict): + if 'y' in cond and cond['y'] is not None: + assert self.num_classes is not None + emb = emb + self.label_emb(cond['y']) + if 'concat' in cond: + c = cond['concat'] + x = torch.cat([x, c], dim=1) + if 'hint' in cond: + hint = cond['hint'] + context = cond.get('crossattn', None) + else: + context = cond + hint = kwargs.pop('hint', None) + + if self.control_blocks is not None: + out = self._forward_control(x, emb, context, hint) + else: + out = self._forward_origin(x, emb, context) + return out @staticmethod def get_config_template(): @@ -602,6 +660,7 @@ class DiffusionUNetXL(DiffusionUNet): ]) self._feature_size = model_channels input_block_chans = [model_channels] + input_down_flag = [False] ch = model_channels ds = 1 for level, mult in enumerate(channel_mult): @@ -640,6 +699,7 @@ class DiffusionUNetXL(DiffusionUNet): self.input_blocks.append(TimestepEmbedSequential(*layers)) self._feature_size += ch input_block_chans.append(ch) + input_down_flag.append(False) if level != len(channel_mult) - 1: out_ch = ch self.input_blocks.append( @@ -658,9 +718,11 @@ class DiffusionUNetXL(DiffusionUNet): ) ch = out_ch input_block_chans.append(ch) + input_down_flag.append(True) ds *= 2 self._feature_size += ch self._input_block_chans = copy.deepcopy(input_block_chans) + self._input_down_flag = input_down_flag if num_head_channels == -1: dim_head = ch // num_heads @@ -760,25 +822,7 @@ class DiffusionUNetXL(DiffusionUNet): conv_nd(dims, model_channels, out_channels, 3, padding=1)), ) - def forward(self, x, t=None, cond=dict()): - t_emb = timestep_embedding(t, - self.model_channels, - repeat_only=False, - legacy=True) - emb = self.time_embed(t_emb) - - if isinstance(cond, dict): - if 'y' in cond: - assert self.num_classes is not None - emb = emb + self.label_emb(cond['y']) - if 'concat' in cond: - c = cond['concat'] - x = torch.cat([x, c], dim=1) - - context = cond.get('crossattn', None) - else: - context = cond - + def _forward_origin(self, x, emb, context, hint=None): hs = [] h = x for module in self.input_blocks: @@ -789,8 +833,79 @@ class DiffusionUNetXL(DiffusionUNet): h = torch.cat([h, self.lsc_identity[m_id](hs.pop())], dim=1) target_size = hs[-1].shape[-2:] if len(hs) > 0 else None h = module(h, emb, context, target_size) + out = self.out(h) + return out - return self.out(h) + def _forward_control(self, x, emb, context, hint, alpha=0.5): + multi_csc_tuners = self.control_blocks + # hints + multi_hint_hs = [] + for sc_id, csc_tuners in enumerate(multi_csc_tuners): + hint_input = hint[sc_id] if isinstance(hint, list) else hint + hint_h = csc_tuners.pre_hint_blocks(hint_input) + hint_hs = [] + for dsh_blk in csc_tuners.dense_hint_blocks: + hint_h = dsh_blk(hint_h) + hint_hs.append(hint_h) + multi_hint_hs.append(hint_hs) + # unet + hs = [] + h = x + for module in self.input_blocks: + h = module(h, emb, context) + hs.append(h) + h = self.middle_block(h, emb, context) + for m_id, module in enumerate(self.output_blocks): + skip_h = hs.pop() + multi_control_h = 0 + for sc_id, csc_tuners in enumerate(multi_csc_tuners): + hint_h = multi_hint_hs[sc_id][::-1][m_id] + control_h = csc_tuners.lsc_tuner_blocks[m_id]( + skip_h + hint_h, x_shortcut=hint_h) + multi_control_h += csc_tuners.scale * control_h + tuner_h = self.lsc_identity[m_id](skip_h) - skip_h + if torch.all( + torch.isclose(tuner_h, + torch.zeros_like(tuner_h), + atol=1e-6)): + # csc-tuner + skip_h_new = skip_h + multi_control_h + else: + # csc-tuner + sc-tuner + skip_h_new = skip_h + alpha * multi_control_h + ( + 1 - alpha) * tuner_h + h = torch.cat([h, skip_h_new], dim=1) + target_size = hs[-1].shape[-2:] if len(hs) > 0 else None + h = module(h, emb, context, target_size) + out = self.out(h) + return out + + def forward(self, x, t=None, cond=dict(), **kwargs): + t_emb = timestep_embedding(t, + self.model_channels, + repeat_only=False, + legacy=True) + emb = self.time_embed(t_emb) + hint = None + if isinstance(cond, dict): + if 'y' in cond: + assert self.num_classes is not None + emb = emb + self.label_emb(cond['y']) + if 'concat' in cond: + c = cond['concat'] + x = torch.cat([x, c], dim=1) + if 'hint' in cond: + hint = cond['hint'] + context = cond.get('crossattn', None) + else: + context = cond + hint = kwargs.pop('hint', None) + + if self.control_blocks is not None: + out = self._forward_control(x, emb, context, hint) + else: + out = self._forward_origin(x, emb, context) + return out def convert_to_fp16(self): """ diff --git a/scepter/modules/model/embedder/embedder.py b/scepter/modules/model/embedder/embedder.py index e710cef..5cc1d38 100644 --- a/scepter/modules/model/embedder/embedder.py +++ b/scepter/modules/model/embedder/embedder.py @@ -224,16 +224,13 @@ class FrozenOpenCLIPEmbedder(BaseEmbedder): super().__init__(cfg, logger=logger) arch = cfg.get('ARCH', 'ViT-H-14') - if cfg.PRETRAINED_MODEL is None: - model, _, _ = open_clip.create_model_and_transforms( - arch, device=torch.device('cpu'), pretrained=None) - del model.visual - else: + model, _, _ = open_clip.create_model_and_transforms( + arch, device=torch.device('cpu'), pretrained=None) + del model.visual + if cfg.PRETRAINED_MODEL is not None: with FS.get_from(cfg.PRETRAINED_MODEL, wait_finish=True) as local_path: - model, _, _ = open_clip.create_model_and_transforms( - arch, device=torch.device('cpu'), pretrained=local_path) - del model.visual + model.load_state_dict(torch.load(local_path), strict=False) self.model = model self.use_grad = cfg.get('USE_GRAD', False) @@ -362,7 +359,7 @@ class FrozenOpenCLIPEmbedder2(BaseEmbedder): def __init__(self, cfg, logger=None): super().__init__(cfg, logger=logger) arch = cfg.get('ARCH', 'ViT-H-14') - if cfg.PRETRAINED_MODEL is None: + if cfg.get('PRETRAINED_MODEL', None) is None: model, _, _ = open_clip.create_model_and_transforms( arch, device=torch.device('cpu'), pretrained=None) del model.visual diff --git a/scepter/modules/model/network/__init__.py b/scepter/modules/model/network/__init__.py index dda2aba..0e11597 100644 --- a/scepter/modules/model/network/__init__.py +++ b/scepter/modules/model/network/__init__.py @@ -4,4 +4,4 @@ from scepter.modules.model.network.autoencoder import ae_kl from scepter.modules.model.network.classifier import Classifier from scepter.modules.model.network.diffusion import (diffusion, schedules, solvers) -from scepter.modules.model.network.ldm import ldm, ldm_xl +from scepter.modules.model.network.ldm import ldm, ldm_sce, ldm_xl diff --git a/scepter/modules/model/network/diffusion/diffusion.py b/scepter/modules/model/network/diffusion/diffusion.py index ac0240d..5a23c56 100644 --- a/scepter/modules/model/network/diffusion/diffusion.py +++ b/scepter/modules/model/network/diffusion/diffusion.py @@ -159,7 +159,8 @@ class GaussianDiffusion(object): model, model_kwargs={}, reduction='mean', - noise=None): + noise=None, + **kwargs): # hyperparams sigmas = _i(self.sigmas, t, x0) alphas = _i(self.alphas, t, x0) @@ -168,7 +169,7 @@ class GaussianDiffusion(object): if noise is None: noise = torch.randn_like(x0) xt = self.diffuse(x0, t, noise) - out = model(xt, t=t, **model_kwargs) + out = model(xt, t=t, **model_kwargs, **kwargs) # mse loss target = { diff --git a/scepter/modules/model/network/diffusion/solvers.py b/scepter/modules/model/network/diffusion/solvers.py index a8fcb7c..ab4bf22 100644 --- a/scepter/modules/model/network/diffusion/solvers.py +++ b/scepter/modules/model/network/diffusion/solvers.py @@ -54,7 +54,8 @@ def sample_euler(noise, s_tmax=float('inf'), s_noise=1., seed=None, - show_progress=True): + show_progress=True, + **kwargs): """ Implements Algorithm 2 (Euler steps) from Karras et al. (2022). """ @@ -87,7 +88,8 @@ def sample_euler_ancestral(noise, eta=1., s_noise=1., seed=None, - show_progress=True): + show_progress=True, + **kwargs): """ Ancestral sampling with Euler method steps. """ @@ -120,7 +122,8 @@ def sample_heun(noise, s_tmax=float('inf'), s_noise=1., seed=None, - show_progress=True): + show_progress=True, + **kwargs): """ Implements Algorithm 2 (Heun steps) from Karras et al. (2022). """ @@ -165,7 +168,8 @@ def sample_dpm_2(noise, s_tmax=float('inf'), s_noise=1., seed=None, - show_progress=True): + show_progress=True, + **kwargs): """ A sampler inspired by DPM-Solver-2 and Algorithm 2 from Karras et al. (2022). """ @@ -211,7 +215,8 @@ def sample_dpm_2_ancestral(noise, eta=1., s_noise=1., seed=None, - show_progress=True): + show_progress=True, + **kwargs): """ Ancestral sampling with DPM-Solver second-order steps. """ @@ -253,7 +258,8 @@ def sample_dpmpp_2s_ancestral(noise, eta=1., s_noise=1., seed=None, - show_progress=True): + show_progress=True, + **kwargs): """ Ancestral sampling with DPM-Solver++ (2S) second-order steps. """ @@ -372,7 +378,8 @@ def sample_dpmpp_sde(noise, s_noise=1., r=1 / 2, seed=None, - show_progress=True): + show_progress=True, + **kwargs): """ DPM-Solver++ (stochastic). """ @@ -429,7 +436,12 @@ def sample_dpmpp_sde(noise, @torch.no_grad() -def sample_dpmpp_2m(noise, model, sigmas, seed=None, show_progress=True): +def sample_dpmpp_2m(noise, + model, + sigmas, + seed=None, + show_progress=True, + **kwargs): """ DPM-Solver++ (2M). """ @@ -475,7 +487,8 @@ def sample_dpmpp_2m_sde(noise, s_noise=1., solver_type='midpoint', seed=None, - show_progress=True): + show_progress=True, + **kwargs): """ DPM-Solver++ (2M) SDE. """ @@ -527,7 +540,13 @@ def sample_dpmpp_2m_sde(noise, # -------------------- variation preserving (VP) solver --------------------# @torch.no_grad() -def sample_ddim(noise, model, sigmas, eta=0., seed=None, show_progress=True): +def sample_ddim(noise, + model, + sigmas, + eta=0., + seed=None, + show_progress=True, + **kwargs): """ DDIM solver steps. """ @@ -556,7 +575,8 @@ def sample_img2img_euler(noise, s_tmax=float('inf'), s_noise=1., seed=None, - show_progress=True): + show_progress=True, + **kwargs): """ Implements Algorithm 2 (Euler steps) from Karras et al. (2022). """ @@ -588,7 +608,8 @@ def sample_img2img_euler_ancestral(noise, eta=1., s_noise=1., seed=None, - show_progress=True): + show_progress=True, + **kwargs): """ Ancestral sampling with Euler method steps. """ diff --git a/scepter/modules/model/network/ldm/__init__.py b/scepter/modules/model/network/ldm/__init__.py index 30f2253..bb8d1a9 100644 --- a/scepter/modules/model/network/ldm/__init__.py +++ b/scepter/modules/model/network/ldm/__init__.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- # Copyright (c) Alibaba, Inc. and its affiliates. from scepter.modules.model.network.ldm.ldm import LatentDiffusion +from scepter.modules.model.network.ldm.ldm_sce import ( + LatentDiffusionSCEControl, LatentDiffusionSCETuning, + LatentDiffusionXLSCEControl, LatentDiffusionXLSCETuning) from scepter.modules.model.network.ldm.ldm_xl import LatentDiffusionXL diff --git a/scepter/modules/model/network/ldm/ldm.py b/scepter/modules/model/network/ldm/ldm.py index 5e0ffff..4063bf5 100644 --- a/scepter/modules/model/network/ldm/ldm.py +++ b/scepter/modules/model/network/ldm/ldm.py @@ -241,6 +241,14 @@ class LatentDiffusion(TrainModule): with torch.autocast(device_type='cuda', enabled=False): context = self.encode_condition( self.tokenizer(prompt).to(we.device_id)) + if 'hint' in kwargs and kwargs['hint'] is not None: + hint = kwargs.pop('hint') + if isinstance(context, dict): + context['hint'] = hint + else: + context = {'crossattn': context, 'hint': hint} + else: + hint = None if self.min_snr_gamma is not None: alphas = self.diffusion.alphas.to(we.device_id)[t] sigmas = self.diffusion.sigmas.pow(2).to(we.device_id)[t] @@ -250,11 +258,13 @@ class LatentDiffusion(TrainModule): else: weights = 1 self.register_probe({'snrs_weights': weights}) + loss = self.diffusion.loss(x0=x_start, t=t, model=self.model, model_kwargs={'cond': context}, - noise=noise) + noise=noise, + **kwargs) loss = loss * weights loss = loss.mean() ret = {'loss': loss, 'probe_data': {'prompt': prompt}} @@ -305,7 +315,18 @@ class LatentDiffusion(TrainModule): null_context = self.encode_condition(self.tokenizer(n_prompt).to( we.device_id), method=method) - + if 'hint' in kwargs and kwargs['hint'] is not None: + hint = kwargs.pop('hint') + if isinstance(context, dict): + context['hint'] = hint + else: + context = {'crossattn': context, 'hint': hint} + if isinstance(null_context, dict): + null_context['hint'] = hint + else: + null_context = {'crossattn': null_context, 'hint': hint} + else: + hint = None if 'index' in kwargs: kwargs.pop('index') image_size = None @@ -317,7 +338,9 @@ class LatentDiffusion(TrainModule): image_size = [h, w] if 'image_size' in kwargs: image_size = kwargs.pop('image_size') - if image_size is None or isinstance(image_size, numbers.Number): + if isinstance(image_size, numbers.Number): + image_size = [image_size, image_size] + if image_size is None: image_size = [1024, 1024] height, width = image_size noise = self.noise_sample(num_samples, height // self.size_factor, @@ -387,9 +410,11 @@ class LatentDiffusion(TrainModule): t_x_samples = [None for _ in prompt] outputs = list() - for p, np, tnp, img, t_img in zip(prompt, n_prompt, train_n_prompt, - x_samples, t_x_samples): + for i, (p, np, tnp, img, t_img) in enumerate( + zip(prompt, n_prompt, train_n_prompt, x_samples, t_x_samples)): one_tup = {'prompt': p, 'n_prompt': np, 'image': img} + if hint is not None: + one_tup.update({'hint': hint[i]}) if t_img is not None: one_tup['train_n_prompt'] = tnp one_tup['train_n_image'] = t_img @@ -408,6 +433,8 @@ class LatentDiffusion(TrainModule): 'prompt': res['prompt'], 'n_prompt': res['n_prompt'] } + if 'hint' in res: + one_tup.update({'hint': res['hint']}) if 'train_n_prompt' in res: one_tup['train_n_prompt'] = res['train_n_prompt'] one_tup['train_n_image'] = res['train_n_image'] diff --git a/scepter/modules/model/network/ldm/ldm_sce.py b/scepter/modules/model/network/ldm/ldm_sce.py new file mode 100644 index 0000000..e398953 --- /dev/null +++ b/scepter/modules/model/network/ldm/ldm_sce.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright (c) Alibaba, Inc. and its affiliates. +import copy + +import torch +import torch.nn as nn +import torchvision.transforms as TT + +from scepter.modules.annotator.registry import ANNOTATORS +from scepter.modules.model.registry import MODELS, TUNERS +from scepter.modules.utils.config import Config, dict_to_yaml + +from .ldm import LatentDiffusion +from .ldm_xl import LatentDiffusionXL + + +@MODELS.register_class() +class LatentDiffusionSCETuning(LatentDiffusion): + para_dict = {} + para_dict.update(LatentDiffusion.para_dict) + + def __init__(self, cfg, logger): + super().__init__(cfg, logger=logger) + + def init_params(self): + super().init_params() + self.tuner_model_config = self.cfg.TUNER_MODEL + + def construct_network(self): + super().construct_network() + input_block_channels = self.model._input_block_chans + sc_tuner_cfg = self.tuner_model_config['SC_TUNER_CFG'] + use_layers = self.tuner_model_config.get('USE_LAYERS', None) + lsc_tuner_blocks = nn.ModuleList([]) + for i, chan in enumerate(input_block_channels[::-1]): + if use_layers and i not in use_layers: + lsc_tuner_blocks.append(nn.Identity()) + continue + tuner_cfg = copy.deepcopy(sc_tuner_cfg) + tuner_cfg['DIM'] = chan + tuner_cfg['TUNER_LENGTH'] = int(chan * + tuner_cfg.get('DOWN_RATIO', 1.0)) + sc_tuner = TUNERS.build(tuner_cfg, logger=self.logger) + lsc_tuner_blocks.append(sc_tuner) + self.model.lsc_identity = lsc_tuner_blocks + + def save_pretrained(self, + *args, + destination=None, + prefix='', + keep_vars=False): + save_state = { + key: value + for key, value in self.state_dict().items() + if 'lsc_identity' in key + } + return save_state + + def save_pretrained_config(self): + return copy.deepcopy(self.cfg.TUNER_MODEL.cfg_dict) + + @staticmethod + def get_config_template(): + return dict_to_yaml('MODELS', + __class__.__name__, + LatentDiffusionSCETuning.para_dict, + set_name=True) + + +@MODELS.register_class() +class LatentDiffusionXLSCETuning(LatentDiffusionSCETuning, LatentDiffusionXL): + pass + + +@MODELS.register_class() +class LatentDiffusionSCEControl(LatentDiffusion): + para_dict = { + 'CONTROL_MODEL': {}, + } + para_dict.update(LatentDiffusion.para_dict) + + def __init__(self, cfg, logger): + super().__init__(cfg, logger=logger) + + def init_params(self): + super().init_params() + self.control_model_config = self.cfg.CONTROL_MODEL + self.control_anno_config = self.cfg.CONTROL_ANNO + + def construct_network(self): + super().construct_network() + # anno + self.control_processor = ANNOTATORS.build(self.control_anno_config) + if isinstance(self.control_model_config, (dict, Config)): + self.control_model_config = [self.control_model_config] + control_model = nn.ModuleList([]) + for k, sub_cfg in enumerate(self.control_model_config): + sub_cfg['INPUT_BLOCK_CHANS'] = self.model._input_block_chans + sub_cfg['INPUT_DOWN_FLAG'] = self.model._input_down_flag + csc_tuners = TUNERS.build(sub_cfg, logger=self.logger) + control_model.append(csc_tuners) + self.model.control_blocks = control_model + + @torch.no_grad() + def get_control_input(self, control, *args, **kwargs): + hints = [] + for ctr in control: + hint = self.control_processor(ctr) + hint = TT.ToTensor()(hint) + hints.append(hint) + hints = torch.stack(hints).to(control.device) + return hints + + def forward_train(self, **kwargs): + # if ('module' not in kwargs) or ('module' in kwargs and self.control_method not in kwargs['module']): + # kwargs['module'] = {self.control_method: self.control_model} + if 'hint' not in kwargs and 'image_preprocess' in kwargs: + image_preprocess = kwargs.pop('image_preprocess') + kwargs['hint'] = self.get_control_input(image_preprocess) + return super().forward_train(**kwargs) + + @torch.no_grad() + @torch.autocast('cuda', dtype=torch.float16) + def forward_test(self, **kwargs): + # if ('module' not in kwargs) or ('module' in kwargs and self.control_method not in kwargs['module']): + # kwargs['module'] = {self.control_method: self.control_model} + if 'hint' not in kwargs and 'image_preprocess' in kwargs: + image_preprocess = kwargs.pop('image_preprocess') + kwargs['hint'] = self.get_control_input(image_preprocess) + kwargs['image_size'] = kwargs['hint'].shape[-2:] + return super().forward_test(**kwargs) + + def save_pretrained(self, + *args, + destination=None, + prefix='', + keep_vars=False): + return self.model.control_blocks.state_dict(*args, + destination=destination, + keep_vars=keep_vars) + + def save_pretrained_config(self): + return copy.deepcopy(self.cfg.CONTROL_MODEL.cfg_dict) + + @staticmethod + def get_config_template(): + return dict_to_yaml('MODELS', + __class__.__name__, + LatentDiffusionSCEControl.para_dict, + set_name=True) + + +@MODELS.register_class() +class LatentDiffusionXLSCEControl(LatentDiffusionSCEControl, + LatentDiffusionXL): + pass diff --git a/scepter/modules/model/network/ldm/ldm_xl.py b/scepter/modules/model/network/ldm/ldm_xl.py index a02edf2..0730670 100644 --- a/scepter/modules/model/network/ldm/ldm_xl.py +++ b/scepter/modules/model/network/ldm/ldm_xl.py @@ -176,7 +176,14 @@ class LatentDiffusionXL(LatentDiffusion): continue batch[key] = kwargs[key].to(we.device_id) context = getattr(self.cond_stage_model, 'encode')(batch) - + if 'hint' in kwargs and kwargs['hint'] is not None: + hint = kwargs.pop('hint') + if isinstance(context, dict): + context['hint'] = hint + else: + context = {'crossattn': context, 'hint': hint} + else: + hint = None if self.min_snr_gamma is not None: alphas = self.diffusion.alphas.to(we.device_id)[t] sigmas = self.diffusion.sigmas.pow(2).to(we.device_id)[t] @@ -190,7 +197,8 @@ class LatentDiffusionXL(LatentDiffusion): t=t, model=self.model, model_kwargs={'cond': context}, - noise=noise) + noise=noise, + **kwargs) loss = loss * weights loss = loss.mean() ret = {'loss': loss, 'probe_data': {'prompt': prompt}} @@ -273,6 +281,19 @@ class LatentDiffusionXL(LatentDiffusion): context = getattr(self.cond_stage_model, 'encode')(batch) null_context = getattr(self.cond_stage_model, 'encode')(batch_uc) + if 'hint' in kwargs and kwargs['hint'] is not None: + hint = kwargs.pop('hint') + if isinstance(context, dict): + context['hint'] = hint + else: + context = {'crossattn': context, 'hint': hint} + if isinstance(null_context, dict): + null_context['hint'] = hint + else: + null_context = {'crossattn': null_context, 'hint': hint} + else: + hint = None + if 'index' in kwargs: kwargs.pop('index') height, width = batch['target_size_as_tuple'][0].cpu().numpy().tolist() @@ -482,15 +503,18 @@ class LatentDiffusionXL(LatentDiffusion): before_refiner_t_samples = [None for _ in prompt] outputs = list() - for p, np, tnp, img, r_img, t_img, r_t_img in zip( - prompt, n_prompt, train_n_prompt, x_samples, - before_refiner_samples, t_x_samples, before_refiner_t_samples): + for i, (p, np, tnp, img, r_img, t_img, r_t_img) in enumerate( + zip(prompt, n_prompt, train_n_prompt, x_samples, + before_refiner_samples, t_x_samples, + before_refiner_t_samples)): one_tup = { 'prompt': p, 'n_prompt': np, 'image': img, 'before_refiner_image': r_img } + if hint is not None: + one_tup.update({'hint': hint[i]}) if t_img is not None: one_tup['train_n_prompt'] = tnp one_tup['train_n_image'] = t_img diff --git a/scepter/modules/model/tuner/__init__.py b/scepter/modules/model/tuner/__init__.py index 3ecebea..097158f 100644 --- a/scepter/modules/model/tuner/__init__.py +++ b/scepter/modules/model/tuner/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- # Copyright (c) Alibaba, Inc. and its affiliates. +from scepter.modules.model.tuner import sce from scepter.modules.model.tuner.swift_tuner import (SwiftAdapter, SwiftFull, SwiftLoRA) diff --git a/scepter/modules/model/tuner/sce/__init__.py b/scepter/modules/model/tuner/sce/__init__.py new file mode 100644 index 0000000..8c549fe --- /dev/null +++ b/scepter/modules/model/tuner/sce/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Copyright (c) Alibaba, Inc. and its affiliates. +from scepter.modules.model.tuner.sce.scetuning import CSCTuners, SCTuner +from scepter.modules.model.tuner.sce.scetuning_component import SCEAdapter diff --git a/scepter/modules/model/tuner/sce/scetuning.py b/scepter/modules/model/tuner/sce/scetuning.py new file mode 100644 index 0000000..667aa6e --- /dev/null +++ b/scepter/modules/model/tuner/sce/scetuning.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- +# Copyright (c) Alibaba, Inc. and its affiliates. +from collections import OrderedDict + +import torch +import torch.nn as nn + +from scepter.modules.model.registry import TUNERS +from scepter.modules.model.tuner.base_tuner import BaseTuner +from scepter.modules.model.tuner.tuner_component import conv_nd, zero_module +from scepter.modules.utils.config import dict_to_yaml +from scepter.modules.utils.file_system import FS + + +@TUNERS.register_class() +class SCTuner(BaseTuner): + def __init__(self, cfg, logger=None): + super().__init__(cfg, logger=logger) + self.logger = logger + dim = cfg['DIM'] + tuner_length = cfg['TUNER_LENGTH'] + tuner_name = cfg.get('TUNER_NAME', 'SCEAdapter') + self.tuner_name = tuner_name + if tuner_name == 'SCEAdapter': + from .scetuning_component import SCEAdapter + self.tuner_op = SCEAdapter(dim=dim, adapter_length=tuner_length) + else: + raise Exception(f'Error tuner op {tuner_name}') + + def forward(self, x, x_shortcut=None, use_shortcut=True, **kwargs): + if self.tuner_name == 'SCEAdapter': + out = self.tuner_op(x, x_shortcut, use_shortcut) + else: + out = x + return out + + @staticmethod + def get_config_template(): + return dict_to_yaml('TUNERS', + __class__.__name__, + SCTuner.para_dict, + set_name=True) + + +@TUNERS.register_class() +class CSCTuners(BaseTuner): + def __init__(self, cfg, logger=None): + super().__init__(cfg, logger=logger) + self.logger = logger + input_block_channels = cfg['INPUT_BLOCK_CHANS'] + input_down_flag = cfg['INPUT_DOWN_FLAG'] + assert len(input_block_channels) == len(input_down_flag) + pre_hint_in_channels = cfg.get('PRE_HINT_IN_CHANNELS', 3) + pre_hint_out_channels = cfg.get('PRE_HINT_OUT_CHANNELS', 256) + pre_hint_dim_ratio = cfg.get('PRE_HINT_DIM_RATIO', 1.0) + dense_hint_kernal = cfg.get('DENSE_HINT_KERNAL', 3) + sc_tuner_cfg = cfg['SC_TUNER_CFG'] + use_layers = cfg.get('USE_LAYERS', None) + self.pretrained_model = cfg.get('PRETRAINED_MODEL', None) + self.scale = cfg.get('SCALE', 1.0) + self.method = 'csctuning' + + # pre_hint + dims = 2 + ch = pre_hint_out_channels + self.pre_hint_blocks = nn.Sequential( + conv_nd(dims, + pre_hint_in_channels, + int(16 * pre_hint_dim_ratio), + 3, + padding=1), + nn.SiLU(), + conv_nd(dims, + int(16 * pre_hint_dim_ratio), + int(16 * pre_hint_dim_ratio), + 3, + padding=1), + nn.SiLU(), + conv_nd(dims, + int(16 * pre_hint_dim_ratio), + int(32 * pre_hint_dim_ratio), + 3, + padding=1, + stride=2), + nn.SiLU(), + conv_nd(dims, + int(32 * pre_hint_dim_ratio), + int(32 * pre_hint_dim_ratio), + 3, + padding=1), + nn.SiLU(), + conv_nd(dims, + int(32 * pre_hint_dim_ratio), + int(96 * pre_hint_dim_ratio), + 3, + padding=1, + stride=2), + nn.SiLU(), + conv_nd(dims, + int(96 * pre_hint_dim_ratio), + int(96 * pre_hint_dim_ratio), + 3, + padding=1), + nn.SiLU(), + conv_nd(dims, + int(96 * pre_hint_dim_ratio), + ch, + 3, + padding=1, + stride=2), + ) + # dense_hint + self.dense_hint_blocks = nn.ModuleList([]) + stride_list = [2 if flag else 1 for flag in input_down_flag] + for i, chan in enumerate(input_block_channels): + if use_layers and i not in use_layers: + self.dense_hint_blocks.append(nn.Identity()) + continue + self.dense_hint_blocks.append( + nn.Sequential( + nn.SiLU(), + zero_module( + conv_nd(dims, + ch, + chan, + dense_hint_kernal, + padding=1, + stride=stride_list[i])) + if dense_hint_kernal == 3 else zero_module( + conv_nd(dims, + ch, + chan, + dense_hint_kernal, + padding=0, + stride=stride_list[i])))) + ch = chan + # tuner + self.lsc_tuner_blocks = nn.ModuleList([]) + for i, chan in enumerate(input_block_channels[::-1]): + if use_layers and i not in use_layers: + self.lsc_tuner_blocks.append(nn.Identity()) + continue + sc_tuner_cfg['DIM'] = chan + sc_tuner_cfg['TUNER_LENGTH'] = int(chan * + cfg.get('DOWN_RATIO', 1.0)) + sc_tuner = TUNERS.build(sc_tuner_cfg, logger=self.logger) + self.lsc_tuner_blocks.append(sc_tuner) + + def load_pretrained_model(self, pretrained_model): + if self.pretrained_model: + with FS.get_from(self.pretrained_model, + wait_finish=True) as local_path: + self.init_from_ckpt(local_path) + + def init_from_ckpt(self, path): + model_new = OrderedDict() + model = torch.load(path, map_location='cpu') + for k, v in model.items(): + if k.startswith('model.'): + k = k[len('model.'):] + if k.startswith('0.'): + k = k[len('0.'):] + model_new[k] = v + missing, unexpected = self.load_state_dict(model_new, strict=False) + print( + f'Restored from {path} with {len(missing)} missing and {len(unexpected)} unexpected keys' + ) + if len(missing) > 0: + print(f'Missing Keys:\n {missing}') + if len(unexpected) > 0: + print(f'\nUnexpected Keys:\n {unexpected}') + + @staticmethod + def get_config_template(): + return dict_to_yaml('TUNERS', + __class__.__name__, + CSCTuners.para_dict, + set_name=True) diff --git a/scepter/modules/model/tuner/sce/scetuning_component.py b/scepter/modules/model/tuner/sce/scetuning_component.py new file mode 100644 index 0000000..c5520e6 --- /dev/null +++ b/scepter/modules/model/tuner/sce/scetuning_component.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Copyright (c) Alibaba, Inc. and its affiliates. +import math + +import torch.nn as nn + +from scepter.modules.model.tuner.tuner_utils import (choose_weight_type, + get_weight_value) + + +class SCEAdapter(nn.Module): + def __init__(self, + dim, + adapter_length, + adapter_type=None, + adapter_weight=None, + act_layer=nn.GELU, + zero_init_last=True, + use_bias=True): + super(SCEAdapter, self).__init__() + self.dim = dim + self.adapter_length = adapter_length + self.adapter_type = adapter_type + self.adapter_weight = adapter_weight + self.zero_init_last = zero_init_last + self.use_bias = use_bias + self.ln1 = nn.Linear(dim, adapter_length, bias=use_bias) + self.activate = act_layer() + self.ln2 = nn.Linear(adapter_length, dim, bias=use_bias) + self.init_weights() + self.init_scaling() + + def _zero_init_weights(self, m): + if isinstance(m, nn.Linear): + nn.init.zeros_(m.weight) + if self.use_bias: + nn.init.zeros_(m.bias) + + def _kaiming_init_weights(self, m): + if isinstance(m, nn.Linear): + nn.init.kaiming_uniform_(m.weight, a=math.sqrt(5)) + + def init_weights(self): + self._kaiming_init_weights(self.ln1) + if self.zero_init_last: + self._zero_init_weights(self.ln2) + else: + self._kaiming_init_weights(self.ln2) + + def init_scaling(self): + if self.adapter_weight: + self.scaling = choose_weight_type(self.adapter_weight, self.dim) + else: + self.scaling = None + + def forward(self, x, x_shortcut=None, use_shortcut=True, **kwargs): + if x_shortcut is None: + x_shortcut = x + x_shape = x.shape + if len(x_shape) == 4: + b, d, h, w = x_shape + x = x.permute(0, 2, 3, 1).reshape(b, h * w, d) + out = self.ln2(self.activate(self.ln1(x))) + if self.adapter_weight: + scaling = get_weight_value(self.adapter_weight, self.scaling, out) + out = out * scaling if scaling is not None else out + if len(x_shape) == 4: + b, d, h, w = x_shape + out = out.reshape(b, h, w, -1).permute(0, 3, 1, 2).contiguous() + if use_shortcut: + out = x_shortcut + out + return out diff --git a/scepter/modules/model/tuner/swift_tuner.py b/scepter/modules/model/tuner/swift_tuner.py index df877ff..f4890e6 100644 --- a/scepter/modules/model/tuner/swift_tuner.py +++ b/scepter/modules/model/tuner/swift_tuner.py @@ -104,6 +104,7 @@ class SwiftAdapter(BaseTuner): SwiftAdapter.para_dict, set_name=True) + @TUNERS.register_class() class SwiftSCETuning(BaseTuner): para_dict = { diff --git a/scepter/modules/model/tuner/tuner_component.py b/scepter/modules/model/tuner/tuner_component.py index bd2183f..25c6c9e 100644 --- a/scepter/modules/model/tuner/tuner_component.py +++ b/scepter/modules/model/tuner/tuner_component.py @@ -6,6 +6,28 @@ import torch import torch.nn as nn +def conv_nd(dims, *args, **kwargs): + """ + Create a 1D, 2D, or 3D convolution module. + """ + if dims == 1: + return nn.Conv1d(*args, **kwargs) + elif dims == 2: + return nn.Conv2d(*args, **kwargs) + elif dims == 3: + return nn.Conv3d(*args, **kwargs) + raise ValueError(f'unsupported dimensions: {dims}') + + +def zero_module(module): + """ + Zero out the parameters of a module and return it. + """ + for p in module.parameters(): + p.detach().zero_() + return module + + class Prompt(nn.Module): """The implementation of vision prompt tuning method. diff --git a/scepter/modules/solver/base_solver.py b/scepter/modules/solver/base_solver.py index e62d59c..c7b49ae 100644 --- a/scepter/modules/solver/base_solver.py +++ b/scepter/modules/solver/base_solver.py @@ -110,7 +110,7 @@ try: self.solver.after_epoch(self.solver.hooks_dict['test']) def setup(self, stage: str) -> None: - self.solver.logger = get_logger(name='std_torch') + self.solver.logger = get_logger(name='scepter') self.solver._prefix = FS.init_fs_client(self.solver.file_system, logger=self.solver.logger) self.solver._local_rank = self.global_rank diff --git a/scepter/modules/solver/diffusion_solver.py b/scepter/modules/solver/diffusion_solver.py index f2705ae..3b5b3e9 100644 --- a/scepter/modules/solver/diffusion_solver.py +++ b/scepter/modules/solver/diffusion_solver.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) Alibaba, Inc. and its affiliates. +import copy import os from collections import OrderedDict, defaultdict @@ -97,6 +98,8 @@ class LatentDiffusionSolver(BaseSolver): def __init__(self, cfg, logger=None): super().__init__(cfg, logger=logger) self.max_steps = cfg.MAX_STEPS + if self.max_steps > 0: + self.max_epochs = -1 self.use_amp = cfg.get('USE_AMP', False) self.dtype = getattr(torch, cfg.DTYPE) self.use_fairscale = cfg.get('USE_FAIRSCALE', False) @@ -297,6 +300,25 @@ class LatentDiffusionSolver(BaseSolver): ckpt['scaler'] = self.scaler.state_dict() return ckpt + def save_pretrained(self): + if hasattr(self.model, 'save_pretrained'): + ckpt = self.model.save_pretrained() + elif hasattr(self.model, 'module') and hasattr(self.model.module, + 'save_pretrained'): + ckpt = self.model.module.save_pretrained() + else: + ckpt = dict() + if hasattr(self.model, 'save_pretrained_config'): + cfg = self.model.save_pretrained_config() + elif hasattr(self.model, 'module') and hasattr( + self.model.module, 'save_pretrained_config'): + cfg = self.model.module.save_pretrained_config() + else: + cfg = copy.deepcopy(self.cfg.MODEL.cfg_dict) + if 'FILE_SYSTEM' in cfg: + cfg.pop('FILE_SYSTEM') + return ckpt, cfg + def solve(self): self.before_solve() if 'train' in self._mode_set: @@ -366,8 +388,17 @@ class LatentDiffusionSolver(BaseSolver): log_data, log_label, ori_label = [], [], [] for result in all_results: # the inference image use - log_data.append((result['image'].permute(1, 2, 0).cpu().numpy() * - 255).astype(np.uint8)) + if 'hint' in result: + merge_image = torch.cat([ + result['hint'][:result['image'].shape[0]], result['image'] + ], + dim=2) + log_data.append((merge_image.permute(1, 2, 0).cpu().numpy() * + 255).astype(np.uint8)) + else: + log_data.append( + (result['image'].permute(1, 2, 0).cpu().numpy() * + 255).astype(np.uint8)) log_label.append(result['prompt'] + ' NegPrompt: ' + result['n_prompt']) ori_label.append(result['prompt']) @@ -385,9 +416,18 @@ class LatentDiffusionSolver(BaseSolver): for result in all_results: # the inference image use if 'train_n_image' in result: - log_data.append( - (result['train_n_image'].permute(1, 2, 0).cpu().numpy() * - 255).astype(np.uint8)) + if 'hint' in result: + merge_image = torch.cat([ + result['hint'][:result['train_n_image'].shape[0]], + result['train_n_image'] + ], + dim=2) + log_data.append( + (merge_image.permute(1, 2, 0).cpu().numpy() * + 255).astype(np.uint8)) + else: + log_data.append((result['train_n_image'].permute( + 1, 2, 0).cpu().numpy() * 255).astype(np.uint8)) log_label.append(result['prompt'] + 'NegPrompt' + result['train_n_prompt']) ori_label.append(result['prompt']) @@ -578,8 +618,16 @@ class LatentDiffusionSolver(BaseSolver): transfer_data_to_cuda(self.current_batch_data[self.mode])) log_data, log_label = [], [] for result in outputs: - merge_image = torch.cat([result['orig'], result['recon']], - dim=2) + if 'hint' in result: + merge_image = torch.cat([ + result['orig'], + result['hint'][:result['orig'].shape[0]], + result['recon'] + ], + dim=2) + else: + merge_image = torch.cat([result['orig'], result['recon']], + dim=2) log_data.append((merge_image.permute(1, 2, 0).cpu().numpy() * 255).astype(np.uint8)) log_label.append('recon image: ' + result['prompt'] + @@ -599,8 +647,16 @@ class LatentDiffusionSolver(BaseSolver): log_data, log_label = [], [] for result in outputs: if 'train_n_image' in result: - merge_image = torch.cat( - [result['orig'], result['train_n_image']], dim=2) + if 'hint' in result: + merge_image = torch.cat([ + result['orig'], + result['hint'][:result['orig'].shape[0]], + result['train_n_image'] + ], + dim=2) + else: + merge_image = torch.cat( + [result['orig'], result['train_n_image']], dim=2) log_data.append( (merge_image.permute(1, 2, 0).cpu().numpy() * 255).astype(np.uint8)) diff --git a/scepter/modules/solver/hooks/checkpoint.py b/scepter/modules/solver/hooks/checkpoint.py index ec38d81..45b91cc 100644 --- a/scepter/modules/solver/hooks/checkpoint.py +++ b/scepter/modules/solver/hooks/checkpoint.py @@ -1,11 +1,15 @@ # -*- coding: utf-8 -*- # Copyright (c) Alibaba, Inc. and its affiliates. +import json +import os import os.path as osp +import shutil import sys import warnings import torch import torch.distributed as du +from swift import push_to_hub from scepter.modules.solver.hooks.hook import Hook from scepter.modules.solver.hooks.registry import HOOKS @@ -56,6 +60,9 @@ class CheckpointHook(Hook): self.save_last = cfg.get('SAVE_LAST', False) self.save_best = cfg.get('SAVE_BEST', False) self.save_best_by = cfg.get('SAVE_BEST_BY', '') + self.push_to_hub = cfg.get('PUSH_TO_HUB', False) + self.hub_model_id = cfg.get('HUB_MODEL_ID', None) + self.last_ckpt = None if self.save_best and not self.save_best_by: warnings.warn( "CheckpointHook: Parameter 'save_best_by' is not set, turn off save_best function." @@ -96,7 +103,6 @@ class CheckpointHook(Hook): if solver.total_iter != 0 and ( (solver.total_iter + 1) % self.interval == 0 or solver.total_iter == solver.max_steps - 1): - checkpoint = solver.save_checkpoint() solver.logger.info( f'Saving checkpoint after {solver.total_iter + 1} steps') if we.rank == 0: @@ -106,11 +112,44 @@ class CheckpointHook(Hook): solver.total_iter + 1)) with FS.put_to(save_path) as local_path: with open(local_path, 'wb') as f: + checkpoint = solver.save_checkpoint() torch.save(checkpoint, f) + + from swift import SwiftModel + if isinstance(solver.model, SwiftModel): + save_path = osp.join( + solver.work_dir, + 'checkpoints/{}-{}'.format(self.save_name_prefix, + solver.total_iter + 1)) + local_folder, _ = FS.map_to_local(save_path) + solver.model.save_pretrained(local_folder) + FS.put_dir_from_local_dir(local_folder, save_path) + else: + if hasattr(solver, 'save_pretrained'): + save_path = osp.join( + solver.work_dir, 'checkpoints/{}-{}-bin'.format( + self.save_name_prefix, solver.total_iter + 1)) + local_folder, _ = FS.map_to_local(save_path) + FS.make_dir(local_folder) + ckpt, cfg = solver.save_pretrained() + with FS.put_to( + os.path.join( + local_folder, + 'pytorch_model.bin')) as local_path: + with open(local_path, 'wb') as f: + torch.save(ckpt, f) + with FS.put_to( + os.path.join( + local_folder, + 'configuration.json')) as local_path: + json.dump(cfg, open(local_path, 'w')) + FS.put_dir_from_local_dir(local_folder, save_path) + if self.save_last and solver.total_iter == solver.max_steps - 1: with FS.get_fs_client(save_path) as client: last_path = osp.join(solver.work_dir, 'checkpoint.pth') client.make_link(last_path, save_path) + self.last_ckpt = save_path torch.cuda.synchronize() if we.is_distributed: @@ -173,6 +212,48 @@ class CheckpointHook(Hook): torch.save(checkpoint['pre_state_dict'], f) client.put_object_from_local_file(local_file, save_path) + def create_or_update_model_card(self, model, output_dir: str): + """ + Updates or create the model card. + """ + if not os.path.exists(os.path.join(output_dir, 'README.md')): + lines = [] + else: + with open(os.path.join(output_dir, 'README.md'), 'r') as f: + lines = f.readlines() + + # write the lines back to README.md + with open(os.path.join(output_dir, 'README.md'), 'w') as f: + f.writelines(lines) + + def after_all_iter(self, solver): + if we.rank == 0: + if self.push_to_hub and self.last_ckpt: + if os.path.isfile(self.last_ckpt): + base_dir = os.path.dirname(self.last_ckpt) + base_file = os.path.basename(self.last_ckpt) + save_path = os.path.join(base_dir, 'after_all_iter') + os.makedirs(save_path) + self.create_or_update_model_card(solver.model, save_path) + try: + os.link(self.last_ckpt, + os.path.join(save_path, base_file)) + except OSError: + shutil.copyfile(self.last_ckpt, + os.path.join(save_path, base_file)) + + push_to_hub(repo_name=self.hub_model_id, + output_dir=self.last_ckpt, + private=False) + current_dir = os.path.dirname(__file__) + base_path = os.sep.join(current_dir.split(os.sep)[:-4]) + base_path = os.path.join(base_path, 'config') + file_name = self.hub_model_id.replace(os.sep, '_') + content = {'name': self.hub_model_id} + import json + with open(os.path.join(base_path, file_name), 'w') as f: + json.dump(content, f) + @staticmethod def get_config_template(): return dict_to_yaml('hook', diff --git a/scepter/modules/transform/__init__.py b/scepter/modules/transform/__init__.py index b57b57e..9b2e1b4 100644 --- a/scepter/modules/transform/__init__.py +++ b/scepter/modules/transform/__init__.py @@ -16,7 +16,7 @@ from scepter.modules.transform.io import (LoadCvImageFromFile, from scepter.modules.transform.io_video import (DecodeVideoToTensor, LoadVideoFromFile) from scepter.modules.transform.registry import TRANSFORMS, build_pipeline -from scepter.modules.transform.tensor import Rename, Select, ToTensor +from scepter.modules.transform.tensor import Rename, Select, ToNumpy, ToTensor from scepter.modules.transform.transform_xl import FlexibleCropXL from scepter.modules.transform.video import (AutoResizedCropVideo, CenterCropVideo, NormalizeVideo, diff --git a/scepter/modules/transform/tensor.py b/scepter/modules/transform/tensor.py index 4612b2f..f2df463 100644 --- a/scepter/modules/transform/tensor.py +++ b/scepter/modules/transform/tensor.py @@ -3,6 +3,7 @@ import numpy as np import torch +from PIL import Image from scepter.modules.transform.registry import TRANSFORMS from scepter.modules.utils.config import dict_to_yaml @@ -24,6 +25,17 @@ def to_tensor(data): raise TypeError(f'Unsupported type {type(data)}') +def to_numpy(data): + if isinstance(data, torch.Tensor): + return data.detach().cpu().numpy() + elif isinstance(data, (int, float, list, tuple, dict, Image.Image)): + return np.array(data) + elif isinstance(data, np.ndarray): + return data + else: + raise TypeError(f'Unsupported type {type(data)}') + + @TRANSFORMS.register_class() class ToTensor(object): def __init__(self, cfg, logger=None): @@ -54,6 +66,50 @@ class ToTensor(object): set_name=True) +@TRANSFORMS.register_class() +class ToNumpy(object): + def __init__(self, cfg, logger=None): + self.input_key = cfg.get('INPUT_KEY', 'img') + self.output_key = cfg.get('OUTPUT_KEY', 'img') + + def __call__(self, item): + if isinstance(self.input_key, str): + self.input_key = [self.input_key] + if isinstance(self.output_key, str): + self.output_key = [self.output_key] + for idx, key in enumerate(self.input_key): + item[self.output_key[idx]] = to_numpy(item[key]) + return item + + @staticmethod + def get_config_template(): + ''' + { "ENV" : + { "description" : "", + "A" : { + "value": 1.0, + "description": "" + } + } + } + :return: + ''' + para_dict = [{ + 'INPUT_KEY': { + 'value': [], + 'description': 'input_key' + }, + 'OUTPUT_KEY': { + 'value': [], + 'description': 'output_key' + } + }] + return dict_to_yaml('TRANSFORM', + __class__.__name__, + para_dict, + set_name=True) + + @TRANSFORMS.register_class() class Select(object): def __init__(self, cfg, logger=None): @@ -107,14 +163,14 @@ class Select(object): @TRANSFORMS.register_class() class Rename(object): def __init__(self, cfg, logger=None): - self.in_keys = cfg.IN_KEYS - self.out_keys = cfg.OUT_KEYS + self.input_key = cfg.INPUT_KEY + self.output_key = cfg.OUTPUT_KEY def __call__(self, item): data = {} - for idx, key in enumerate(self.in_keys): - data[self.out_keys[idx]] = item[key] - have_key_set = set(self.in_keys) + for idx, key in enumerate(self.input_key): + data[self.output_key[idx]] = item[key] + have_key_set = set(self.input_key) for k, v in item.items(): if k not in have_key_set: data[k] = v @@ -134,12 +190,12 @@ class Rename(object): :return: ''' para_dict = [{ - 'IN_KEYS': { + 'INPUT_KEY': { 'value': [], 'description': 'The keys need to rename, the other keys are outputed by default.' }, - 'OUT_KEYS': { + 'OUTPUT_KEY': { 'value': [], 'description': 'The keys need to rename, the other keys are outputed by default.' diff --git a/scepter/modules/utils/config.py b/scepter/modules/utils/config.py index 947c232..d7bceb1 100644 --- a/scepter/modules/utils/config.py +++ b/scepter/modules/utils/config.py @@ -3,6 +3,7 @@ import argparse import copy import json +import numbers import os import sys @@ -579,7 +580,7 @@ class Config(object): for key, val in cfg_dict.items(): if isinstance(val, (Config, dict, list)): cfg_new[key] = Config.get_plain_cfg(val) - else: + elif isinstance(val, (str, numbers.Number)): cfg_new[key] = val return cfg_new elif isinstance(cfg, dict): @@ -588,7 +589,7 @@ class Config(object): for key, val in cfg_dict.items(): if isinstance(val, (Config, dict, list)): cfg_new[key] = Config.get_plain_cfg(val) - else: + elif isinstance(val, (str, numbers.Number)): cfg_new[key] = val return cfg_new elif isinstance(cfg, list): @@ -597,7 +598,7 @@ class Config(object): for val in cfg_list: if isinstance(val, (Config, dict, list)): cfg_new.append(Config.get_plain_cfg(val)) - else: + elif isinstance(val, (str, numbers.Number)): cfg_new.append(val) return cfg_new else: diff --git a/scepter/modules/utils/distribute.py b/scepter/modules/utils/distribute.py index abdefb4..439eda5 100644 --- a/scepter/modules/utils/distribute.py +++ b/scepter/modules/utils/distribute.py @@ -327,7 +327,7 @@ class Workenv(object): self.seed = 2023 self.debug = False self.use_pl = False - self.launcher = 'spawn' + self.launcher = 'spawn' if torch.cuda.device_count() > 1 else None self.data_online = False self.share_storage = False @@ -358,7 +358,7 @@ class Workenv(object): fn(config) return - if (os.environ.get('WORLD_SIZE') is None or os.environ.get('WORLD_SIZE') == 1) \ + if (os.environ.get('WORLD_SIZE') is None or int(os.environ.get('WORLD_SIZE')) == 1) \ and torch.cuda.device_count() == 1 and not self.launcher == 'dist': self.device_id = 0 fn(config) diff --git a/scepter/modules/utils/file_clients/local_fs.py b/scepter/modules/utils/file_clients/local_fs.py index b568503..7cd3d05 100644 --- a/scepter/modules/utils/file_clients/local_fs.py +++ b/scepter/modules/utils/file_clients/local_fs.py @@ -239,7 +239,7 @@ class LocalFs(BaseFs): return True def walk_dir(self, file_dir, recurse=True): - for root, dirs, files in os.walk(file_dir, topdown=True): + for root, dirs, files in os.walk(file_dir, topdown=recurse): sub_files = files + dirs for name in sub_files: yield os.path.join(root, name) diff --git a/scepter/studio/__init__.py b/scepter/studio/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/studio/home/__init__.py b/scepter/studio/home/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/studio/home/home.py b/scepter/studio/home/home.py new file mode 100644 index 0000000..c272c05 --- /dev/null +++ b/scepter/studio/home/home.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +import gradio as gr + +from scepter.modules.utils.config import Config +from scepter.studio.home.home_ui.desc_ui import DescUI +from scepter.studio.home.home_ui.guide_ui import GuideUI + + +class HomeUI(): + def __init__(self, + cfg_general_file, + is_debug=False, + language='en', + root_work_dir='./'): + cfg_general = Config(cfg_file=cfg_general_file) + desc_info = cfg_general.DESC_INFO + self.desc_ui = DescUI(desc_info=desc_info, + is_debug=is_debug, + language=language) + guide_info = cfg_general.GUIDE_INFO + self.guide_ui = GuideUI(guide_info=guide_info, + is_debug=is_debug, + language=language) + + def create_ui(self): + self.desc_ui.create_ui() + self.guide_ui.create_ui() + + def set_callbacks(self, manager): + self.desc_ui.set_callbacks(self.desc_ui, manager) + self.guide_ui.set_callbacks(self.guide_ui, manager) + + +if __name__ == '__main__': + st_ins = HomeUI(None, + is_debug=True, + language='zh', + root_work_dir='./cache') + with gr.Blocks() as demo: + gr.Markdown('

SCEPTER Home

') + with gr.Tabs(elem_id='tabs') as tabs: + with gr.TabItem('editor', id=1, elem_id=f'tab_{1}'): + st_ins.create_ui() + st_ins.set_callbacks() + demo.queue(status_update_rate=1).launch(show_error=True, + debug=True, + enable_queue=True) diff --git a/scepter/studio/home/home_ui/__init__.py b/scepter/studio/home/home_ui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/studio/home/home_ui/component_names.py b/scepter/studio/home/home_ui/component_names.py new file mode 100644 index 0000000..1d01b7a --- /dev/null +++ b/scepter/studio/home/home_ui/component_names.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- + + +class DescUIName(): + def __init__(self, language='en'): + if language == 'en': + pass + + elif language == 'zh': + pass + + +class GuideUIName(): + def __init__(self, language='en'): + if language == 'en': + pass + + elif language == 'zh': + pass diff --git a/scepter/studio/home/home_ui/desc_ui.py b/scepter/studio/home/home_ui/desc_ui.py new file mode 100644 index 0000000..22b15b4 --- /dev/null +++ b/scepter/studio/home/home_ui/desc_ui.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +import gradio as gr + +from scepter.studio.home.home_ui.component_names import DescUIName +from scepter.studio.utils.uibase import UIBase + + +class DescUI(UIBase): + def __init__(self, desc_info, is_debug=False, language='en'): + self.desc_info = desc_info + self.language = language + self.is_debug = is_debug + self.component_names = DescUIName(language) + + def create_ui(self, *args, **kwargs): + if self.language == 'en': + gr.HTML(self.desc_info.EN_INFO) + elif self.language == 'zh': + gr.HTML(self.desc_info.ZH_INFO) + + def set_callbacks(self, desc_ui, manager=None): + pass diff --git a/scepter/studio/home/home_ui/guide_ui.py b/scepter/studio/home/home_ui/guide_ui.py new file mode 100644 index 0000000..981fcfa --- /dev/null +++ b/scepter/studio/home/home_ui/guide_ui.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +import gradio as gr + +from scepter.studio.home.home_ui.component_names import GuideUIName +from scepter.studio.utils.uibase import UIBase + + +class GuideUI(UIBase): + def __init__(self, guide_info, is_debug=False, language='en'): + self.guide_info = guide_info + self.language = language + self.is_debug = is_debug + self.component_names = GuideUIName(language) + + def create_ui(self, *args, **kwargs): + if self.language == 'en': + gr.HTML(self.guide_info.EN_INFO) + elif self.language == 'zh': + gr.HTML(self.guide_info.ZH_INFO) + + def set_callbacks(self, guide_ui, manager=None): + pass diff --git a/scepter/studio/inference/__init__.py b/scepter/studio/inference/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/studio/inference/inference.py b/scepter/studio/inference/inference.py new file mode 100644 index 0000000..323ee4c --- /dev/null +++ b/scepter/studio/inference/inference.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +import os +from glob import glob + +import gradio as gr + +import scepter +from scepter.modules.utils.config import Config +from scepter.modules.utils.file_system import FS +from scepter.studio.inference.inference_manager.infer_runer import \ + PipelineManager +from scepter.studio.inference.inference_ui.component_names import \ + InferenceUIName +from scepter.studio.inference.inference_ui.control_ui import ControlUI +from scepter.studio.inference.inference_ui.diffusion_ui import DiffusionUI +from scepter.studio.inference.inference_ui.gallery_ui import GalleryUI +from scepter.studio.inference.inference_ui.mantra_ui import MantraUI +from scepter.studio.inference.inference_ui.model_manage_ui import ModelManageUI +from scepter.studio.inference.inference_ui.refiner_ui import RefinerUI +from scepter.studio.inference.inference_ui.tuner_ui import TunerUI +from scepter.studio.utils.env import init_env + + +class InferenceUI(): + def __init__(self, + cfg_general_file, + is_debug=False, + language='en', + root_work_dir='./'): + config_dir = os.path.dirname(cfg_general_file) + cfg_general = Config(cfg_file=cfg_general_file) + cfg_general.WORK_DIR = os.path.join(root_work_dir, + cfg_general.WORK_DIR) + if not FS.exists(cfg_general.WORK_DIR): + FS.make_dir(cfg_general.WORK_DIR) + cfg_general = init_env(cfg_general) + # official mantra + mantra_book = Config( + cfg_file=os.path.join(os.path.dirname(scepter.dirname), + cfg_general.EXTENSION_PARAS.MANTRA_BOOK)) + cfg_general.MANTRAS = mantra_book.MANTRAS + # official tuners + official_tuners = Config( + cfg_file=os.path.join(os.path.dirname(scepter.dirname), + cfg_general.EXTENSION_PARAS.OFFICIAL_TUNERS)) + cfg_general.TUNERS = official_tuners.TUNERS + official_controllers = Config(cfg_file=os.path.join( + os.path.dirname(scepter.dirname), + cfg_general.EXTENSION_PARAS.OFFICIAL_CONTROLLERS)) + cfg_general.CONTROLLERS = official_controllers.CONTROLLERS + + pipe_manager = PipelineManager() + config_list = glob(os.path.join(config_dir, '*/*_pro.yaml'), + recursive=True) + for config_file in config_list: + pipe_manager.register_pipeline(Config(cfg_file=config_file)) + + for one_tuner in cfg_general.TUNERS: + pipe_manager.register_tuner( + one_tuner, + name=one_tuner.NAME_ZH if language == 'zh' else one_tuner.NAME) + + for one_controller in cfg_general.CONTROLLERS: + pipe_manager.register_controllers(one_controller) + + self.model_manage_ui = ModelManageUI(cfg_general, + pipe_manager, + is_debug=is_debug, + language=language) + self.gallery_ui = GalleryUI(cfg_general, + pipe_manager, + is_debug=is_debug, + language=language) + self.diffusion_ui = DiffusionUI(cfg_general, + pipe_manager, + is_debug=is_debug, + language=language) + self.mantra_ui = MantraUI(cfg_general, + pipe_manager, + is_debug=is_debug, + language=language) + self.tuner_ui = TunerUI(cfg_general, + pipe_manager, + is_debug=is_debug, + language=language) + self.refiner_ui = RefinerUI(cfg_general, + pipe_manager, + is_debug=is_debug, + language=language) + self.control_ui = ControlUI(cfg_general, + pipe_manager, + is_debug=is_debug, + language=language) + self.component_names = InferenceUIName(language=language) + + def create_ui(self): + self.model_manage_ui.create_ui() + self.gallery_ui.create_ui() + with gr.Row(variant='panel', equal_height=True): + self.check_box_for_setting = gr.CheckboxGroup( + choices=self.component_names.check_box_for_setting, + show_label=False) + with gr.Row(variant='panel', equal_height=True): + with gr.Accordion(label=self.component_names.advance_block_name, + open=True): + with gr.Tabs() as self.setting_tab: + with gr.TabItem(label=self.component_names.diffusion_paras, + id='diffusion_ui'): + self.diffusion_ui.create_ui() + # 0 + with gr.TabItem(label=self.component_names.mantra_paras, + id='mantra_ui', + visible=True) as self.mantra_tab: + self.mantra_ui.create_ui() + self.mantra_state = gr.State(value=False) + # 1 + with gr.TabItem(label=self.component_names.tuner_paras, + id='tuner_ui', + visible=True) as self.tuner_tab: + self.tuner_ui.create_ui() + self.tuner_state = gr.State(value=False) + # 2 + with gr.TabItem(label=self.component_names.contrl_paras, + id='control_ui', + visible=True) as self.control_tab: + self.control_ui.create_ui() + self.control_state = gr.State(value=False) + # 3 + with gr.TabItem(label=self.component_names.refine_paras, + id='refiner_ui', + visible=True) as self.refine_tab: + self.refiner_ui.create_ui() + + def set_callbacks(self, manager): + self.model_manage_ui.set_callbacks(self.diffusion_ui, self.tuner_ui, + self.control_ui, self.mantra_ui) + self.gallery_ui.set_callbacks(self, self.model_manage_ui, + self.diffusion_ui, self.mantra_ui, + self.tuner_ui, self.refiner_ui, + self.control_ui) + self.diffusion_ui.set_callbacks(self.model_manage_ui) + self.mantra_ui.set_callbacks(self.model_manage_ui) + self.tuner_ui.set_callbacks(self.model_manage_ui) + self.control_ui.set_callbacks(self.model_manage_ui, self.diffusion_ui) + self.refiner_ui.set_callbacks() + + def change_setting_tab(check_box): + mantra_ui, tuner_ui, control_ui = False, False, False + for key in check_box: + if self.component_names.check_box_for_setting.index(key) == 0: + mantra_ui = True + if self.component_names.check_box_for_setting.index(key) == 1: + tuner_ui = True + if self.component_names.check_box_for_setting.index(key) == 2: + control_ui = True + return (mantra_ui, tuner_ui, control_ui) + + self.check_box_for_setting.change( + change_setting_tab, + inputs=[self.check_box_for_setting], + outputs=[self.mantra_state, self.tuner_state, self.control_state]) + + +if __name__ == '__main__': + infer_ins = InferenceUI('scepter/methods/studio/inference/inference.yaml', + is_debug=True, + language='en', + root_work_dir='./cache') + with gr.Blocks() as demo: + gr.Markdown('

scepter studio

') + with gr.Tabs(elem_id='tabs') as tabs: + with gr.TabItem('editor', id=1, elem_id=f'tab_{1}'): + infer_ins.creat_ui() + infer_ins.set_callbacks() + demo.queue(status_update_rate=1).launch(show_error=True, + debug=True, + enable_queue=True) diff --git a/scepter/studio/inference/inference_manager/__init__.py b/scepter/studio/inference/inference_manager/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/studio/inference/inference_manager/infer_runer.py b/scepter/studio/inference/inference_manager/infer_runer.py new file mode 100644 index 0000000..1007525 --- /dev/null +++ b/scepter/studio/inference/inference_manager/infer_runer.py @@ -0,0 +1,188 @@ +# -*- coding: utf-8 -*- +from scepter.modules.inference.diffusion_inference import DiffusionInference +from scepter.modules.utils.logger import get_logger + + +class PipelineManager(): + def __init__(self, logger=None): + ''' + Args: + logger: + ''' + """ + Only (refine) cond model and (refine) diffusion model are binded strictly. + Users can choose any vae or refiner according to the given diffusion model. + """ + if logger is None: + logger = get_logger(name='scepter') + + self.module_list = [ + 'diffusion_model', 'first_stage_model', 'cond_stage_model', + 'refiner_cond_model', 'refiner_diffusion_model' + ] + self.pipeline_level_modules = {} + self.module_level_choices = {} + self.model_level_info = {} + self.logger = logger + + def contruct_models_index(self, pipeline_name, pipeline): + """ + + Args: + pipeline_name: + pipeline: + + Returns: + + """ + """ + self.pipeline_level_modules is used to index the modules given pipeline + { + "SD_XL1.0": { + "diffusion_model": "", + .... + } + } + self.module_level_choices is used to provide all choices for modules. + an example for self.module_level_models + { + "diffusion_model" : { + "choices": [], + "default": "" + } + .... + } + + self.model_level_info is used to index the best combination for different modules give model name + and check the combination is legal or not. + { + "xxxxxx": { + "pipeline": [], + "check_bind_module": [], + "model_info": {} + .... + } + } + + """ + self.pipeline_level_modules[pipeline_name] = pipeline + for module_name in self.module_list: + if module_name not in self.module_level_choices: + self.module_level_choices[module_name] = { + 'choices': [], + 'default': '' + } + module = getattr(pipeline, module_name) + if module is None: + continue + model_name = f"{pipeline_name}_{module['name']}" + self.module_level_choices[module_name]['choices'].append( + model_name) + if pipeline.is_default or self.module_level_choices[module_name][ + 'default'] == '': + self.module_level_choices[module_name]['default'] = model_name + if model_name not in self.model_level_info: + self.model_level_info[model_name] = { + 'pipeline': [], + 'check_bind_module': [], + 'model_info': {} + } + self.model_level_info[model_name]['pipeline'].append(pipeline_name) + self.model_level_info[model_name]['model_info'] = module + + def construct_new_pipeline(self): + pass + + def register_pipeline(self, cfg): + new_inference = DiffusionInference(logger=self.logger) + new_inference.init_from_cfg(cfg) + self.contruct_models_index(cfg.NAME, new_inference) + + def register_tuner(self, cfg, name=None, is_customized=False): + ''' + Args: + cfg: { + NAME: "" + NAME_ZH: "" + BASE_MODEL: "" + MODEL_PATH: "", + DESCRIPTION: "" + } + + Returns: + + ''' + if not is_customized: + tuners_key = 'tuners' + else: + tuners_key = 'customized_tuners' + + if tuners_key not in self.module_level_choices: + self.module_level_choices[tuners_key] = {} + + if cfg.BASE_MODEL not in self.module_level_choices[tuners_key]: + self.module_level_choices[tuners_key][cfg.BASE_MODEL] = { + 'choices': [], + 'default': '' + } + if name not in self.module_level_choices[tuners_key][ + cfg.BASE_MODEL]['choices']: + self.module_level_choices[tuners_key][ + cfg.BASE_MODEL]['choices'].append(name) + self.module_level_choices[tuners_key][cfg.BASE_MODEL]['default'] = name + if tuners_key not in self.model_level_info: + self.model_level_info[tuners_key] = {} + if cfg.BASE_MODEL not in self.model_level_info[tuners_key]: + self.model_level_info[tuners_key][cfg.BASE_MODEL] = {} + self.model_level_info[tuners_key][cfg.BASE_MODEL][name] = { + 'pipeline': [], + 'check_bind_module': [], + 'model_info': cfg + } + + def register_controllers(self, cfg): + ''' + Args: + cfg: { + NAME: "" + NAME_ZH: "" + BASE_MODEL: "" + MODEL_PATH: "", + DESCRIPTION: "" + } + + Returns: + + ''' + if 'controllers' not in self.module_level_choices: + self.module_level_choices['controllers'] = {} + + if cfg.BASE_MODEL not in self.module_level_choices['controllers']: + self.module_level_choices['controllers'][cfg.BASE_MODEL] = {} + if cfg.TYPE not in self.module_level_choices['controllers'][ + cfg.BASE_MODEL]: + self.module_level_choices['controllers'][cfg.BASE_MODEL][ + cfg.TYPE] = { + 'choices': [], + 'default': '' + } + controller_name = cfg.BASE_MODEL + '_' + cfg.NAME + self.module_level_choices['controllers'][cfg.BASE_MODEL][ + cfg.TYPE]['choices'].append(controller_name) + self.module_level_choices['controllers'][cfg.BASE_MODEL][ + cfg.TYPE]['default'] = controller_name + if 'controllers' not in self.model_level_info: + self.model_level_info['controllers'] = {} + if cfg.BASE_MODEL not in self.model_level_info['controllers']: + self.model_level_info['controllers'][cfg.BASE_MODEL] = {} + self.model_level_info['controllers'][ + cfg.BASE_MODEL][controller_name] = { + 'pipeline': [], + 'check_bind_module': [], + 'model_info': cfg + } + + def get_pipeline_given_modules(self, modules): + diffusion_model = modules['diffusion_model'] + pipepline_name = self.model_level_info[diffusion_model]['pipeline'][0] + return self.pipeline_level_modules[pipepline_name] diff --git a/scepter/studio/inference/inference_ui/__init__.py b/scepter/studio/inference/inference_ui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/studio/inference/inference_ui/component_names.py b/scepter/studio/inference/inference_ui/component_names.py new file mode 100644 index 0000000..715d10b --- /dev/null +++ b/scepter/studio/inference/inference_ui/component_names.py @@ -0,0 +1,214 @@ +# -*- coding: utf-8 -*- +# For dataset manager + + +class InferenceUIName(): + def __init__(self, language='en'): + if language == 'en': + self.advance_block_name = 'Advance Setting' + self.check_box_for_setting = [ + 'Use Mantra', 'Use Tuners', 'Use Controller' + ] + self.diffusion_paras = 'Generation Setting' + self.mantra_paras = 'Mantra Book' + self.tuner_paras = 'Tuners' + self.contrl_paras = 'Controlable Generation' + self.refine_paras = 'Refiner Setting' + elif language == 'zh': + self.advance_block_name = '生成选项' + self.check_box_for_setting = ['使用咒语', '使用微调', '使用控制'] + self.diffusion_paras = '生成参数设置' + self.mantra_paras = '咒语书' + self.tuner_paras = '微调模型' + self.contrl_paras = '可控生成' + self.refine_paras = 'Refine设置' + + +class ModelManageUIName(): + def __init__(self, language='en'): + if language == 'en': + self.model_block_name = 'Model Management' + self.postprocess_model_name = 'Refiners and Tuners' + self.diffusion_model = 'Unet' + self.first_stage_model = 'Vae' + self.cond_stage_model = 'Condition Model' + self.refine_diffusion_model = 'Refine Unet' + self.refine_cond_model = 'Refine Condition Model' + self.load_lora_tuner = 'Load Lora Tuner' + self.load_swift_tuner = 'Load swift Tuner' + elif language == 'zh': + self.model_block_name = '模型管理' + self.postprocess_model_name = 'Refiners and Tuners' + self.diffusion_model = 'Unet' + self.first_stage_model = 'Vae' + self.cond_stage_model = 'Condition Model' + self.refine_diffusion_model = 'Refine Unet' + self.refine_cond_model = 'Refine Condition Model' + self.load_lora_tuner = '加载 Lora 微调模型' + self.load_swift_tuner = '加载 Swift 微调模型' + + +class GalleryUIName(): + def __init__(self, language='en'): + if language == 'en': + self.gallery_block_name = "Model's Output" + self.gallery_diffusion_output = 'Diffusion Output' + self.gallery_before_refine_output = 'Before Refine Output' + self.prompt_input = 'Type Prompt Here' + self.generate = 'Generate' + elif language == 'zh': + self.gallery_block_name = '模型的输出' + self.gallery_diffusion_output = '扩散输出' + self.gallery_before_refine_output = '精炼前输出' + self.prompt_input = '在此输入提示' + self.generate = '生成' + + +class DiffusionUIName(): + def __init__(self, language='en'): + if language == 'en': + + self.sample = 'Sampler' + self.sample_steps = 'Sample Steps' + self.image_number = 'Images Number' + self.resolutions_height = 'Output Height' + self.resolutions_width = 'Output Width' + + self.negative_prompt = 'Negative Prompt' + self.negative_prompt_placeholder = 'Type Prompt Here' + self.negative_prompt_description = 'Describing what you do not want to see.' + self.prompt_prefix = 'Prompt Prefix' + self.guide_scale = 'Guide Scale For Uncondition' + self.guide_rescale = 'Guide ReScale' + self.discretization = 'Discretization' + self.random_seed = 'Use Random Seed' + self.seed = 'Used Seed' + + elif language == 'zh': + + self.sample = '采样器' + self.sample_steps = '采样步数' + self.image_number = '图片数量' + self.resolutions_height = '输出高度' + self.resolutions_width = '输出宽度' + self.negative_prompt = '负向提示' + self.negative_prompt_placeholder = '在此输入提示' + self.negative_prompt_description = '描述您不希望看到的内容。' + self.prompt_prefix = '提示前缀词' + self.guide_scale = '条件引导比例' + self.guide_rescale = '引导缩放' + self.discretization = '离散化' + self.random_seed = '使用随机种子' + self.seed = '使用的种子' + + +class MantraUIName(): + def __init__(self, language='en'): + if language == 'en': + + self.mantra_styles = 'Mantra Styles' + self.style_name = 'Mantra Name' + self.style_prompt = 'Mantra Prompt' + self.style_source = 'Mantra Source' + self.style_negative_prompt = 'Mantra Negative Prompt' + self.select_style = 'Selected Mantra' + self.style_desc = 'Mantra Description' + self.style_template = 'Mantra Prompt Template' + self.style_negative_template = 'Mantra Negative Prompt Template' + self.style_example = 'Mantra Results Example' + self.style_example_prompt = 'Mantra Example Prompt' + + elif language == 'zh': + self.mantra_styles = '咒语风格' + self.style_name = '咒语名称' + self.style_prompt = '咒语提示' + self.style_source = '咒语来源' + self.style_negative_prompt = '咒语负向提示' + self.select_style = '选定的咒语' + self.style_desc = '咒语描述' + self.style_template = '咒语提示模板' + self.style_negative_template = '咒语负向提示模板' + self.style_example = '咒语示例图' + self.style_example_prompt = '咒语示例提示词' + + +class RefinerUIName(): + def __init__(self, language='en'): + if language == 'en': + + self.refine_sample = 'Refine Sampler' + self.refine_discretization = 'Refine Discretization' + self.refine_guide_scale = 'Refine Guide Scale For Uncondition' + self.refine_guide_rescale = 'Guide ReScale' + self.refine_strength = 'Refine Strength' + self.refine_strength_description = 'Use to control how many steps used to refine.' + self.refine_diffusion_model = 'Refiner' + self.refine_cond_model = 'Refine Cond' + + elif language == 'zh': + + self.refine_sample = 'Refine采样器' + self.refine_discretization = 'Refine离散化' + self.refine_guide_scale = 'Refine条件引导比例' + self.refine_guide_rescale = 'Refine引导缩放' + self.refine_strength = 'Refine强度' + self.refine_strength_description = '用于控制用于Refine步数。' + self.refine_diffusion_model = 'Refiner' + self.refine_cond_model = 'Refine Cond' + + +class TunerUIName(): + def __init__(self, language='en'): + if language == 'en': + + self.tuner_model = 'Tuner' + self.tuner_name = 'Tuner Name' + self.tuner_type = 'Tuner Type' + self.tuner_desc = 'Tuner Description' + self.tuner_example = 'Results Example' + self.tuner_prompt_example = 'Prompt Example' + self.base_model = 'Base Model Name' + self.custom_tuner_model = 'Customized Model' + + elif language == 'zh': + self.tuner_model = '微调模型' + self.tuner_name = '微调模型名' + self.tuner_type = '微调模型类型' + self.tuner_desc = '微调模型描述' + self.tuner_example = '示例结果' + self.tuner_prompt_example = '示例提示词' + self.base_model = '基础模型' + self.custom_tuner_model = '自定义模型' + + +class ControlUIName(): + def __init__(self, language='en'): + if language == 'en': + + self.source_image = 'Source Image' + self.cond_image = 'Conditional Image' + self.control_preprocessor = 'Control Preprocessor' + self.crop_type = 'Crop type' + self.direction = ( + "Note: 1) After clicking 'Extract', you can extract " + 'the conditional image from the original image on the left;\n' + '2) You can also directly transfer the conditional image on the right; \n' + '3) Or simply upload the original image and directly run the\n' + "'Conditional Inference' below.") + self.preprocess = 'Preprocess' + self.control_model = 'Generation Model' + + self.control_err1 = "Condition preprocessor doesn't exist." + self.control_err2 = 'Condition preprocessor failed.' + elif language == 'zh': + self.preprocess = '条件预处理' + self.source_image = '源图片' + self.cond_image = '条件图片' + self.control_preprocessor = '图像预处理器' + self.crop_type = '抠图方式' + self.direction = ('注:1)点击【Extract】后可从左侧原始图像提取出条件图像;\n' + '2)也可直接传输右侧条件图像;\n' + '3)或只上传原始图像直接运行下方的【条件推理】') + self.control_err1 = '预处理器不存在。' + self.control_err2 = '预处理失败。' + self.control_model = '生成模型' diff --git a/scepter/studio/inference/inference_ui/control_ui.py b/scepter/studio/inference/inference_ui/control_ui.py new file mode 100644 index 0000000..5068465 --- /dev/null +++ b/scepter/studio/inference/inference_ui/control_ui.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- + +import gradio as gr +import numpy as np +import torchvision.transforms as TT +from PIL import Image + +from scepter.modules.annotator.registry import ANNOTATORS +from scepter.modules.utils.distribute import we +from scepter.studio.inference.inference_ui.component_names import ControlUIName +from scepter.studio.utils.uibase import UIBase + +refresh_symbol = '\U0001f504' # 🔄 + + +class ControlUI(UIBase): + def __init__(self, cfg, pipe_manager, is_debug=False, language='en'): + self.cfg = cfg + self.pipe_manager = pipe_manager + + controlable_anno = cfg.CONTROLABLE_ANNOTATORS + self.controlable_annotators = {} + self.control_choices = [] + self.control_defult = None + for control_anno in controlable_anno: + self.controlable_annotators[control_anno.TYPE] = { + 'cfg': control_anno, + 'device': 'offline', + 'model': None + } + if control_anno.IS_DEFAULT: + self.control_defult = control_anno.TYPE + self.control_choices.append(control_anno.TYPE) + if self.control_defult is None: + self.control_defult = self.control_choices[0] if len( + self.control_choices) > 0 else None + + default_choices = pipe_manager.module_level_choices + default_diffusion_model = default_choices['diffusion_model']['default'] + default_pipeline = pipe_manager.model_level_info[ + default_diffusion_model]['pipeline'][0] + if default_pipeline in default_choices[ + 'controllers'] and self.control_defult is not None: + self.controller_choices = default_choices['controllers'][ + default_pipeline][self.control_defult]['choices'] + self.controller_default = default_choices['controllers'][ + default_pipeline][self.control_defult]['default'] + else: + self.controller_choices = [] + self.controller_default = '' + self.component_names = ControlUIName(language) + + def load_annotator(self, annotator): + if annotator['device'] == 'offline': + annotator['model'] = ANNOTATORS.build(annotator['cfg']) + annotator['device'] = 'cpu' + if annotator['device'] == 'cpu': + annotator['model'] = annotator['model'].to(we.device_id) + annotator['device'] = we.device_id + return annotator + + def unload_annotator(self, annotator): + if not annotator['device'] == 'offline' and not annotator[ + 'device'] == 'cpu': + annotator['model'] = annotator['model'].to('cpu') + annotator['device'] = 'cpu' + return annotator + + def create_ui(self, *args, **kwargs): + gr.Markdown(self.component_names.preprocess) + with gr.Group(): + with gr.Row(): + with gr.Column(scale=1, min_width=0): + self.source_image = gr.Image( + label=self.component_names.source_image, + type='pil', + tool='editor', + interactive=True) + with gr.Column(scale=1, min_width=0): + self.cond_image = gr.Image( + label=self.component_names.cond_image, + type='pil', + tool='editor', + interactive=True) + with gr.Row(): + with gr.Column(scale=1, min_width=0): + with gr.Row(): + self.control_mode = gr.Dropdown( + label=self.component_names.control_preprocessor, + choices=self.control_choices, + value=self.control_defult, + interactive=True) + self.crop_type = gr.Dropdown( + label=self.component_names.crop_type, + choices=['CenterCrop', 'NoCrop'], + value='CenterCrop', + interactive=True) + self.control_model = gr.Dropdown( + label=self.component_names.control_model, + choices=self.controller_choices, + value=self.controller_default, + interactive=True) + with gr.Column(scale=1, min_width=0): + self.cond_button = gr.Button('Extract') + gr.Markdown(self.component_names.direction) + + def set_callbacks(self, model_manage_ui, diffusion_ui): + def extract_condition(source_image, control_mode, crop_type, + output_height, output_width): + if control_mode not in self.controlable_annotators: + gr.Error(self.component_names.control_err1 + ' ' + + control_mode) + annotator = self.controlable_annotators[control_mode] + annotator = self.load_annotator(annotator) + if crop_type == 'CenterCrop': + source_image = TT.Resize(max(output_height, + output_width))(source_image) + source_image = TT.CenterCrop( + (output_height, output_width))(source_image) + cond_image = annotator['model'](np.array(source_image)) + self.controlable_annotators[control_mode] = self.unload_annotator( + annotator) + if cond_image is None: + gr.Error(self.component_names.control_err2) + cond_image = Image.fromarray(cond_image) + return gr.Image(value=cond_image) + + self.cond_button.click(extract_condition, + inputs=[ + self.source_image, self.control_mode, + self.crop_type, diffusion_ui.output_height, + diffusion_ui.output_width + ], + outputs=[self.cond_image]) + + def change_control_mode(control_mode, diffusion_model): + default_choices = self.pipe_manager.module_level_choices + now_pipeline = self.pipe_manager.model_level_info[diffusion_model][ + 'pipeline'][0] + if now_pipeline in default_choices[ + 'controllers'] and control_mode in default_choices[ + 'controllers'][now_pipeline]: + controller_choices = default_choices['controllers'][ + now_pipeline][control_mode]['choices'] + controller_default = default_choices['controllers'][ + now_pipeline][control_mode]['default'] + else: + controller_choices = [] + controller_default = '' + return gr.Dropdown(choices=controller_choices, + value=controller_default) + + self.control_mode.change( + change_control_mode, + inputs=[self.control_mode, model_manage_ui.diffusion_model], + outputs=[self.control_model]) diff --git a/scepter/studio/inference/inference_ui/diffusion_ui.py b/scepter/studio/inference/inference_ui/diffusion_ui.py new file mode 100644 index 0000000..69451a3 --- /dev/null +++ b/scepter/studio/inference/inference_ui/diffusion_ui.py @@ -0,0 +1,182 @@ +# -*- coding: utf-8 -*- +import copy +import random + +import gradio as gr + +from scepter.studio.inference.inference_ui.component_names import \ + DiffusionUIName +from scepter.studio.utils.uibase import UIBase + +refresh_symbol = '\U0001f504' # 🔄 + + +class DiffusionUI(UIBase): + def __init__(self, cfg, pipe_manager, is_debug=False, language='en'): + self.cfg = cfg + self.pipe_manager = pipe_manager + + default_choices = pipe_manager.module_level_choices + default_diffusion = default_choices['diffusion_model']['default'] + now_pipeline = pipe_manager.model_level_info[default_diffusion][ + 'pipeline'][0] + + self.default_resolutions = pipe_manager.pipeline_level_modules[ + now_pipeline].paras.RESOLUTIONS + self.default_input = pipe_manager.pipeline_level_modules[ + now_pipeline].input + + self.diffusion_paras = self.load_all_paras() + # deal with resolution + self.h_level_dict = {} + for hw_tuple in self.diffusion_paras.RESOLUTIONS.get('VALUES', []): + h, w = hw_tuple + if h not in self.h_level_dict: + self.h_level_dict[h] = [] + self.h_level_dict[h].append(w) + self.component_names = DiffusionUIName(language) + + def merge_resolutions(self, ori_h_level_dict, default_resolutions): + h_level_dict = copy.deepcopy(ori_h_level_dict) + for res in default_resolutions: + h, w = res + if h not in h_level_dict: + h_level_dict[h] = [] + h_level_dict[h].append(w) + if len(self.default_resolutions) > 0: + default_res = default_resolutions[0] + else: + default_res = self.diffusion_paras.RESOLUTIONS.DEFAULT + return h_level_dict, default_res + + def get_default(self, ori_diffusion_paras, cur_default): + diffusion_paras = copy.deepcopy(ori_diffusion_paras) + for key in diffusion_paras: + if key.lower() in cur_default: + diffusion_paras.get(key).DEFAULT = cur_default.get(key.lower()) + value = diffusion_paras.get(key).get('VALUES') + if value is not None and cur_default.get( + key.lower()) not in value: + value.VALUES.append(cur_default.get(key.lower())) + return diffusion_paras + + def load_all_paras(self): + diffusion_paras = self.cfg.DIFFUSION_PARAS + return diffusion_paras + + def create_ui(self, *args, **kwargs): + self.cur_paras = self.get_default(self.diffusion_paras, + self.default_input) + with gr.Row(equal_height=True): + self.negative_prompt = gr.Textbox( + label=self.component_names.negative_prompt, + show_label=True, + placeholder=self.component_names.negative_prompt_placeholder, + info=self.component_names.negative_prompt_description, + value=self.cur_paras.NEGATIVE_PROMPT.get('DEFAULT', ''), + lines=2) + with gr.Row(equal_height=True): + with gr.Column(scale=1): + self.prompt_prefix = gr.Textbox( + label=self.component_names.prompt_prefix, + value=self.cur_paras.PROMPT_PREFIX.get('DEFAULT', ''), + interactive=True) + with gr.Column(scale=2): + self.sampler = gr.Dropdown( + label=self.component_names.sample, + choices=self.cur_paras.SAMPLE.get('VALUES', []), + value=self.cur_paras.SAMPLE.get('DEFAULT', ''), + interactive=True) + with gr.Row(equal_height=True): + with gr.Column(scale=1): + self.discretization = gr.Dropdown( + label=self.component_names.discretization, + choices=self.cur_paras.DISCRETIZATION.get('VALUES', []), + value=self.cur_paras.DISCRETIZATION.get('DEFAULT', ''), + interactive=True) + self.cur_h_level_dict, default_res = self.merge_resolutions( + self.h_level_dict, self.default_resolutions) + with gr.Column(scale=1): + self.output_height = gr.Dropdown( + label=self.component_names.resolutions_height, + choices=[key for key in self.cur_h_level_dict.keys()], + value=default_res[0], + interactive=True) + with gr.Column(scale=1): + self.output_width = gr.Dropdown( + label=self.component_names.resolutions_width, + choices=self.cur_h_level_dict[default_res[0]], + value=default_res[1], + interactive=True) + with gr.Row(equal_height=True): + self.image_number = gr.Slider( + label=self.component_names.image_number, + minimum=self.cur_paras.SAMPLES.get('MIN', 1), + maximum=self.cur_paras.SAMPLES.get('MAX', 4), + step=1, + value=self.cur_paras.SAMPLES.get('DEFAULT', 1), + interactive=True) + with gr.Row(equal_height=True): + self.sample_steps = gr.Slider( + label=self.component_names.sample_steps, + minimum=self.cur_paras.SAMPLE_STEPS.get('MIN', 1), + maximum=self.cur_paras.SAMPLE_STEPS.get('MAX', 100), + step=1, + value=self.cur_paras.SAMPLE_STEPS.get('DEFAULT', 30), + interactive=True) + + self.guide_scale = gr.Slider( + label=self.component_names.guide_scale, + minimum=self.cur_paras.GUIDE_SCALE.get('MIN', 1), + maximum=self.cur_paras.GUIDE_SCALE.get('MAX', 10), + step=0.5, + value=self.cur_paras.GUIDE_SCALE.get('DEFAULT', 7.5), + interactive=True) + self.guide_rescale = gr.Slider( + label=self.component_names.guide_rescale, + minimum=self.cur_paras.GUIDE_RESCALE.get('MIN', 1), + maximum=self.cur_paras.GUIDE_RESCALE.get('MAX', 1.0), + step=0.1, + value=self.cur_paras.GUIDE_RESCALE.get('DEFAULT', 0.5), + interactive=True) + with gr.Row(equal_height=True): + with gr.Column(scale=1): + self.seed_random = gr.Checkbox( + label=self.component_names.random_seed, value=True) + with gr.Row(equal_height=True, visible=False) as self.seed_panel: + with gr.Column(scale=2): + self.image_seed = gr.Textbox(label=self.component_names.seed, + value=-1, + max_lines=1, + interactive=True) + with gr.Column(scale=1): + self.refresh_seed = gr.Button(value=refresh_symbol) + + def set_callbacks(self, model_manage_ui): + def random_checked(r): + value = -1 + return (gr.Row(visible=not r), gr.Textbox(value=value)) + + def refresh_seed(): + return random.randint(0, 10**12) + + self.seed_random.change(random_checked, + inputs=[self.seed_random], + outputs=[self.seed_panel, self.image_seed], + queue=False, + show_progress=False) + self.refresh_seed.click(refresh_seed, outputs=[self.image_seed]) + + def change_height(h): + if h not in self.cur_h_level_dict: + return gr.Dropdown() + all_choices = self.cur_h_level_dict[h] + if len(all_choices) > 0: + default = all_choices[-1] + else: + default = -1 + return gr.Dropdown(choices=all_choices, value=default) + + self.output_height.change(change_height, + inputs=[self.output_height], + outputs=[self.output_width]) diff --git a/scepter/studio/inference/inference_ui/gallery_ui.py b/scepter/studio/inference/inference_ui/gallery_ui.py new file mode 100644 index 0000000..df2108c --- /dev/null +++ b/scepter/studio/inference/inference_ui/gallery_ui.py @@ -0,0 +1,201 @@ +# -*- coding: utf-8 -*- +import gradio as gr +import numpy as np +from PIL import Image + +from scepter.studio.inference.inference_ui.component_names import GalleryUIName +from scepter.studio.utils.uibase import UIBase + + +class GalleryUI(UIBase): + def __init__(self, cfg, pipe_manager, is_debug=False, language='en'): + self.pipe_manager = pipe_manager + self.component_names = GalleryUIName(language) + + def create_ui(self, *args, **kwargs): + with gr.Group(): + gr.Markdown(value=self.component_names.gallery_block_name) + with gr.Row(variant='panel', equal_height=True): + with gr.Column(scale=2, min_width=0, + visible=False) as self.before_refine_panel: + self.before_refine_gallery = gr.Gallery( + label=self.component_names. + gallery_before_refine_output, + value=[]) + with gr.Column(scale=2, min_width=0): + self.output_gallery = gr.Gallery( + label=self.component_names.gallery_diffusion_output, + value=[]) + with gr.Row(elem_classes='type_row'): + with gr.Column(scale=17): + self.prompt = gr.Textbox( + show_label=False, + placeholder=self.component_names.prompt_input, + elem_id='positive_prompt', + container=False, + autofocus=True, + elem_classes='type_row', + lines=1) + + with gr.Column(scale=3, min_width=0): + self.generate_button = gr.Button( + label='Generate', + value=self.component_names.generate, + elem_classes='type_row', + elem_id='generate_button', + visible=True) + + def set_callbacks(self, inference_ui, model_manage_ui, diffusion_ui, + mantra_ui, tuner_ui, refiner_ui, control_ui): + def generate_image( + mantra_state, tuner_state, control_state, diffusion_model, + first_stage_model, cond_stage_model, refiner_cond_model, + refiner_diffusion_model, tuner_model, custom_tuner_model, + control_model, crop_type, control_cond_image, prompt, + negative_prompt, prompt_prefix, sample, discretization, + output_height, output_width, image_number, sample_steps, + guide_scale, guide_rescale, refine_state, refine_strength, + refine_sampler, refine_discretization, refine_guide_scale, + refine_guide_rescale, style_template, style_negative_template, + image_seed): + current_pipeline = self.pipe_manager.get_pipeline_given_modules({ + 'diffusion_model': + diffusion_model, + 'first_stage_model': + first_stage_model, + 'cond_stage_model': + cond_stage_model, + 'refiner_cond_model': + refiner_cond_model, + 'refiner_diffusion_model': + refiner_diffusion_model + }) + now_pipeline = self.pipe_manager.model_level_info[diffusion_model][ + 'pipeline'][0] + used_tuner_model = [] + if not isinstance(tuner_model, list): + tuner_model = [tuner_model] + for tuner_m in tuner_model: + if tuner_m is None or tuner_m == '': + continue + if (now_pipeline + in self.pipe_manager.model_level_info['tuners'] + and tuner_m in self.pipe_manager. + model_level_info['tuners'][now_pipeline]): + tuner_m = self.pipe_manager.model_level_info['tuners'][ + now_pipeline][tuner_m]['model_info'] + used_tuner_model.append(tuner_m) + used_custom_tuner_model = [] + if not isinstance(custom_tuner_model, list): + custom_tuner_model = [custom_tuner_model] + for tuner_m in custom_tuner_model: + if tuner_m is None or tuner_m == '': + continue + if (now_pipeline in + self.pipe_manager.model_level_info['customized_tuners'] + and tuner_m in self.pipe_manager. + model_level_info['customized_tuners'][now_pipeline]): + tuner_m = self.pipe_manager.model_level_info[ + 'customized_tuners'][now_pipeline][tuner_m][ + 'model_info'] + used_custom_tuner_model.append(tuner_m) + + if (now_pipeline + in self.pipe_manager.model_level_info['controllers'] + and control_model in self.pipe_manager. + model_level_info['controllers'][now_pipeline]): + control_model = self.pipe_manager.model_level_info[ + 'controllers'][now_pipeline][control_model]['model_info'] + + prompt_rephrased = style_template.replace( + '{prompt}', prompt + ) if not style_template == '' and mantra_state else prompt + prompt_rephrased = f'{prompt_prefix}{prompt_rephrased}' if not prompt_prefix == '' else prompt_rephrased + negative_prompt_rephrased = negative_prompt + style_negative_template if mantra_state else negative_prompt + pipeline_input = { + 'prompt': prompt_rephrased, + 'negative_prompt': negative_prompt_rephrased, + 'sample': sample, + 'sample_steps': sample_steps, + 'discretization': discretization, + 'original_size_as_tuple': + [int(output_height), int(output_width)], + 'target_size_as_tuple': + [int(output_height), int(output_width)], + 'crop_coords_top_left': [0, 0], + 'guide_scale': guide_scale, + 'guide_rescale': guide_rescale, + } + if refine_state: + pipeline_input['refine_sampler'] = refine_sampler + pipeline_input['refine_discretization'] = refine_discretization + pipeline_input['refine_guide_scale'] = refine_guide_scale + pipeline_input['refine_guide_rescale'] = refine_guide_rescale + else: + refine_strength = 0 + results = current_pipeline( + pipeline_input, + num_samples=image_number, + intermediate_callback=None, + refine_strength=refine_strength, + img_to_img_strength=0, + tuner_model=used_tuner_model + + used_custom_tuner_model if tuner_state else None, + control_model=control_model if control_state else None, + control_cond_image=control_cond_image + if control_state else None, + crop_type=crop_type if control_state else None, + seed=int(image_seed)) + images = [] + before_images = [] + if 'images' in results: + images_tensor = results['images'] * 255 + images = [ + Image.fromarray(images_tensor[idx].permute( + 1, 2, 0).cpu().numpy().astype(np.uint8)) + for idx in range(images_tensor.shape[0]) + ] + if 'before_refine_images' in results and results[ + 'before_refine_images'] is not None: + before_refine_images_tensor = results[ + 'before_refine_images'] * 255 + before_images = [ + Image.fromarray(before_refine_images_tensor[idx].permute( + 1, 2, 0).cpu().numpy().astype(np.uint8)) + for idx in range(before_refine_images_tensor.shape[0]) + ] + if 'seed' in results: + print(results['seed']) + print(images, before_images) + return ( + gr.Column(visible=len(before_images) > 0), + before_images, + images, + ) + + self.generate_button.click( + generate_image, + inputs=[ + inference_ui.mantra_state, inference_ui.tuner_state, + inference_ui.control_state, model_manage_ui.diffusion_model, + model_manage_ui.first_stage_model, + model_manage_ui.cond_stage_model, + refiner_ui.refiner_cond_model, + refiner_ui.refiner_diffusion_model, tuner_ui.tuner_model, + tuner_ui.custom_tuner_model, control_ui.control_model, + control_ui.crop_type, control_ui.cond_image, self.prompt, + diffusion_ui.negative_prompt, diffusion_ui.prompt_prefix, + diffusion_ui.sampler, diffusion_ui.discretization, + diffusion_ui.output_height, diffusion_ui.output_width, + diffusion_ui.image_number, diffusion_ui.sample_steps, + diffusion_ui.guide_scale, diffusion_ui.guide_rescale, + refiner_ui.refine_state, refiner_ui.refine_strength, + refiner_ui.refine_sampler, refiner_ui.refine_discretization, + refiner_ui.refine_guide_scale, refiner_ui.refine_guide_rescale, + mantra_ui.style_template, mantra_ui.style_negative_template, + diffusion_ui.image_seed + ], + outputs=[ + self.before_refine_panel, self.before_refine_gallery, + self.output_gallery + ]) diff --git a/scepter/studio/inference/inference_ui/mantra_ui.py b/scepter/studio/inference/inference_ui/mantra_ui.py new file mode 100644 index 0000000..19c3e7c --- /dev/null +++ b/scepter/studio/inference/inference_ui/mantra_ui.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +import os + +import gradio as gr +from tqdm import tqdm + +from scepter.modules.utils.file_system import FS +from scepter.studio.inference.inference_ui.component_names import MantraUIName +from scepter.studio.utils.uibase import UIBase + +refresh_symbol = '\U0001f504' # 🔄 + + +class MantraUI(UIBase): + def __init__(self, cfg, pipe_manager, is_debug=False, language='en'): + self.cfg = cfg + self.language = language + self.pipe_manager = pipe_manager + default_choices = pipe_manager.module_level_choices + default_diffusion_model = default_choices['diffusion_model']['default'] + self.default_pipeline = pipe_manager.model_level_info[ + default_diffusion_model]['pipeline'][0] + self.cfg_mantra = cfg.MANTRAS + self.name_level_style, self.all_styles = self.load_all_styles() + self.component_names = MantraUIName(language) + + def load_all_styles(self): + all_styles = {} + name_level_style = {} + for one_style in tqdm(self.cfg_mantra): + if one_style.BASE_MODEL not in name_level_style: + name_level_style[one_style.BASE_MODEL] = {} + if one_style.BASE_MODEL not in all_styles: + all_styles[one_style.BASE_MODEL] = [] + if self.language == 'zh': + name_level_style[one_style.BASE_MODEL][ + one_style.NAME_ZH] = one_style + all_styles[one_style.BASE_MODEL].append(one_style.NAME_ZH) + else: + name_level_style[one_style.BASE_MODEL][ + one_style.NAME] = one_style + all_styles[one_style.BASE_MODEL].append(one_style.NAME) + # if one_style.get('IMAGE_PATH', None): + # one_style.IMAGE_PATH = FS.get_from(one_style.IMAGE_PATH) + return name_level_style, all_styles + + def create_ui(self, *args, **kwargs): + with gr.Row(equal_height=True): + with gr.Column(scale=1): + with gr.Group(visible=True): + with gr.Row(equal_height=True): + self.style = gr.Dropdown( + label=self.component_names.mantra_styles, + choices=self.all_styles[self.default_pipeline], + value=None, + multiselect=True, + interactive=True) + with gr.Row(equal_height=True): + with gr.Column(scale=1): + self.style_name = gr.Text( + value='', + label=self.component_names.style_name) + with gr.Column(scale=1): + self.style_source = gr.Text( + value='', + label=self.component_names.style_source) + with gr.Column(scale=1): + self.style_desc = gr.Text( + value='', + label=self.component_names.style_desc) + with gr.Row(equal_height=True): + self.style_prompt = gr.Text( + value='', + label=self.component_names.style_prompt, + lines=4) + with gr.Row(equal_height=True): + self.style_negative_prompt = gr.Text( + value='', + label=self.component_names.style_negative_prompt, + lines=4) + with gr.Column(scale=1): + with gr.Group(visible=True): + with gr.Row(equal_height=True): + self.style_template = gr.Text( + value='', + label=self.component_names.style_template, + lines=2) + with gr.Row(equal_height=True): + self.style_negative_template = gr.Text( + value='', + label=self.component_names.style_negative_template, + lines=2) + with gr.Row(equal_height=True): + self.style_example = gr.Image( + label=self.component_names.style_example, + source='upload', + value=None, + interactive=False) + with gr.Row(equal_height=True): + self.style_example_prompt = gr.Text( + value='', + label=self.component_names.style_example_prompt, + lines=2) + + def set_callbacks(self, model_manage_ui): + def change_style(style, diffusion_model): + style_template = '' + style_negative_template = [] + if len(style) > 0: + style_name = style[-1] + diffusion_model_info = self.pipe_manager.model_level_info[ + diffusion_model] + now_pipeline = diffusion_model_info['pipeline'][0] + style_info = self.name_level_style[now_pipeline].get( + style_name, {}) + for st in style: + c_style_info = self.name_level_style[now_pipeline].get( + st, {}) + c_prompt = c_style_info.get('PROMPT', '') + c_negative_prompt = c_style_info.get('NEGATIVE_PROMPT', '') + if style_template == '': + style_template = c_prompt + elif '{prompt}' in style_template: + if '{prompt}' in c_prompt: + style_template = style_template.replace( + '{prompt}', c_prompt) + else: + style_template += c_prompt + style_negative_template.append(c_negative_prompt) + else: + style_name = '' + style_info = {} + style_negative_template = ','.join(style_negative_template) + if style_info.get( + 'IMAGE_PATH', + None) and not os.path.exists(style_info.IMAGE_PATH): + style_info.IMAGE_PATH = FS.get_from(style_info.IMAGE_PATH) + return (gr.Text(value=style_name), + gr.Text(value=style_info.get('SOURCE', '')), + gr.Text(value=style_info.get('PROMPT', '')), + gr.Text(value=style_info.get('NEGATIVE_PROMPT', '')), + gr.Text(value=style_template), + gr.Text(value=style_negative_template), + gr.Image(value=style_info.get('IMAGE_PATH', None)), + gr.Text(value=style_info.get('PROMPT_EXAMPLE', ''))) + + self.style.change(change_style, + inputs=[self.style, model_manage_ui.diffusion_model], + outputs=[ + self.style_name, self.style_source, + self.style_prompt, self.style_negative_prompt, + self.style_template, + self.style_negative_template, self.style_example, + self.style_example_prompt + ]) diff --git a/scepter/studio/inference/inference_ui/model_manage_ui.py b/scepter/studio/inference/inference_ui/model_manage_ui.py new file mode 100644 index 0000000..8861ad0 --- /dev/null +++ b/scepter/studio/inference/inference_ui/model_manage_ui.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- + +import gradio as gr + +from scepter.studio.inference.inference_ui.component_names import \ + ModelManageUIName +from scepter.studio.utils.uibase import UIBase + +refresh_symbol = '\U0001f504' # 🔄 + + +class ModelManageUI(UIBase): + def __init__(self, cfg, pipe_manager, is_debug=False, language='en'): + self.pipe_manager = pipe_manager + self.default_choices = pipe_manager.module_level_choices + self.component_names = ModelManageUIName(language) + + def create_ui(self, *args, **kwargs): + with gr.Group(): + gr.Markdown(value=self.component_names.model_block_name) + with gr.Row(variant='panel', equal_height=True): + with gr.Column(scale=1, min_width=0) as self.diffusion_panel: + self.diffusion_model = gr.Dropdown( + label=self.component_names.diffusion_model, + choices=self.default_choices['diffusion_model'] + ['choices'], + value=self.default_choices['diffusion_model'] + ['default'], + interactive=True) + with gr.Column(scale=1, min_width=0) as self.first_stage_panel: + self.first_stage_model = gr.Dropdown( + label=self.component_names.first_stage_model, + choices=self.default_choices['first_stage_model'] + ['choices'], + value=self.default_choices['first_stage_model'] + ['default'], + interactive=False) + with gr.Column(scale=1, min_width=0) as self.cond_stage_panel: + self.cond_stage_model = gr.Dropdown( + label=self.component_names.cond_stage_model, + choices=self.default_choices['cond_stage_model'] + ['choices'], + value=self.default_choices['cond_stage_model'] + ['default'], + interactive=False) + # with gr.Accordion( + # label=self.component_names.postprocess_model_name, + # open=False): + # with gr.Row(equal_height=True): + # self.advance_postprocess_checkbox = gr.CheckboxGroup( + # # choices=['Refiners', 'Tuners'], show_label=False) + # choices=['Tuners'], show_label=False) + # with gr.Row(equal_height=True, + # visible=False) as self.refine_diffusion_panel: + # with gr.Column(variant='panel', scale=1, min_width=0): + # self.refiner_diffusion_model = gr.Dropdown( + # label=self.component_names.refine_diffusion_model, + # choices=self.default_choices[ + # 'refiner_diffusion_model']['choices'], + # value=self.default_choices[ + # 'refiner_diffusion_model']['default'], + # interactive=True) + # with gr.Column(variant='panel', scale=1, min_width=0): + # self.refiner_cond_model = gr.Dropdown( + # label=self.component_names.refine_cond_model, + # choices=self.default_choices['refiner_cond_model'] + # ['choices'], + # value=self.default_choices['refiner_cond_model'] + # ['default'], + # interactive=True) + # with gr.Column(variant='panel', scale=1, min_width=0): + # self.tuner_button = gr.Button(value=refresh_symbol) + # + # def refresh_choices(): + # return gr.update(choices=get_tuner_choices()) + # + # self.tuner_button.click(refresh_choices, [], + # [self.tuner_model]) + # with gr.Column(variant='panel', scale=4, min_width=0): + # with gr.Group() as self.tuners_group: + # with gr.Row(variant='panel') as self.tuners_panel: + # with gr.Column( + # scale=1, + # min_width=0) as self.tuners_management: + # self.load_Lora_tuner_btn = gr.Button( + # value=self.component_names. + # load_lora_tuner) + # self.load_swift_tuner_btn = gr.Button( + # value=self.component_names. + # load_swift_tuner) + # with gr.Column(scale=1, + # min_width=0) as self.load_panel: + # self.tuner_name = gr.Text( + # label='tuner_name') + # with gr.Row(variant='panel') as self.tuner_info: + # with gr.Accordion(label=self.component_names. + # postprocess_model_name, + # open=False): + # self.tuner_name = gr.Text( + # label='tuner_name') + + def set_callbacks(self, diffusion_ui, tuner_ui, control_ui, mantra_ui): + # def select_refine_tuner(all_select, evt: gr.SelectData): + # if 'Refiners' in all_select: + # refine_panel = gr.Row(visible=True) + # refine_tab = gr.Group(visible=True) + # refine_state = True + # else: + # refine_panel = gr.Row(visible=False) + # refine_tab = gr.Group(visible=False) + # refine_state = False + # # if 'Tuners' in all_select: + # # tuner_panel = gr.Row(visible=True) + # # else: + # # tuner_panel = gr.Row(visible=False) + # return refine_panel, refine_tab, refine_state + # + # self.advance_postprocess_checkbox.select( + # select_refine_tuner, + # inputs=[self.advance_postprocess_checkbox], + # outputs=[ + # self.refine_diffusion_panel, self.tuner_choice_panel, + # advance_ui.refine_tab, advance_ui.refine_state + # ]) + def diffusion_model_change(diffusion_model, control_mode): + diffusion_model_info = self.pipe_manager.model_level_info[ + diffusion_model] + now_pipeline = diffusion_model_info['pipeline'][0] + pipeline_ins = self.pipe_manager.pipeline_level_modules[ + now_pipeline] + all_module_name = {} + for module_name in self.pipe_manager.module_list: + module = getattr(pipeline_ins, module_name) + if module is None: + continue + model_name = f"{now_pipeline}_{module['name']}" + all_module_name[module_name] = model_name + if now_pipeline in self.default_choices['tuners']: + tunner_choices = self.default_choices['tuners'][now_pipeline][ + 'choices'] + else: + tunner_choices = [] + + if now_pipeline in self.default_choices[ + 'controllers'] and control_mode in self.default_choices[ + 'controllers'][now_pipeline]: + controller_choices = self.default_choices['controllers'][ + now_pipeline][control_mode]['choices'] + controller_default = self.default_choices['controllers'][ + now_pipeline][control_mode]['default'] + else: + controller_choices = [] + controller_default = '' + + default_resolutions = self.pipe_manager.pipeline_level_modules[ + now_pipeline].paras.RESOLUTIONS + h_level_dict, default_res = diffusion_ui.merge_resolutions( + diffusion_ui.h_level_dict, default_resolutions) + diffusion_ui.cur_h_level_dict = h_level_dict + + default_input = self.pipe_manager.pipeline_level_modules[ + now_pipeline].input + cur_paras = diffusion_ui.get_default(diffusion_ui.diffusion_paras, + default_input) + diffusion_ui.cur_paras = cur_paras + return ( + gr.Dropdown(value=all_module_name['first_stage_model']), + gr.Dropdown(value=all_module_name['cond_stage_model']), + gr.Dropdown(choices=tunner_choices, value=None), + gr.Dropdown(choices=controller_choices, + value=controller_default), + gr.Dropdown(choices=mantra_ui.all_styles[now_pipeline], + value=[]), + gr.Textbox(choices=cur_paras.NEGATIVE_PROMPT.get('VALUES', []), + value=cur_paras.NEGATIVE_PROMPT.get('DEFAULT', '')), + gr.Textbox(choices=cur_paras.PROMPT_PREFIX.get('VALUES', []), + value=cur_paras.PROMPT_PREFIX.get('DEFAULT', '')), + gr.Dropdown(choices=[key for key in h_level_dict.keys()], + value=default_res[0]), + gr.Dropdown(choices=cur_paras.SAMPLE.get('VALUES', []), + value=cur_paras.SAMPLE.get('DEFAULT', '')), + gr.Dropdown(choices=cur_paras.DISCRETIZATION.get('VALUES', []), + value=cur_paras.DISCRETIZATION.get('DEFAULT', '')), + gr.Slider(value=cur_paras.SAMPLE_STEPS.get('DEFAULT', 30)), + gr.Slider(value=cur_paras.GUIDE_SCALE.get('DEFAULT', 7.5)), + gr.Slider(value=cur_paras.GUIDE_RESCALE.get('DEFAULT', 0.5))) + + self.diffusion_model.change( + diffusion_model_change, + inputs=[self.diffusion_model, control_ui.control_mode], + outputs=[ + self.first_stage_model, self.cond_stage_model, + tuner_ui.tuner_model, control_ui.control_model, + mantra_ui.style, diffusion_ui.negative_prompt, + diffusion_ui.prompt_prefix, diffusion_ui.output_height, + diffusion_ui.sampler, diffusion_ui.discretization, + diffusion_ui.sample_steps, diffusion_ui.guide_scale, + diffusion_ui.guide_rescale + ]) diff --git a/scepter/studio/inference/inference_ui/refiner_ui.py b/scepter/studio/inference/inference_ui/refiner_ui.py new file mode 100644 index 0000000..7158a46 --- /dev/null +++ b/scepter/studio/inference/inference_ui/refiner_ui.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +import gradio as gr + +from scepter.studio.inference.inference_ui.component_names import RefinerUIName +from scepter.studio.utils.uibase import UIBase + +refresh_symbol = '\U0001f504' # 🔄 + + +class RefinerUI(UIBase): + def __init__(self, cfg, pipe_manager, is_debug=False, language='en'): + self.cfg = cfg + self.pipe_manager = pipe_manager + self.diffusion_paras = self.load_all_paras() + self.component_names = RefinerUIName(language) + + def load_all_paras(self): + diffusion_paras = self.cfg.DIFFUSION_PARAS + return diffusion_paras + + def create_ui(self, *args, **kwargs): + self.refine_state = gr.State(value=False) + with gr.Group(visible=False) as self.refine_tab: + with gr.Row(equal_height=True): + with gr.Column(variant='panel', scale=1, min_width=0): + self.refiner_diffusion_model = gr.Dropdown( + label=self.component_names.refine_diffusion_model, + choices=[], + value=None, + interactive=True) + with gr.Column(variant='panel', scale=1, min_width=0): + self.refiner_cond_model = gr.Dropdown( + label=self.component_names.refine_cond_model, + choices=[], + value=None, + interactive=True) + with gr.Row(equal_height=True): + self.refine_strength = gr.Slider( + label=self.component_names.refine_strength, + minimum=self.diffusion_paras.REFINE_STRENGTH.get( + 'MIN', 0.0), + maximum=self.diffusion_paras.REFINE_STRENGTH.get( + 'MAX', 1.0), + step=0.05, + value=self.diffusion_paras.REFINE_STRENGTH.get( + 'DEFAULT', 7.5), + interactive=True) + with gr.Row(equal_height=True): + with gr.Column(scale=1): + self.refine_sampler = gr.Dropdown( + label=self.component_names.refine_sample, + choices=self.diffusion_paras.REFINE_SAMPLERS.get( + 'VALUES', []), + value=self.diffusion_paras.REFINE_SAMPLERS.get( + 'DEFAULT', ''), + interactive=True) + with gr.Column(scale=1): + self.refine_discretization = gr.Dropdown( + label=self.component_names.refine_discretization, + choices=self.diffusion_paras.REFINE_DISCRETIZATION.get( + 'VALUES', []), + value=self.diffusion_paras.REFINE_DISCRETIZATION.get( + 'DEFAULT', ''), + interactive=True) + with gr.Row(equal_height=True): + with gr.Column(scale=1): + self.refine_guide_scale = gr.Slider( + label=self.component_names.refine_guide_scale, + minimum=self.diffusion_paras.REFINE_GUIDE_SCALE.get( + 'MIN', 1), + maximum=self.diffusion_paras.REFINE_GUIDE_SCALE.get( + 'MAX', 10), + step=0.5, + value=self.diffusion_paras.REFINE_GUIDE_SCALE.get( + 'DEFAULT', 7.5), + interactive=True) + with gr.Column(scale=1): + self.refine_guide_rescale = gr.Slider( + label=self.component_names.refine_guide_rescale, + minimum=self.diffusion_paras.REFINE_GUIDE_RESCALE.get( + 'MIN', 1), + maximum=self.diffusion_paras.REFINE_GUIDE_RESCALE.get( + 'MAX', 1.0), + step=0.1, + value=self.diffusion_paras.REFINE_GUIDE_RESCALE.get( + 'DEFAULT', 0.5), + interactive=True) + + def set_callbacks(self): + pass diff --git a/scepter/studio/inference/inference_ui/tuner_ui.py b/scepter/studio/inference/inference_ui/tuner_ui.py new file mode 100644 index 0000000..14ff853 --- /dev/null +++ b/scepter/studio/inference/inference_ui/tuner_ui.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +import os + +import gradio as gr +from tqdm import tqdm + +from scepter.modules.utils.file_system import FS +from scepter.studio.inference.inference_ui.component_names import TunerUIName +from scepter.studio.utils.uibase import UIBase + +refresh_symbol = '\U0001f504' # 🔄 + + +class TunerUI(UIBase): + def __init__(self, cfg, pipe_manager, is_debug=False, language='en'): + self.cfg = cfg + self.pipe_manager = pipe_manager + self.default_choices = pipe_manager.module_level_choices + default_diffusion_model = self.default_choices['diffusion_model'][ + 'default'] + self.default_pipeline = pipe_manager.model_level_info[ + default_diffusion_model]['pipeline'][0] + if self.default_pipeline in self.default_choices['tuners']: + self.tunner_choices = self.default_choices['tuners'][ + self.default_pipeline]['choices'] + self.tunner_default = self.default_choices['tuners'][ + self.default_pipeline]['default'] + else: + self.tunner_choices = [] + + self.tunner_default = None + self.component_names = TunerUIName(language) + self.cfg_tuners = cfg.TUNERS + self.name_level_tuners = {} + for one_tuner in tqdm(self.cfg_tuners): + if one_tuner.BASE_MODEL not in self.name_level_tuners: + self.name_level_tuners[one_tuner.BASE_MODEL] = {} + # if one_tuner.get('IMAGE_PATH', None): + # one_tuner.IMAGE_PATH = FS.get_from(one_tuner.IMAGE_PATH) + if language == 'zh': + self.name_level_tuners[one_tuner.BASE_MODEL][ + one_tuner.NAME_ZH] = one_tuner + else: + self.name_level_tuners[one_tuner.BASE_MODEL][ + one_tuner.NAME] = one_tuner + + def create_ui(self, *args, **kwargs): + with gr.Row(equal_height=True): + with gr.Column(variant='panel', scale=1, min_width=0): + with gr.Group(visible=True): + with gr.Row(equal_height=True): + with gr.Column(scale=1): + self.tuner_model = gr.Dropdown( + label=self.component_names.tuner_model, + choices=self.tunner_choices, + value=None, + multiselect=True, + interactive=True) + with gr.Column(scale=1): + self.custom_tuner_model = gr.Dropdown( + label=self.component_names.custom_tuner_model, + choices=[], + value=None, + multiselect=True, + interactive=True) + with gr.Row(equal_height=True): + with gr.Column(scale=1): + self.tuner_type = gr.Text( + value='', + label=self.component_names.tuner_type) + with gr.Column(scale=1): + self.base_model = gr.Text( + value='', + label=self.component_names.base_model) + with gr.Column(scale=1): + self.tuner_desc = gr.Text( + value='', + label=self.component_names.tuner_desc, + lines=4) + with gr.Column(variant='panel', scale=1, min_width=0): + with gr.Group(visible=True): + with gr.Row(equal_height=True): + self.tuner_example = gr.Image( + label=self.component_names.tuner_example, + source='upload', + value=None, + interactive=False) + with gr.Row(equal_height=True): + self.tuner_prompt_example = gr.Text( + value='', + label=self.component_names.tuner_prompt_example, + lines=2) + + def set_callbacks(self, model_manage_ui): + def tuner_model_change(tuner_model, diffusion_model): + diffusion_model_info = self.pipe_manager.model_level_info[ + diffusion_model] + now_pipeline = diffusion_model_info['pipeline'][0] + tuner_info = {} + if tuner_model is not None and len(tuner_model) > 0: + tuner_info = self.name_level_tuners[now_pipeline].get( + tuner_model[-1], {}) + if tuner_info.get( + 'IMAGE_PATH', + None) and not os.path.exists(tuner_info.IMAGE_PATH): + tuner_info.IMAGE_PATH = FS.get_from(tuner_info.IMAGE_PATH) + return (gr.Text(value=tuner_info.get('TUNER_TYPE', '')), + gr.Text(value=tuner_info.get('BASE_MODEL', '')), + gr.Text(value=tuner_info.get('DESCRIPTION', '')), + gr.Image(value=tuner_info.get('IMAGE_PATH', None)), + gr.Text(value=tuner_info.get('PROMPT_EXAMPLE', ''))) + + self.tuner_model.change( + tuner_model_change, + inputs=[self.tuner_model, model_manage_ui.diffusion_model], + outputs=[ + self.tuner_type, self.base_model, self.tuner_desc, + self.tuner_example, self.tuner_prompt_example + ]) diff --git a/scepter/studio/preprocess/__init__.py b/scepter/studio/preprocess/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/studio/preprocess/caption_editor_ui/__init__.py b/scepter/studio/preprocess/caption_editor_ui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/studio/preprocess/caption_editor_ui/component_names.py b/scepter/studio/preprocess/caption_editor_ui/component_names.py new file mode 100644 index 0000000..4d64f3a --- /dev/null +++ b/scepter/studio/preprocess/caption_editor_ui/component_names.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +# For dataset manager +class CreateDatasetUIName(): + def __init__(self, language='en'): + if language == 'en': + self.dataset_name = 'All Dataset' + self.btn_create_datasets = 'Create Dataset' + self.user_data_name = 'Current Dataset Name' + self.modify_data_button = 'Modify Name' + self.confirm_data_button = 'Confirm' + self.refresh_list_button = 'Refresh List' + self.zip_file = 'Upload Dataset(Zip/Txt)' + self.zip_file_url = 'Dataset Url' + self.btn_create_datasets_from_file = 'Create Dataset From File' + self.user_direction = ( + '### User Guide: \n' + + f'* {self.btn_create_datasets} button is used to create a new dataset ' + "from scratch. Please make sure to modify the dataset's name and version. After creation, " + 'you can upload images one by one. \n' + f'* The {self.btn_create_datasets_from_file} button supports creating a new dataset from ' + 'a file, currently supporting zip files. For zip files, the format should be consistent' + " with the one used during training, ensuring it contains an 'images/' folder and a '" + "train.csv' (which will use the image paths in this file); " + 'The first line is Target:FILE, Prompt, followed by the format of each line: image path, description.' + 'we also surpport the zip of ' + 'one level subfolder of images whose format are in jpg, jpeg, png, webp.\n' + f'* If you have refreshed the page, please click the {self.refresh_list_button} ' + 'button to ensure all previously created datasets are visible in the dropdown menu.\n' + '* ZIP example: https://modelscope.cn/api/v1/models/damo/scepter/repo?Revision=master&FilePath=datasets/3D_example_csv.zip \n' # noqa + '* For processing and training with large-scale data, it is recommended to use the command line.' + ) + # Error or Warning + self.illegal_data_name_err1 = ( + 'The data name is empty or contains illegal ' + "characters ' ' (space) or '/' (slash).") + self.illegal_data_name_err2 = "Please follow the format '{name}-{version}-{randomstr}'" + self.illegal_data_name_err3 = "Do not include '.' in the dataset name." + self.illegal_data_name_err4 = 'Please do not upload files and set dataset links simultaneously.' + self.illegal_data_name_err5 = 'Invalid dataset name, please switch datasets or create a new one.' + self.illegal_data_err1 = 'File download failed' + self.illegal_data_err2 = 'Illegal file format' + self.illegal_data_err3 = 'File decompression failed, failed to upload to storage!' + self.modify_data_name_err1 = 'Failed to change dataset name!' + self.refresh_data_list_info1 = ( + 'The dataset name has been changed, ' + 'please refresh the list and try again.') + elif language == 'zh': + self.dataset_name = '数据集' + self.btn_create_datasets = '新建' + self.user_data_name = '当前数据集名称' + self.modify_data_button = '修改数据集名称' + self.confirm_data_button = '确认' + self.refresh_list_button = '刷新列表' + self.zip_file = '上传数据集' + self.zip_file_url = '数据集链接' + self.btn_create_datasets_from_file = '从文件新建' + self.user_direction = ( + '### 使用说明 \n' + + f'* {self.btn_create_datasets} 按钮用于从零新建数据集,请注意修改数据集的name和version,' + '新建完成后可以逐个上传图片。\n' + + f'* {self.btn_create_datasets_from_file} 按钮支持从文件中来新建数据集,目前支持zip文件,' + '需要保证在文件夹外进行打包,并包含images/文件夹和train.csv(会使用该文件中的图片路径),首行为Target:FILE,Prompt,' + '其次每行格式为:图片路径,描述;' + '同时我们也支持图像文件的zip包,格式在jpg、jpeg、png或webp \n' + + f'* 如果刷新了页面,请点击{self.refresh_list_button} 按钮以确保所有以往创建的数据集在下拉框中可见。\n' + '* ZIP样例路径:https://modelscope.cn/api/v1/models/damo/scepter/repo?Revision=master&FilePath=datasets/3D_example_csv.zip \n' # noqa + '* 对于大规模数据的处理和训练,建议使用命令行形式') + # Error or Warning + self.illegal_data_name_err1 = "数据名称为空或包含非法字符' '或者'/'" + self.illegal_data_name_err2 = '请按照{name}-{version}-{randomstr}' + self.illegal_data_name_err3 = "数据集名称中不要包含'.'" + self.illegal_data_name_err4 = '请不要同时上传文件和设置数据集链接' + self.illegal_data_name_err5 = '不合法的数据集名称,请切换数据集或新建数据集。' + self.illegal_data_err1 = '文件下载失败' + self.illegal_data_err2 = '非法的文件格式' + self.illegal_data_err3 = '文件解压失败,上传存储器失败!' + self.modify_data_name_err1 = '变更数据集名称失败!' + self.refresh_data_list_info1 = '该数据集名称发生了变更,请刷新列表试一下。' + + +class DatasetGalleryUIName(): + def __init__(self, language='en'): + if language == 'en': + self.upload_image = 'Upload Image' + self.upload_image_btn = 'Upload' + self.image_caption = 'Image Caption' + self.dataset_images = 'Dataset Images' + self.ori_caption = 'Original Caption' + self.edit_caption = 'Editable Caption' + self.btn_modify = 'Replace Caption' + self.btn_delete = 'Delete Image' + # Error or Warning + self.delete_err1 = 'Deletion failed, the data is already empty.' + elif language == 'zh': + self.upload_image = '上传图片' + self.upload_image_btn = '上传' + self.image_caption = '图片描述' + self.dataset_images = '图片集' + self.ori_caption = '原始描述' + self.edit_caption = '编辑描述' + self.btn_modify = '替换描述' + self.btn_delete = '删除图片' + # Error or Warning + self.delete_err1 = '删除失败,数据已经为空了' + + +class ExportDatasetUIName(): + def __init__(self, language='en'): + if language == 'en': + self.btn_export_zip = 'Download Data' + self.btn_export_list = 'Export List' + self.export_file = 'Download Data' + # Error or Warning + self.export_err1 = 'The dataset is empty, export is not possible!' + self.export_zip_err1 = 'Failed to compress the file!' + self.upload_err1 = 'Failed to compress the file!' + self.go_to_train = 'Go to train...' + elif language == 'zh': + self.btn_export_zip = '导出数据' + self.btn_export_list = '导出列表' + self.export_file = '下载数据' + self.export_err1 = '数据集为空,无法导出!' + self.export_zip_err1 = '压缩文件失败!' + self.upload_err1 = '压缩文件失败!' + self.go_to_train = '去训练...' diff --git a/scepter/studio/preprocess/caption_editor_ui/create_dataset_ui.py b/scepter/studio/preprocess/caption_editor_ui/create_dataset_ui.py new file mode 100644 index 0000000..a683a23 --- /dev/null +++ b/scepter/studio/preprocess/caption_editor_ui/create_dataset_ui.py @@ -0,0 +1,605 @@ +# -*- coding: utf-8 -*- +from __future__ import annotations + +import copy +import csv +import datetime +import json +import os.path + +import gradio as gr +from PIL import Image +from tqdm import tqdm + +from scepter.modules.utils.directory import get_md5 +from scepter.modules.utils.file_system import FS +from scepter.studio.preprocess.caption_editor_ui.component_names import \ + CreateDatasetUIName +from scepter.studio.utils.uibase import UIBase + +refresh_symbol = '\U0001f504' # 🔄 + + +class CreateDatasetUI(UIBase): + def __init__(self, cfg, is_debug=False, language='en'): + self.work_dir = cfg.WORK_DIR + self.dir_list = FS.walk_dir(self.work_dir, recurse=False) + self.cache_file = {} + self.meta_dict = {} + self.dataset_list = self.load_history() + self.components_name = CreateDatasetUIName(language) + + def load_meta(self, meta_file): + dataset_meta = json.load(open(meta_file, 'r')) + return dataset_meta + + def write_csv(self, file_list, save_csv, data_folder): + with FS.put_to(save_csv) as local_path: + print(local_path) + with open(local_path, 'w') as f: + writer = csv.writer(f) + writer.writerow(['Target:FILE', 'Prompt']) + for one_file in file_list: + relative_file = one_file['relative_path'] + if relative_file.startswith('/'): + relative_file = relative_file[1:] + writer.writerow([relative_file, one_file['caption']]) + return save_csv + + def write_file_list(self, file_list, save_csv): + with FS.put_to(save_csv) as local_path: + print(local_path) + with open(local_path, 'w') as f: + for one_file in file_list: + is_flag, file_path = self.del_prefix( + one_file['image_path'], prefix=one_file['prefix']) + f.write('{},{},{},{}\n'.format(file_path, + one_file['width'], + one_file['height'], + one_file['caption'])) + return save_csv + + def save_meta(self, meta, dataset_folder): + meta_file = os.path.join(dataset_folder, 'meta.json') + save_meta = copy.deepcopy(meta) + if 'local_work_dir' in meta: + save_meta.pop('local_work_dir') + if 'work_dir' in meta: + save_meta.pop('work_dir') + with FS.put_to(meta_file) as local_path: + json.dump(save_meta, open(local_path, 'w')) + return meta_file + + def construct_meta(self, cursor, file_list, dataset_folder, user_name): + ''' + { + "dataset_name": "xxxx", + "dataset_scale": 100, + "file_list": "xxxxx", # image_path#;#width#;#height#;#caption + "update_time": "", + "create_time": "" + } + ''' + train_csv = os.path.join(dataset_folder, 'train.csv') + train_csv = self.write_csv(file_list, train_csv, dataset_folder) + save_file_list = os.path.join(dataset_folder, 'file.csv') + save_file_list = self.write_file_list(file_list, save_file_list) + meta = { + 'dataset_name': user_name, + 'cursor': cursor, + 'file_list': file_list, + 'train_csv': train_csv, + 'save_file_list': save_file_list + } + self.save_meta(meta, dataset_folder) + return meta + + def load_from_list(self, save_file, dataset_folder, local_dataset_folder): + file_list = [] + images_folder = os.path.join(local_dataset_folder, 'images') + os.makedirs(images_folder, exist_ok=True) + with FS.get_from(save_file) as local_path: + all_remote_list, all_local_list = [], [] + all_save_list = [] + with open(local_path, 'r') as f: + for line in tqdm(f): + line = line.strip() + if line == '': + continue + try: + image_path, width, height, caption = line.split( + '#;#', 3) + except Exception: + try: + image_path, width, height, caption = line.split( + ',', 3) + except Exception: + raise gr.Error('列表只支持,或#;#作为分割符,四列分别为图像路径/宽/高/描述') + is_legal, new_path, prefix = self.find_prefix(image_path) + try: + int(width), int(height) + except Exception: + raise gr.Error(f'不合法的width({width}),height({height})') + + if not is_legal: + raise gr.Error( + f'路径不支持{image_path},应该为oss路径(oss://)或者省略前缀(xxx/xxx)' + ) + relative_path = os.path.join('images', + image_path.split('/')[-1]) + + all_remote_list.append(new_path) + all_local_list.append( + os.path.join(local_dataset_folder, relative_path)) + all_save_list.append( + os.path.join(dataset_folder, relative_path)) + file_list.append({ + 'image_path': + os.path.join(dataset_folder, relative_path), + 'relative_path': + relative_path, + 'width': + int(width), + 'height': + int(height), + 'caption': + caption, + 'prefix': + prefix, + 'edit_caption': + caption + }) + cache_file_list = [] + for idx, local_path in enumerate( + FS.get_batch_objects_from(all_remote_list)): + if local_path is None: + raise gr.Error(f'下载图像失败{all_remote_list[idx]}') + _ = FS.put_object_from_local_file(local_path, all_local_list[idx]) + cache_file_list.append(local_path) + + for local_path, target_path, flg in FS.put_batch_objects_to( + cache_file_list, all_save_list): + if not flg: + raise gr.Error(f'上传图像失败{local_path}') + if os.path.exists(local_path): + try: + os.remove(local_path) + except Exception: + pass + + return file_list + + def load_from_zip(self, save_file, data_folder, local_dataset_folder): + with FS.get_from(save_file) as local_path: + res = os.popen( + f"unzip -o '{local_path}' -d '{local_dataset_folder}'") + res = res.readlines() + if not os.path.exists(local_dataset_folder): + raise gr.Error(f'解压{save_file}失败{str(res)}') + file_folder = None + train_list = None + hit_dir = None + raw_list = [] + mac_osx = os.path.join(local_dataset_folder, '__MACOSX') + if os.path.exists(mac_osx): + res = os.popen(f"rm -rf '{mac_osx}'") + res = res.readlines() + for one_dir in FS.walk_dir(local_dataset_folder, recurse=False): + if one_dir.endswith('__MACOSX'): + res = os.popen(f"rm -rf '{one_dir}'") + res = res.readlines() + continue + if FS.isdir(one_dir): + sub_dir = FS.walk_dir(one_dir) + for one_s_dir in sub_dir: + if FS.isdir(one_s_dir) and one_s_dir.split( + one_dir)[1].replace('/', '') == 'images': + file_folder = one_s_dir + hit_dir = one_dir + if FS.isfile(one_s_dir) and one_s_dir.split( + one_dir)[1].replace('/', '') == 'train.csv': + train_list = one_s_dir + if file_folder is not None and train_list is not None: + break + if (one_s_dir.endswith('.jpg') + or one_s_dir.endswith('.jpeg') + or one_s_dir.endswith('.png') + or one_s_dir.endswith('.webp')): + raw_list.append(one_s_dir) + else: + if (one_dir.endswith('.jpg') or one_dir.endswith('.jpeg') + or one_dir.endswith('.png') + or one_dir.endswith('.webp')): + raw_list.append(one_dir) + + if file_folder is None and len(raw_list) < 1: + raise gr.Error( + "images folder or train.csv doesn't exists, or nothing exists in your zip" + ) + new_file_folder = f'{local_dataset_folder}/images' + os.makedirs(new_file_folder, exist_ok=True) + if file_folder is not None: + res = os.popen(f"mv '{file_folder}'/* '{new_file_folder}'") + res = res.readlines() + elif len(raw_list) > 0: + raw_list = list(set(raw_list)) + for img_id, cur_image in enumerate(raw_list): + _, surfix = os.path.splitext(cur_image) + try: + os.rename( + os.path.abspath(cur_image), + f'{new_file_folder}/{get_md5(cur_image)}{surfix}') + raw_list[img_id] = [ + os.path.join('images', + f'{get_md5(cur_image)}{surfix}'), + cur_image.split('/')[-1] + ] + except Exception as e: + print(e) + + if not os.path.exists(new_file_folder): + raise gr.Error(f'{str(res)}') + new_train_list = f'{local_dataset_folder}/train.csv' + if train_list is None or not os.path.exists(train_list): + with open(new_train_list, 'w') as f: + writer = csv.writer(f) + writer.writerow(['Target:FILE', 'Prompt']) + for cur_image, cur_prompt in raw_list: + writer.writerow([cur_image, cur_prompt]) + else: + res = os.popen(f"mv '{train_list}' '{new_train_list}'") + res = res.readlines() + if not os.path.exists(new_train_list): + raise gr.Error(f'{str(res)}') + res = os.popen(f"rm -rf '{hit_dir}'") + res = res.readlines() + file_list = self.load_train_csv(new_train_list, data_folder) + return file_list + + def get_image_meta(self, image): + img = Image.open(image) + return img.size + + def load_train_csv(self, file_path, data_folder): + base_folder = os.path.dirname(file_path) + file_list = [] + with open(file_path, 'r') as f: + reader = csv.reader(f) + for row in reader: + image_path, prompt = row[0], row[1] + if image_path == 'Target:FILE': + continue + local_image_path = os.path.join(base_folder, image_path) + w, h = self.get_image_meta(local_image_path) + file_list.append({ + 'image_path': + os.path.join(data_folder, image_path), + 'relative_path': + image_path, + 'width': + w, + 'height': + h, + 'caption': + prompt, + 'prefix': + '', + 'edit_caption': + prompt + }) + return file_list + + def find_prefix(self, file_path): + for k in FS._prefix_to_clients.keys(): + if file_path.startswith(k): + return True, file_path, '' + elif FS.exists(os.path.join(k, file_path)): + return True, os.path.join(k, file_path), '' + elif FS.exists(os.path.join(k, 'datasets', file_path)): + return True, os.path.join(k, 'datasets', file_path), 'datasets' + return False, None, None + + def del_prefix(self, file_path, prefix=''): + for k in FS._prefix_to_clients.keys(): + if file_path.startswith(k): + file_path = file_path.replace(k, '') + while file_path.startswith('/'): + file_path = file_path[1:] + if not prefix == '' and file_path.startswith(prefix): + file_path = file_path.split(prefix)[-1] + while file_path.startswith('/'): + file_path = file_path[1:] + return True, file_path + return False, file_path + + def load_history(self): + dataset_list = [] + for one_dir in self.dir_list: + if FS.isdir(one_dir): + meta_file = os.path.join(one_dir, 'meta.json') + if FS.exists(meta_file): + local_dataset_folder, _ = FS.map_to_local(one_dir) + local_dataset_folder = FS.get_dir_to_local_dir( + one_dir, local_dataset_folder) + meta_data = self.load_meta( + os.path.join(local_dataset_folder, 'meta.json')) + meta_data['local_work_dir'] = local_dataset_folder + meta_data['work_dir'] = one_dir + dataset_list.append(meta_data['dataset_name']) + self.meta_dict[meta_data['dataset_name']] = meta_data + return dataset_list + + def create_ui(self): + with gr.Box(): + gr.Markdown(self.components_name.user_direction) + with gr.Box(): + with gr.Row(): + with gr.Column(scale=1, min_width=0): + self.dataset_name = gr.Dropdown( + label=self.components_name.dataset_name, + choices=self.dataset_list, + interactive=True) + with gr.Column(scale=1, min_width=0): + self.refresh_dataset_name = gr.Button( + value=self.components_name.refresh_list_button) + self.btn_create_datasets = gr.Button( + value=self.components_name.btn_create_datasets) + self.btn_create_datasets_from_file = gr.Button( + value=self.components_name. + btn_create_datasets_from_file) + self.panel_state = gr.Checkbox(label='panel_state', + value=False, + visible=False) + with gr.Column(scale=2, min_width=0): + with gr.Row(equal_height=True): + with gr.Column(visible=False, min_width=0) as panel: + self.user_data_name = gr.Text( + label=self.components_name.user_data_name, + value='', + interactive=True) + self.user_data_name_state = gr.State(value='') + self.create_mode = gr.State(value=0) + with gr.Column(visible=False, + min_width=0) as file_panel: + self.file_path = gr.File( + label=self.components_name.zip_file, + min_width=0, + file_types=['.zip', '.txt', '.csv']) + self.file_path_url = gr.Text( + label=self.components_name.zip_file_url, + value='', + visible=False) + with gr.Column(visible=False, + min_width=0) as btn_panel: + self.random_data_button = gr.Button( + value=refresh_symbol) + self.confirm_data_button = gr.Button( + value=self.components_name.confirm_data_button) + with gr.Column(visible=False, + min_width=0) as modify_panel: + self.modify_data_button = gr.Button( + value=self.components_name.modify_data_button) + + self.dataset_panel = panel + self.btn_panel = btn_panel + self.file_panel = file_panel + self.modify_panel = modify_panel + + def set_callbacks(self, gallery_dataset, export_dataset): + def show_dataset_panel(): + return (gr.Column(visible=False), gr.Column(visible=True), + gr.Column(visible=True), + gr.Checkbox(value=False, visible=False), + gr.Text(value=get_random_dataset_name(), + interactive=True), 1) + + def show_file_panel(): + return (gr.Column(visible=True), gr.Column(visible=True), + gr.Column(visible=True), + gr.Checkbox(value=False, visible=False), + gr.Text(value=get_random_dataset_name(), interactive=True), + gr.File(value=None), gr.Text(value='', visible=False), 2) + + def get_random_dataset_name(): + data_name = 'name-version-{0:%Y%m%d_%H_%M_%S}'.format( + datetime.datetime.now()) + return data_name + + def refresh(): + return gr.Dropdown(value=self.dataset_list[-1] + if len(self.dataset_list) > 0 else '', + choices=self.dataset_list) + + self.refresh_dataset_name.click(refresh, outputs=[self.dataset_name]) + + def confirm_create_dataset(user_name, create_mode, file_url, file_path, + panel_state): + if user_name.strip() == '' or ' ' in user_name or '/' in user_name: + raise gr.Error(self.components_name.illegal_data_name_err1) + + if len(user_name.split('-')) < 3: + raise gr.Error(self.components_name.illegal_data_name_err2) + + if '.' in user_name: + raise gr.Error(self.components_name.illegal_data_name_err3) + + if not file_url.strip() == '' and file_path is not None: + raise gr.Error(self.components_name.illegal_data_name_err4) + if create_mode == 1 and not file_url.strip() == '': + file_name, surfix = os.path.splitext(file_url.split('?')[0]) + save_file = os.path.join(self.work_dir, f'{user_name}{surfix}') + with FS.put_to(save_file) as local_path: + res = os.popen(f"wget '{file_url}' -O '{local_path}'") + res.readlines() + if not FS.exists(save_file): + raise gr.Error( + f'{self.components_name.illegal_data_err1} {str(res)}') + elif create_mode == 2 and file_path is not None and file_path.name: + self.cache_file[user_name] = { + 'file_name': file_path.name, + 'surfix': os.path.splitext(file_path.name)[-1] + } + cache_file = self.cache_file.pop(user_name) + surfix = cache_file['surfix'] + ori_file = cache_file['file_name'] + save_file = os.path.join(self.work_dir, f'{user_name}{surfix}') + with FS.put_to(save_file) as local_path: + res = os.popen(f"cp '{ori_file}' '{local_path}'") + res = res.readlines() + if not FS.exists(save_file): + raise gr.Error( + f'{self.components_name.illegal_data_err1}{str(res)}') + else: + surfix = None + # untar file or create blank dataset + dataset_folder = os.path.join(self.work_dir, user_name) + local_dataset_folder, _ = FS.map_to_local(dataset_folder) + if surfix == '.zip': + file_list = self.load_from_zip(save_file, dataset_folder, + local_dataset_folder) + elif surfix in ['.txt', '.csv']: + file_list = self.load_from_list(save_file, dataset_folder, + local_dataset_folder) + elif surfix is None: + file_list = [] + else: + raise gr.Error( + f'{self.components_name.illegal_data_err2} {surfix}') + is_flag = FS.put_dir_from_local_dir(local_dataset_folder, + dataset_folder) + if not is_flag: + raise gr.Error(f'{self.components_name.illegal_data_err3}') + + cursor = 0 if len(file_list) > 0 else -1 + meta = self.construct_meta(cursor, file_list, dataset_folder, + user_name) + + meta['local_work_dir'] = local_dataset_folder + meta['work_dir'] = dataset_folder + + self.meta_dict[meta['dataset_name']] = meta + self.dataset_list.append(meta['dataset_name']) + return ( + gr.Checkbox(value=True, visible=False), + gr.Dropdown(value=user_name, choices=self.dataset_list), + ) + + def clear_file(): + return gr.Text(visible=True) + + # Click Create + self.btn_create_datasets.click(show_dataset_panel, [], [ + self.file_panel, self.dataset_panel, self.btn_panel, + self.panel_state, self.user_data_name, self.create_mode + ]) + + self.btn_create_datasets_from_file.click(show_file_panel, [], [ + self.file_panel, self.dataset_panel, self.btn_panel, + self.panel_state, self.user_data_name, self.file_path, + self.file_path_url, self.create_mode + ]) + + # Click Refresh + self.random_data_button.click(get_random_dataset_name, [], + [self.user_data_name]) + + self.file_path.clear(clear_file, outputs=[self.file_path_url]) + + # Click Confirm + self.confirm_data_button.click(confirm_create_dataset, [ + self.user_data_name, self.create_mode, self.file_path_url, + self.file_path, self.panel_state + ], [self.panel_state, self.dataset_name]) + + def show_edit_panel(panel_state, data_name): + if panel_state: + return (gr.Row(visible=True), gr.Row(visible=True), + gr.Row(visible=True), gr.Column(visible=True), + gr.Column(visible=False), gr.Column(visible=False), + data_name) + else: + return (gr.Row(visible=False), gr.Row(visible=False), + gr.Row(visible=False), gr.Column(visible=False), + gr.Column(), gr.Column(), data_name) + + self.panel_state.change( + show_edit_panel, [self.panel_state, self.dataset_name], [ + gallery_dataset.gallery_panel, gallery_dataset.upload_panel, + export_dataset.export_panel, self.modify_panel, + self.file_panel, self.btn_panel, self.user_data_name_state + ]) + + def modify_data_name(user_name, prev_data_name): + print( + f'Current file name {prev_data_name}, new file name {user_name}.' + ) + if user_name.strip() == '' or ' ' in user_name or '/' in user_name: + raise gr.Error(self.components_name.illegal_data_name_err1) + if len(user_name.split('-')) < 3: + raise gr.Error(self.components_name.illegal_data_name_err2) + if '.' in user_name: + raise gr.Error(self.components_name.illegal_data_name_err3) + if user_name != prev_data_name: + if prev_data_name in self.meta_dict: + ori_meta = self.meta_dict[prev_data_name] + dataset_folder = os.path.join(self.work_dir, user_name) + local_dataset_folder, _ = FS.map_to_local(dataset_folder) + os.makedirs(local_dataset_folder, exist_ok=True) + is_flag = FS.get_dir_to_local_dir(ori_meta['work_dir'], + local_dataset_folder) + file_list = ori_meta['file_list'] + is_flag = FS.put_dir_from_local_dir( + local_dataset_folder, dataset_folder) + if not is_flag: + raise gr.Error(self.components_name.illegal_data_err3) + is_flag = FS.put_dir_from_local_dir( + local_dataset_folder, dataset_folder) + if not is_flag: + raise gr.Error(self.components_name.illegal_data_err3) + cursor = ori_meta['cursor'] + meta = self.construct_meta(cursor, file_list, + dataset_folder, user_name) + meta['local_work_dir'] = local_dataset_folder + meta['work_dir'] = dataset_folder + + if prev_data_name in self.dataset_list: + self.dataset_list.remove(prev_data_name) + self.dataset_list.append(user_name) + self.meta_dict.pop(prev_data_name) + self.meta_dict[user_name] = meta + _ = FS.delete_object( + os.path.join(ori_meta['work_dir'], 'meta.json')) + _ = FS.delete_object( + os.path.join(ori_meta['local_work_dir'], 'meta.json')) + else: + raise gr.Error(self.components_name.modify_data_name_err1) + return user_name, gr.Dropdown( + choices=self.dataset_list, + value=user_name, + select_index=len(self.dataset_list) - 1) + else: + return user_name, gr.Dropdown() + + self.modify_data_button.click( + modify_data_name, + inputs=[self.user_data_name, self.user_data_name_state], + outputs=[self.user_data_name_state, self.dataset_name]) + + def dataset_change(user_name): + if user_name is None or user_name == '': + raise gr.Error(self.components_name.illegal_data_name_err5 + + f'{user_name}') + if user_name not in self.meta_dict: + raise gr.Error(self.components_name.refresh_data_list_info1) + return (gr.Column(visible=True), gr.Column(visible=False), + gr.Checkbox(value=True, visible=False), + gr.Text(value=user_name, + interactive=True), gr.Text(value=user_name)) + + self.dataset_name.change(dataset_change, + inputs=[self.dataset_name], + outputs=[ + self.dataset_panel, self.file_panel, + self.panel_state, self.user_data_name, + gallery_dataset.gallery_state + ]) diff --git a/scepter/studio/preprocess/caption_editor_ui/dataset_gallery_ui.py b/scepter/studio/preprocess/caption_editor_ui/dataset_gallery_ui.py new file mode 100644 index 0000000..d723f73 --- /dev/null +++ b/scepter/studio/preprocess/caption_editor_ui/dataset_gallery_ui.py @@ -0,0 +1,288 @@ +# -*- coding: utf-8 -*- +from __future__ import annotations + +import os.path + +import gradio as gr +import imagehash + +from scepter.modules.utils.file_system import FS +from scepter.studio.preprocess.caption_editor_ui.component_names import \ + DatasetGalleryUIName +from scepter.studio.preprocess.caption_editor_ui.create_dataset_ui import \ + CreateDatasetUI +from scepter.studio.utils.uibase import UIBase + + +class DatasetGalleryUI(UIBase): + def __init__(self, cfg, is_debug=False, language='en'): + self.selected_path = '' + self.selected_index = -1 + self.selected_index_prev = -1 + self.component_names = DatasetGalleryUIName(language) + + def create_ui(self): + with gr.Row(variant='panel', visible=False, + equal_height=True) as upload_panel: + with gr.Column(): + self.upload_image = gr.Image( + label=self.component_names.upload_image, + tool='sketch', + type='pil') + with gr.Column(min_width=80): + self.caption = gr.Textbox( + label=self.component_names.image_caption, + placeholder='', + value='', + lines=5) + self.upload_button = gr.Button( + value=self.component_names.upload_image_btn) + + with gr.Row(visible=False, equal_height=True) as gallery_panel: + with gr.Row(visible=False): + # self.gallery_state = gr.Checkbox(label='gallery_state', value=False, visible=False) + self.cbg_hidden_dataset_filter = gr.CheckboxGroup( + label='Dataset Filter') + self.nb_hidden_dataset_filter_apply = gr.Number( + label='Filter Apply', value=-1) + self.btn_hidden_set_index = gr.Button( + elem_id='dataset_tag_editor_btn_hidden_set_index') + self.nb_hidden_image_index = gr.Number(value=None, + label='hidden_idx_next') + self.nb_hidden_image_index_prev = gr.Number( + value=None, label='hidden_idx_prev') + self.gallery_state = gr.Text(label='gallery_state', + value='', + visible=False) + + # with gr.Row(variant='panel', equal_height=True): + with gr.Column(scale=1): + self.gl_dataset_images = gr.Gallery( + label=self.component_names.dataset_images, + elem_id='dataset_tag_editor_dataset_gallery', + columns=4) + with gr.Column(scale=1): + with gr.Row(equal_height=True): + self.info = gr.Text(value='', + label=None, + show_label=False, + interactive=False) + with gr.Row(equal_height=True): + with gr.Column(scale=1, min_width=0): + self.ori_caption = gr.Textbox( + label=self.component_names.ori_caption, + placeholder='', + value='', + lines=10, + autoscroll=False, + interactive=False) + with gr.Column(scale=1, min_width=0): + self.edit_caption = gr.Textbox( + label=self.component_names.edit_caption, + placeholder='', + value='', + lines=10, + autoscroll=False, + interactive=True) + with gr.Row(equal_height=True): + self.modify_button = gr.Button( + value=self.component_names.btn_modify) + with gr.Row(equal_height=True): + self.delete_button = gr.Button( + value=self.component_names.btn_delete) + + self.upload_panel = upload_panel + self.gallery_panel = gallery_panel + + def set_callbacks(self, create_dataset: CreateDatasetUI): + def change_gallery(dataset_name): + meta_data = create_dataset.meta_dict[dataset_name] + if len(meta_data['file_list']) > 0: + cursor = create_dataset.meta_dict[dataset_name]['cursor'] + else: + cursor = -1 + image_list = [ + os.path.join(meta_data['local_work_dir'], v['relative_path']) + for v in meta_data['file_list'] + ] + if cursor >= 0: + return gr.Gallery(label=dataset_name, + value=image_list, + selected_index=cursor) + else: + return gr.Gallery(label=dataset_name, + value=image_list, + selected_index=None) + + self.gallery_state.change(change_gallery, + inputs=[create_dataset.user_data_name], + outputs=[self.gl_dataset_images]) + + def select_image(dataset_name, evt: gr.SelectData): + meta_data = create_dataset.meta_dict[dataset_name] + if len(meta_data['file_list']) > 0: + current_info = meta_data['file_list'][evt.index] + create_dataset.meta_dict[dataset_name]['cursor'] = evt.index + cursor = evt.index + else: + current_info = {'caption': ''} + cursor = -1 + + all_number = len(meta_data['file_list']) + if cursor >= 0: + return (gr.Gallery(selected_index=cursor), + gr.Textbox(value=current_info['caption']), + gr.Textbox(value=current_info['edit_caption']), + gr.Text(value=f'{cursor+1}/{all_number}')) + else: + return (gr.Gallery(value=[], selected_index=None), + gr.Textbox(value=current_info['caption']), + gr.Textbox(value=current_info['edit_caption']), + gr.Text(value=f'{cursor + 1}/{all_number}')) + + def change_image(dataset_name): + meta_data = create_dataset.meta_dict[dataset_name] + cursor = create_dataset.meta_dict[dataset_name]['cursor'] + if cursor >= 0: + current_info = meta_data['file_list'][cursor] + else: + current_info = {'caption': '', 'edit_caption': ''} + all_number = len(meta_data['file_list']) + return (gr.Textbox(value=current_info['caption']), + gr.Textbox(value=current_info['edit_caption']), + gr.Text(value=f'{cursor+1}/{all_number}')) + + def change_caption(dataset_name, edit_caption): + cursor = create_dataset.meta_dict[dataset_name]['cursor'] + create_dataset.meta_dict[dataset_name]['file_list'][cursor][ + 'caption'] = edit_caption + create_dataset.save_meta( + create_dataset.meta_dict[dataset_name], + create_dataset.meta_dict[dataset_name]['work_dir']) + return gr.Textbox(value=edit_caption) + + self.gl_dataset_images.select(select_image, + inputs=[create_dataset.user_data_name], + outputs=[ + self.gl_dataset_images, + self.ori_caption, self.edit_caption, + self.info + ]) + self.gl_dataset_images.change( + change_image, + inputs=[create_dataset.user_data_name], + outputs=[self.ori_caption, self.edit_caption, self.info]) + + self.modify_button.click( + change_caption, + inputs=[create_dataset.user_data_name, self.edit_caption], + outputs=[self.ori_caption]) + + def delete_file(dataset_name): + cursor = create_dataset.meta_dict[dataset_name]['cursor'] + if len(create_dataset.meta_dict[dataset_name]['file_list']) < 1: + raise gr.Error(self.component_names.delete_err1) + current_file = create_dataset.meta_dict[dataset_name][ + 'file_list'].pop(cursor) + local_file = os.path.join( + create_dataset.meta_dict[dataset_name]['local_work_dir'], + current_file['relative_path']) + try: + os.remove(local_file) + except Exception: + print(f'remove file {local_file} error') + if cursor >= len( + create_dataset.meta_dict[dataset_name]['file_list']): + cursor = 0 + create_dataset.meta_dict[dataset_name]['cursor'] = cursor + create_dataset.save_meta( + create_dataset.meta_dict[dataset_name], + create_dataset.meta_dict[dataset_name]['work_dir']) + current_info = create_dataset.meta_dict[dataset_name]['file_list'][ + cursor] + image_list = [ + os.path.join( + create_dataset.meta_dict[dataset_name]['local_work_dir'], + v['relative_path']) + for v in create_dataset.meta_dict[dataset_name]['file_list'] + ] + return (gr.Gallery(value=image_list, selected_index=cursor), + gr.Textbox(value=current_info['caption']), + gr.Textbox(value=current_info['caption'] + if current_info['edit_caption'] == + '' else current_info['edit_caption']), + gr.Text(value=f'{cursor + 1}/{len(image_list)}')) + + self.delete_button.click(delete_file, + inputs=[create_dataset.user_data_name], + outputs=[ + self.gl_dataset_images, self.ori_caption, + self.edit_caption, self.info + ]) + + def add_file(dataset_name, upload_image, caption): + if 'image' in upload_image: + image = upload_image['image'] + + else: + image = upload_image + w, h = image.size + meta = create_dataset.meta_dict[dataset_name] + local_work_dir = meta['local_work_dir'] + work_dir = meta['work_dir'] + + save_folder = os.path.join(local_work_dir, 'images') + os.makedirs(save_folder, exist_ok=True) + + relative_path = os.path.join('images', + f'{imagehash.phash(image)}.png') + image_path = os.path.join(work_dir, relative_path) + + local_image_path = os.path.join(local_work_dir, relative_path) + with FS.put_to(image_path) as local_path: + image.save(local_path) + + image.save(local_image_path) + + meta['file_list'].append({ + 'image_path': image_path, + 'relative_path': relative_path, + 'width': w, + 'height': h, + 'caption': caption, + 'prefix': '', + 'edit_caption': caption + }) + + meta['cursor'] = len(meta['file_list']) - 1 + create_dataset.meta_dict[dataset_name] = meta + image_list = [ + os.path.join( + create_dataset.meta_dict[dataset_name]['local_work_dir'], + v['relative_path']) + for v in create_dataset.meta_dict[dataset_name]['file_list'] + ] + return (gr.Gallery(value=image_list, + selected_index=meta['cursor']), + gr.Textbox(value=caption), gr.Textbox(value=caption), + gr.Text(value=f"{meta['cursor'] + 1}/{len(image_list)}")) + + self.upload_button.click(add_file, + inputs=[ + create_dataset.user_data_name, + self.upload_image, self.caption + ], + outputs=[ + self.gl_dataset_images, self.ori_caption, + self.edit_caption, self.info + ]) + + def edit_caption_change(dataset_name, edit_caption): + meta = create_dataset.meta_dict[dataset_name] + cursor = meta['cursor'] + if cursor >= 0: + meta['file_list'][cursor]['edit_caption'] = edit_caption + + self.edit_caption.change( + edit_caption_change, + inputs=[create_dataset.user_data_name, self.edit_caption]) diff --git a/scepter/studio/preprocess/caption_editor_ui/export_dataset_ui.py b/scepter/studio/preprocess/caption_editor_ui/export_dataset_ui.py new file mode 100644 index 0000000..24abb61 --- /dev/null +++ b/scepter/studio/preprocess/caption_editor_ui/export_dataset_ui.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +from __future__ import annotations + +import os +import urllib.parse as parse + +import gradio as gr + +from scepter.modules.utils.file_system import FS +from scepter.studio.preprocess.caption_editor_ui.component_names import \ + ExportDatasetUIName +from scepter.studio.utils.uibase import UIBase + + +class ExportDatasetUI(UIBase): + def __init__(self, cfg, is_debug=False, language='en'): + self.dataset_name = '' + self.work_dir = cfg.WORK_DIR + self.export_folder = os.path.join(self.work_dir, cfg.EXPORT_DIR) + self.component_names = ExportDatasetUIName(language) + + def create_ui(self): + with gr.Row(variant='panel', visible=False, + equal_height=True) as export_panel: + self.data_state = gr.State(value=False) + with gr.Column(scale=1, min_width=0): + self.export_to_zip = gr.Button( + value=self.component_names.btn_export_zip) + self.export_url = gr.File( + label=self.component_names.export_file, + visible=False, + value=None, + interactive=False, + show_label=True) + with gr.Column(scale=1, min_width=0): + self.go_to_train = gr.Button( + value=self.component_names.go_to_train, size='lg') + self.export_panel = export_panel + + def set_callbacks(self, create_dataset, manager): + def export_zip(dataset_name): + meta = create_dataset.meta_dict[dataset_name] + work_dir = meta['work_dir'] + local_work_dir = meta['local_work_dir'] + train_csv = os.path.join(work_dir, 'train.csv') + if len(meta['file_list']) < 1: + raise gr.Error(self.component_names.export_err1) + train_csv = create_dataset.write_csv(meta['file_list'], train_csv, + work_dir) + _ = FS.get_from(train_csv, os.path.join(local_work_dir, + 'train.csv')) + save_file_list = work_dir + '_file.csv' + save_file_list = create_dataset.write_file_list( + meta['file_list'], save_file_list) + _ = FS.get_from(save_file_list, + os.path.join(local_work_dir, 'file.csv')) + zip_path = os.path.join(self.export_folder, f'{dataset_name}.zip') + with FS.put_to(zip_path) as local_zip: + res = os.popen( + f"cd '{local_work_dir}' && mkdir -p '{dataset_name}' " + f"&& cp -rf images '{dataset_name}/images' " + f"&& cp -rf train.csv '{dataset_name}/train.csv' " + f"&& zip -r '{os.path.abspath(local_zip)}' '{dataset_name}'/* " + f"&& rm -rf '{dataset_name}'") + print(res.readlines()) + + if not FS.exists(zip_path): + raise gr.Error(self.component_names.export_zip_err1) + create_dataset.save_meta(meta, work_dir) + local_zip = FS.get_from(zip_path) + return gr.File(value=local_zip, visible=True) + + self.export_to_zip.click(export_zip, + inputs=[create_dataset.user_data_name], + outputs=[self.export_url]) + + def export_csv(dataset_name): + meta = create_dataset.meta_dict[dataset_name] + work_dir = meta['work_dir'] + local_work_dir = meta['local_work_dir'] + train_csv = os.path.join(work_dir, 'train.csv') + if len(meta['file_list']) < 1: + raise gr.Error(self.component_names.export_err1) + train_csv = create_dataset.write_csv(meta['file_list'], train_csv, + work_dir) + _ = FS.get_from(train_csv, os.path.join(local_work_dir, + 'train.csv')) + save_file_list = os.path.join(work_dir, 'file.csv') + save_file_list = create_dataset.write_file_list( + meta['file_list'], save_file_list) + local_file_csv = FS.get_from( + save_file_list, os.path.join(local_work_dir, 'file.csv')) + create_dataset.save_meta(meta, work_dir) + is_flag = FS.put_object_from_local_file( + local_file_csv, + os.path.join(self.export_folder, dataset_name + '_file.csv')) + if not is_flag: + raise gr.Error(self.component_names.upload_err1) + list_url = FS.get_url(os.path.join(self.export_folder, + dataset_name + '_file.csv'), + set_public=True) + list_url = parse.unquote(list_url) + if 'wulanchabu' in list_url: + list_url = list_url.replace( + '.cn-wulanchabu.oss-internal.aliyun-inc.', + '.oss-cn-wulanchabu.aliyuncs.') + else: + list_url = list_url.replace('.oss-internal.aliyun-inc.', + '.oss.aliyuncs.') + if not list_url.split('/')[-1] == dataset_name + '_file.csv': + list_url = os.path.join(os.path.dirname(list_url), + dataset_name + '_file.csv') + return gr.Text(value=list_url) + + # self.export_to_list.click(export_csv, + # inputs=[create_dataset.user_data_name], + # outputs=[self.export_url]) + + def go_to_train(dataset_name): + meta = create_dataset.meta_dict[dataset_name] + work_dir = meta['work_dir'] + local_work_dir = meta['local_work_dir'] + train_csv = os.path.join(work_dir, 'train.csv') + if len(meta['file_list']) < 1: + raise gr.Error(self.component_names.export_err1) + train_csv = create_dataset.write_csv(meta['file_list'], train_csv, + work_dir) + _ = FS.get_from(train_csv, os.path.join(local_work_dir, + 'train.csv')) + save_file_list = work_dir + '_file.csv' + _ = create_dataset.write_file_list(meta['file_list'], + save_file_list) + return (gr.Tabs(selected='self_train'), + gr.Textbox(value=os.path.abspath(local_work_dir))) + + self.go_to_train.click( + go_to_train, + inputs=[create_dataset.user_data_name], + outputs=[manager.tabs, manager.self_train.trainer_ui.ms_data_name]) diff --git a/scepter/studio/preprocess/preprocess.py b/scepter/studio/preprocess/preprocess.py new file mode 100644 index 0000000..27dbbe2 --- /dev/null +++ b/scepter/studio/preprocess/preprocess.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +import os.path + +import gradio as gr + +from scepter.modules.utils.config import Config +from scepter.modules.utils.file_system import FS +from scepter.studio.preprocess.caption_editor_ui.create_dataset_ui import \ + CreateDatasetUI +from scepter.studio.preprocess.caption_editor_ui.dataset_gallery_ui import \ + DatasetGalleryUI +from scepter.studio.preprocess.caption_editor_ui.export_dataset_ui import \ + ExportDatasetUI +from scepter.studio.utils.env import init_env + + +class PreprocessUI(): + def __init__(self, + cfg_general_file, + is_debug=False, + language='en', + root_work_dir='./'): + cfg_general = Config(cfg_file=cfg_general_file) + + cfg_general.WORK_DIR = os.path.join(root_work_dir, + cfg_general.WORK_DIR) + if not FS.exists(cfg_general.WORK_DIR): + FS.make_dir(cfg_general.WORK_DIR) + + cfg_general = init_env(cfg_general) + self.create_dataset = CreateDatasetUI.get_instance(cfg_general, + is_debug=is_debug, + language=language) + self.dataset_gallery = DatasetGalleryUI.get_instance(cfg_general, + is_debug=is_debug, + language=language) + self.export_dataset = ExportDatasetUI.get_instance(cfg_general, + is_debug=is_debug, + language=language) + + def create_ui(self): + self.create_dataset.create_ui() + self.dataset_gallery.create_ui() + self.export_dataset.create_ui() + + def set_callbacks(self, manager): + self.create_dataset.set_callbacks(self.dataset_gallery, + self.export_dataset) + self.dataset_gallery.set_callbacks(self.create_dataset) + self.export_dataset.set_callbacks(self.create_dataset, manager) + + +if __name__ == '__main__': + pre_ui = PreprocessUI('scepter/methods/studio/preprocess/preprocess.yaml', + root_work_dir='./cache') + with gr.Blocks() as demo: + gr.Markdown('

SCEPTER Preprocess

') + with gr.Tabs(elem_id='tabs') as tabs: + with gr.TabItem('editor', id=1, elem_id=f'tab_{1}'): + pre_ui.create_ui() + pre_ui.set_callbacks(None) + demo.queue(status_update_rate=1).launch(show_error=True, + debug=True, + enable_queue=True) diff --git a/scepter/studio/self_train/__init__.py b/scepter/studio/self_train/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/studio/self_train/scripts/__init__.py b/scepter/studio/self_train/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/studio/self_train/scripts/run_task.py b/scepter/studio/self_train/scripts/run_task.py new file mode 100644 index 0000000..c6ad59d --- /dev/null +++ b/scepter/studio/self_train/scripts/run_task.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +import argparse +import os + +import cv2 +import numpy as np +import torch + +from scepter.modules.solver.hooks.checkpoint import CheckpointHook +from scepter.modules.solver.registry import SOLVERS +from scepter.modules.utils.config import Config +from scepter.modules.utils.distribute import we +from scepter.modules.utils.file_system import FS +from scepter.modules.utils.logger import get_logger + + +def run_task(cfg): + # torch.cuda.set_per_process_memory_fraction(0.4, we.device_id) + # torch.cuda.empty_cache() + std_logger = get_logger(name='scepter') + std_logger.info(f'Pytorch version: {torch.__version__}') + # std_logger.info(f"Os environment: {os.environ}") + if cfg.args.stage == 'train': + solver = SOLVERS.build(cfg.SOLVER, logger=std_logger) + save_config(cfg) + solver.set_up_pre() + solver.set_up() + ori_steps = solver.max_steps + if 'train' in solver.datas: + dataset = solver.datas['train'].dataset + if hasattr(dataset, 'real_number'): + solver.max_steps = int( + cfg.SOLVER.MAX_EPOCHS * dataset.real_number / + (solver.datas['train'].batch_size * we.world_size)) + std_logger.info( + f'max step is changed from {ori_steps} to {solver.max_steps} ' + f'according to the setting epoches {cfg.SOLVER.MAX_EPOCHS} ' + f'and dataset size {dataset.real_number}') + if 'train' in solver.hooks_dict: + for hook in solver.hooks_dict['train']: + if isinstance(hook, CheckpointHook): + ori_interval = hook.interval + hook.interval = int(hook.interval * + solver.max_steps / + cfg.SOLVER.MAX_EPOCHS) + std_logger.info( + f'checkpoint save interval is changed from {ori_interval} ' + f'to {hook.interval} according to the setting epoches ' + f'interval {ori_interval}') + # size 为无限的时候,使用默认值。 + solver.solve() + + +def save_image(image, save_path, backend='cv2'): + if backend == 'cv2': + image = image.copy() + cv2.cvtColor(image, cv2.COLOR_RGB2BGR, image) + cv2.imwrite(save_path, image) + + +def concatenate_images(images): + heights = [img.shape[0] for img in images] + max_width = sum([img.shape[1] for img in images]) + + concatenated_image = np.zeros((max(heights), max_width, 3), dtype=np.uint8) + x_offset = 0 + for img in images: + concatenated_image[0:img.shape[0], + x_offset:x_offset + img.shape[1], :] = img + x_offset += img.shape[1] + return concatenated_image + + +def save_config(cfg): + from scepter.modules.utils.distribute import get_dist_info + rank, _ = get_dist_info() + if rank == 0: + config_path = os.path.join(cfg.SOLVER.WORK_DIR, + cfg.args.cfg_file.split('/')[-1]) + with FS.put_to(config_path) as local_config_path: + with open(local_config_path, 'w') as f_out: + f_out.write(cfg.dump()) + + +def update_config(cfg): + if cfg.args.work_dir and cfg.args.work_dir != '': + cfg.SOLVER.WORK_DIR = cfg.args.work_dir + return cfg + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description='Argparser for Cate process:\n') + parser.add_argument( + '--stage', + dest='stage', + help='Running stage!', + default='train', + choices=['train', 'inference', 'upsampler_inference', 'control']) + parser.add_argument('--base_model', + dest='base_model', + help='Base model name!', + default='sd') + parser.add_argument( + '--prompt', + dest='prompt', + help='Prompt sentence!', + default='a woman is walking on the street in a rainy day.') + parser.add_argument('--n_prompt', + dest='n_prompt', + help='Add Prompt sentence!', + default='') + parser.add_argument('--image', + dest='image', + help='Image to be upsampled!', + default='') + parser.add_argument('--num_samples', + dest='num_samples', + help="Output image's number!", + default=4, + type=int) + parser.add_argument('--sampler', + dest='sampler', + help='sampler', + default='ddim', + type=str) + parser.add_argument('--sample_steps', + dest='sample_steps', + help='sample_steps', + default=50, + type=int) + parser.add_argument('--inference_resolution', + dest='inference_resolution', + help='inference resolution', + default=1024, + type=int) + parser.add_argument('--seed', + dest='seed', + help='seed', + default=2023, + type=int) + parser.add_argument('--save_folder', + dest='save_folder', + help="Output image's save folder!", + default='test_images') + parser.add_argument('--pretrained_model', + dest='pretrained_model', + help='The pretrained model for our network!', + default='') + parser.add_argument('--learning_rate', + dest='learning_rate', + help='The learning rate for our network!', + default=None) + parser.add_argument('--max_steps', + dest='max_steps', + help='The max steps for our network!', + default=None) + parser.add_argument('--control_mode', + dest='control_mode', + help='', + default=None) + parser.add_argument('--work_dir', dest='work_dir', help='', default=None) + cfg = Config(load=True, parser_ins=parser) + cfg = update_config(cfg) + we.init_env(cfg, logger=None, fn=run_task) diff --git a/scepter/studio/self_train/self_train.py b/scepter/studio/self_train/self_train.py new file mode 100644 index 0000000..9465f8a --- /dev/null +++ b/scepter/studio/self_train/self_train.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +import os + +import gradio as gr + +import scepter +from scepter.modules.utils.config import Config +from scepter.modules.utils.file_system import FS +from scepter.studio.self_train.self_train_ui.inference_ui import InferenceUI +from scepter.studio.self_train.self_train_ui.trainer_ui import TrainerUI +from scepter.studio.self_train.utils.config_parser import get_all_config +from scepter.studio.utils.env import init_env + + +class SelfTrainUI(): + def __init__(self, + cfg_general_file, + is_debug=False, + language='en', + root_work_dir='./'): + cfg_general = Config(cfg_file=cfg_general_file) + + BASE_CFG_VALUE = get_all_config(os.path.dirname(cfg_general_file), + global_meta=cfg_general) + + cfg_general.WORK_DIR = os.path.join(root_work_dir, + cfg_general.WORK_DIR) + if not FS.exists(cfg_general.WORK_DIR): + FS.make_dir(cfg_general.WORK_DIR) + cfg_general = init_env(cfg_general) + + self.trainer_ui = TrainerUI(cfg_general, + BASE_CFG_VALUE, + is_debug=is_debug, + language=language) + self.inference_ui = InferenceUI(cfg_general, + BASE_CFG_VALUE, + is_debug=is_debug, + language=language) + + def create_ui(self): + with gr.Row(): + self.trainer_ui.create_ui() + with gr.Row(): + self.inference_ui.create_ui() + + def set_callbacks(self, manager): + self.trainer_ui.set_callbacks(self.inference_ui) + self.inference_ui.set_callbacks(self.trainer_ui, manager) + + +if __name__ == '__main__': + st_ins = SelfTrainUI(os.path.join( + scepter.dirname, 'scepter/methods/studio/self_train/self_train.yaml'), + is_debug=True, + language='zh', + root_work_dir='./cache') + with gr.Blocks() as demo: + gr.Markdown('

SCEPTER SELF TRAIN

') + with gr.Tabs(elem_id='tabs') as tabs: + with gr.TabItem('editor', id=1, elem_id=f'tab_{1}'): + st_ins.create_ui() + st_ins.set_callbacks() + demo.queue(status_update_rate=1).launch(show_error=True, + debug=True, + enable_queue=True) diff --git a/scepter/studio/self_train/self_train_ui/__init__.py b/scepter/studio/self_train/self_train_ui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/studio/self_train/self_train_ui/component_names.py b/scepter/studio/self_train/self_train_ui/component_names.py new file mode 100644 index 0000000..4b61343 --- /dev/null +++ b/scepter/studio/self_train/self_train_ui/component_names.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +# For dataset manager +class InferenceUIName(): + def __init__(self, language='en'): + if language == 'en': + self.output_model_block = 'Model Output' + self.output_model_name = 'Output Model Name' + self.test_prompt = 'Test Prompt' + self.test_prefix = 'Test Prefix' + self.test_n_prompt = 'Negative Prompt' + self.sampler = 'Sampler' + self.num_inference_steps = 'Sampling Step Length' + self.inference_num = 'Number of Inferences' + self.generator_seed = 'Sampling Seed' + self.tuner_method = 'Tuning Method' + self.inference_resolution = 'Inference Resolution' + self.output_image = 'Output Result' + self.display_button = 'Infer' + self.extra_model_gtxt = 'Extra Model' + self.extra_model_gbtn = 'Add Model' + self.refresh_model_gbtn = 'Refresh Model' + self.go_to_inference = 'Go to inference' + # Error or Warning + self.inference_err1 = 'Inference failed, please try again.' + self.inference_err2 = 'Test prompt is empty.' + self.inference_err3 = "Doesn't surpport this base model" + self.inference_err4 = "This model maybe not finish training, because model doesn't exist." + + elif language == 'zh': + self.output_model_block = '模型产出' + self.output_model_name = '产出模型名称' + self.test_prompt = '测试提示词' + self.test_prefix = '测试前缀' + self.test_n_prompt = '负向提示词' + self.sampler = '采样器' + self.num_inference_steps = '采样步长' + self.inference_num = '推理数' + self.generator_seed = '采样种子' + self.tuner_method = '训练方式' + self.inference_resolution = '推理分辨率' + self.output_image = '输出结果' + self.display_button = '推理' + self.extra_model_gtxt = '额外模型' + self.extra_model_gbtn = '添加模型' + self.refresh_model_gbtn = '刷新模型' + # Error or Warning + self.inference_err1 = '推理失败,请重试。' + self.inference_err2 = '测试提示词为空。' + self.inference_err3 = '不支持的基础模型' + self.go_to_inference = '使用模型' + self.inference_err4 = '模型可能没有训练完成或者模型不存在' + + +class TrainerUIName(): + def __init__(self, language='en'): + if language == 'en': + self.user_direction = ''' + ### User Guide + - Data: Select the template data from Examples, or prepare your custom data + for upload according to the format of the example dog.zip package. + - Parameters: You can try modifying the related parameters. + - Training: Click on [Start Training]. + - Testing: After completing the training, click [Go to inference ]. + - Note: Timeouts may cause the connection to disconnect (an Error may occur). + After waiting for the time when the training is likely to be almost complete, + refresh the interface and then click [Refresh Model] at the bottom of the page. + The trained model should appear in the [Output Model Name] if training was successful; + if not, the training may be incomplete or have failed. + - zip example: https://modelscope.cn/api/v1/models/damo/scepter/repo?Revision=master&FilePath=datasets/3D_example_csv.zip + - For processing and training with large-scale data, it is recommended to use the command line. + ''' # noqa + self.data_type_choices = ['Dataset zip', 'MaaS Dataset'] + self.data_type_value = 'Dataset zip' + self.data_type_name = 'Data Source' + self.ms_data_name_place_hold = 'Supports MaaS dataset/local/HTTP Zip package' + self.ms_data_space = 'ModelScope Space' + self.ms_data_subname = 'MaaS Dataset - Subset' + self.training_block = 'Training Parameters' + self.base_model = 'Base Model' + self.tuner_name = 'Fine-tuning Method' + self.base_model_revision = 'Model Version Number' + self.resolution = 'Resolution' + self.train_epoch = 'Number of Training Epochs' + self.learning_rate = 'Learning Rate' + self.save_interval = 'Save Interval' + self.train_batch_size = 'Training Batch Size' + self.prompt_prefix = 'Prefix' + self.replace_keywords = 'Trigger Keywords' + self.work_name = 'Save Model Name (refresh to get a random value)' + self.push_to_hub = 'Push to hub' + self.log_block = 'Training Log...' + self.training_button = 'Start Training' + + # Error or Warning + self.training_err1 = 'CUDA is unavailable.' + self.training_err2 = 'Currently insufficient VRAM, training failed!' + self.training_err3 = 'You need to prepare training data.' + self.training_err4 = 'Save model name already exists or is None, please regenerate this name.' + self.training_err5 = 'Training failed.' + self.training_err6 = "Can't process training data" + + elif language == 'zh': + self.user_direction = ''' + ### 使用说明 + - 数据: 选择Example的模版数据或可以按照样例中dog.zip包的格式准备自定义数据进行上传 + - 参数: 可尝试进行相关参数的修改 + - 训练: 点击【开始训练】 + - 测试: 完成训练后点击【使用模型】 + - 注意:超时可能导致连接断开(出现Error),可以等差不多可能训完后,刷新界面再点击页面最后的[刷新模型],即可在[产出模型名称中]出现已经完成训练的模型,若不存在则没有完成训练或训练失败 + - ZIP样例:https://modelscope.cn/api/v1/models/damo/scepter/repo?Revision=master&FilePath=datasets/3D_example_csv.zip + - 对于大规模数据的处理和训练,建议使用命令行形式 + ''' # noqa + self.data_type_choices = ['数据集zip', 'MaaS数据集'] + self.data_type_value = '数据集zip' + self.data_type_name = '数据集来源' + self.ms_data_name_place_hold = '支持MaaS数据集/本地/Http Zip包' + self.ms_data_space = 'ModelScope 空间' + self.ms_data_subname = 'MaaS数据集-子集' + self.training_block = '训练参数' + self.base_model = '基础模型' + self.tuner_name = '微调方法' + self.base_model_revision = '模型版本号' + self.resolution = '分辨率' + self.train_epoch = '训练轮数' + self.learning_rate = '学习率' + self.save_interval = '存储间隔' + self.train_batch_size = '训练批次' + self.prompt_prefix = '前缀' + self.replace_keywords = '触发关键词' + self.work_name = '保存模型名称(刷新获得随机值)' + self.push_to_hub = '推送魔搭社区' + self.log_block = '训练日志...' + self.training_button = '开始训练' + # Error or Warning + self.training_err1 = 'CUDA不可用.' + self.training_err2 = '目前显存不足,训练失败!' + self.training_err3 = '您需要准备训练数据' + self.training_err4 = '保存模型未生成或名称已经存在,请重新生成名称' + self.training_err5 = '训练失败' + self.training_err6 = '无法处理的数据' diff --git a/scepter/studio/self_train/self_train_ui/inference_ui.py b/scepter/studio/self_train/self_train_ui/inference_ui.py new file mode 100644 index 0000000..787fd3c --- /dev/null +++ b/scepter/studio/self_train/self_train_ui/inference_ui.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +import os + +import gradio as gr + +from scepter.modules.utils.config import Config +from scepter.modules.utils.file_system import FS +from scepter.studio.self_train.self_train_ui.component_names import \ + InferenceUIName +from scepter.studio.self_train.utils.config_parser import ( + get_base_model_list, get_inference_para_by_model_version) +from scepter.studio.utils.uibase import UIBase + + +class InferenceUI(UIBase): + def __init__(self, cfg, all_cfg_value, is_debug=False, language='en'): + self.BASE_CFG_VALUE = all_cfg_value + self.language = language + self.base_model_info = get_base_model_list(self.BASE_CFG_VALUE) + self.work_dir, _ = FS.map_to_local(cfg.WORK_DIR) + os.makedirs(self.work_dir, exist_ok=True) + self.model_list = [] + # self.model_list.extend(self.base_model_info.get('model_choices', [])) + have_model_list = [] + if not self.work_dir.endswith('/'): + self.work_dir += '/' + for one_dir in FS.walk_dir(self.work_dir): + if one_dir.startswith(self.work_dir): + one_dir = one_dir[len(self.work_dir):] + if not os.path.isdir(os.path.join(self.work_dir, one_dir)): + continue + if len(one_dir.split('/')) > 1: + continue + if '@' in one_dir and os.path.exists( + os.path.join(self.work_dir, one_dir, 'checkpoint.pth')): + if len(one_dir.split('@')) > 4: + have_model_list.append([one_dir, one_dir.split('@')[-1]]) + have_model_list.sort(key=lambda x: -int(x[-1][:-3])) + self.model_list.extend([v[0].split('/')[-1] + for v in have_model_list][:50]) + self.infer_para_data = get_inference_para_by_model_version( + self.BASE_CFG_VALUE, self.base_model_info.get('model_name', []), + self.base_model_info.get('version_name', [])) + self.is_debug = is_debug + self.component_names = InferenceUIName(language) + + def create_ui(self, *args, **kwargs): + with gr.Box(): + gr.Markdown(self.component_names.output_model_block) + with gr.Row(): + with gr.Column(scale=2, min_width=0): + self.output_model_name = gr.Dropdown( + label=self.component_names.output_model_name, + choices=self.model_list, + value=self.base_model_info.get('model_default', ''), + interactive=True) + with gr.Column(scale=1, min_width=0): + self.refresh_model_gbtn = gr.Button( + self.component_names.refresh_model_gbtn) + with gr.Row(): + with gr.Column(scale=2, min_width=0): + self.extra_model_gtxt = gr.Text( + label=self.component_names.extra_model_gtxt, + show_label=False, + placeholder='Add Extra Model') + with gr.Column(scale=1, min_width=0): + self.extra_model_gbtn = gr.Button( + self.component_names.extra_model_gbtn) + with gr.Row(): + with gr.Column(scale=1, min_width=0): + self.go_to_inferece_btn = gr.Button( + self.component_names.go_to_inference) + + def set_callbacks(self, trainer_ui, manager): + self.manager = manager + + def add_model(model_name): + if model_name not in self.model_list: + self.model_list.append(model_name) + return '', gr.Dropdown(choices=self.model_list) + + def refresh_model(): + return gr.Dropdown(choices=self.model_list) + + self.extra_model_gbtn.click( + fn=add_model, + inputs=[self.extra_model_gtxt], + outputs=[self.extra_model_gtxt, self.output_model_name], + queue=False) + self.refresh_model_gbtn.click(fn=refresh_model, + inputs=[], + outputs=[self.output_model_name], + queue=False) + + def go_to_inferece(output_model): + output_model_path = os.path.join(self.work_dir, output_model) + _, _, base_model, _, resolution, _ = output_model_path.split('@') + tuner_cfg = Config(cfg_dict={}, load=False) + tuner_cfg.NAME = output_model + tuner_cfg.NAME_ZH = output_model + tuner_cfg.BASE_MODEL = base_model + model_path = os.path.join(output_model_path, 'checkpoint.pth') + if not os.path.exists(model_path): + gr.Error(self.component_names.inference_err4) + tuner_cfg.MODEL_PATH = model_path + self.manager.inference.model_manage_ui.pipe_manager.register_tuner( + tuner_cfg, + name=tuner_cfg.NAME_ZH + if self.language == 'zh' else tuner_cfg.NAME, + is_customized=True) + + pipeline_level_modules = self.manager.inference.model_manage_ui.pipe_manager.pipeline_level_modules + if tuner_cfg.BASE_MODEL not in pipeline_level_modules: + gr.Error(self.component_names.inference_err3 + + tuner_cfg.BASE_MODEL) + pipeline_ins = pipeline_level_modules[tuner_cfg.BASE_MODEL] + diffusion_model = f"{tuner_cfg.BASE_MODEL}_{pipeline_ins.diffusion_model['name']}" + + default_choices = self.manager.inference.model_manage_ui.pipe_manager.module_level_choices + if 'customized_tuners' in default_choices and tuner_cfg.BASE_MODEL in default_choices[ + 'customized_tuners']: + tunner_choices = default_choices['customized_tuners'][ + tuner_cfg.BASE_MODEL]['choices'] + tunner_default = default_choices['customized_tuners'][ + tuner_cfg.BASE_MODEL]['default'] + if not isinstance(tunner_default, list): + tunner_default = [tunner_default] + else: + tunner_choices = [] + tunner_default = '' + return (gr.Tabs(selected='inference'), + gr.Dropdown(choices=tunner_choices, value=tunner_default), + gr.Dropdown(value=diffusion_model), + gr.Tabs(selected='tuner_ui')) + + self.go_to_inferece_btn.click( + go_to_inferece, + inputs=[self.output_model_name], + outputs=[ + manager.tabs, manager.inference.tuner_ui.custom_tuner_model, + manager.inference.model_manage_ui.diffusion_model, + manager.inference.setting_tab + ]) diff --git a/scepter/studio/self_train/self_train_ui/trainer_ui.py b/scepter/studio/self_train/self_train_ui/trainer_ui.py new file mode 100644 index 0000000..f00681d --- /dev/null +++ b/scepter/studio/self_train/self_train_ui/trainer_ui.py @@ -0,0 +1,585 @@ +# -*- coding: utf-8 -*- +import copy +import datetime +import os +import random +import time + +import gradio as gr +import torch +import yaml + +import scepter +from scepter.modules.utils.file_system import FS +from scepter.studio.self_train.self_train_ui.component_names import \ + TrainerUIName +from scepter.studio.self_train.utils.config_parser import ( + get_default, get_values_by_model, get_values_by_model_version, + get_values_by_model_version_tuner, + get_values_by_model_version_tuner_resolution) +from scepter.studio.utils.uibase import UIBase + + +def print_memory_status(is_debug): + if not is_debug: + nvi_info = os.popen('nvidia-smi').read() + gpu_mem = nvi_info.split('\n')[9].split('|')[2].split('/')[0].strip() + else: + gpu_mem = 0 + return gpu_mem + + +refresh_symbol = '\U0001f504' # 🔄 + + +def get_work_name(model, version, tuner, resolution): + model_prefix = f'Swift@{model}@{version}@{tuner}@{resolution}' + return model_prefix + '@' + '{0:%Y%m%d%H%M%S%f}'.format( + datetime.datetime.now()) + ''.join( + [str(random.randint(1, 10)) for i in range(3)]) + + +class TrainerUI(UIBase): + def __init__(self, cfg, all_cfg_value, is_debug=False, language='en'): + self.BASE_CFG_VALUE = all_cfg_value + self.para_data = get_default(self.BASE_CFG_VALUE) + self.run_script = os.path.join(os.path.dirname(scepter.dirname), + cfg.SCRIPT_DIR, 'run_task.py') + self.work_dir_pre, _ = FS.map_to_local(cfg.WORK_DIR) + self.is_debug = is_debug + self.component_names = TrainerUIName(language=language) + + def create_ui(self): + with gr.Box(): + with gr.Row(variant='panel', equal_height=True): + with gr.Column(variant='panel'): + gr.Markdown(self.component_names.user_direction) + self.data_type = gr.Dropdown( + choices=self.component_names.data_type_choices, + value=self.component_names.data_type_value, + label=self.component_names.data_type_name, + interactive=True) + self.ms_data_name = gr.Textbox( + label=' or '.join( + self.component_names.data_type_choices), + max_lines=1, + placeholder=self.component_names. + ms_data_name_place_hold, + interactive=True) + with gr.Box(visible=False) as self.ms_data_box: + with gr.Row(): + self.ms_data_space = gr.Textbox( + label=self.component_names.ms_data_space, + max_lines=1) + self.ms_data_subname = gr.Textbox( + label=self.component_names.ms_data_subname, + value='default', + max_lines=1) + with gr.Column(variant='panel'): + with gr.Box(): + gr.Markdown(self.component_names.training_block) + with gr.Row(): + with gr.Column(scale=1, min_width=0): + self.base_model = gr.Dropdown( + choices=self.para_data.get( + 'model_choices', []), + value=self.para_data.get( + 'model_default', ''), + label=self.component_names.base_model, + interactive=True) + with gr.Column(scale=1, min_width=0): + self.tuner_name = gr.Dropdown( + choices=self.para_data.get( + 'tuner_choices', []), + value=self.para_data.get( + 'tuner_default', ''), + label=self.component_names.tuner_name, + interactive=True) + with gr.Row(): + with gr.Column(scale=1, min_width=0): + self.base_model_revision = gr.Dropdown( + choices=self.para_data.get( + 'version_choices', []), + value=self.para_data.get( + 'version_default', ''), + label=self.component_names. + base_model_revision, + interactive=True) + + with gr.Column(scale=1, min_width=0): + self.resolution = gr.Dropdown( + choices=self.para_data.get( + 'resolution_choices', []), + value=self.para_data.get( + 'resolution_default', 1024), + label=self.component_names.resolution, + allow_custom_value=True, + interactive=True) + + with gr.Row(): + with gr.Column(scale=1, min_width=0): + self.train_epoch = gr.Number( + label=self.component_names.train_epoch, + value=self.para_data.get('EPOCHS', 10), + precision=0, + interactive=True) + with gr.Column(scale=1, min_width=0): + self.learning_rate = gr.Number( + label=self.component_names.learning_rate, + value=self.para_data.get( + 'LEARNING_RATE', 0.0001), + interactive=True) + + with gr.Row(): + with gr.Column(scale=1, min_width=0): + self.save_interval = gr.Number( + label=self.component_names.save_interval, + value=self.para_data.get( + 'SAVE_INTERVAL', 10), + precision=0, + interactive=True) + with gr.Column(scale=1, min_width=0): + self.train_batch_size = gr.Number( + label=self.component_names. + train_batch_size, + value=self.para_data.get( + 'TRAIN_BATCH_SIZE', 4), + precision=0, + interactive=True) + + with gr.Row(): + with gr.Column(scale=1, min_width=0): + self.prompt_prefix = gr.Text( + label=self.component_names.prompt_prefix, + value=self.para_data.get( + 'TRAIN_PREFIX', '')) + with gr.Column(scale=1, min_width=0): + self.replace_keywords = gr.Text( + label=self.component_names. + replace_keywords, + value='') + + with gr.Row(): + with gr.Column(scale=5, min_width=0): + self.work_name = gr.Text( + label=self.component_names.work_name, + value=None, + interactive=False) + with gr.Column(scale=1, min_width=0): + self.work_name_button = gr.Button( + value=refresh_symbol) + with gr.Column(scale=2, min_width=0): + self.push_to_hub = gr.Checkbox( + label=self.component_names.push_to_hub, + value=False, + visible=False) + + with gr.Row(variant='panel', equal_height=True): + self.examples = gr.Examples( + examples=[ + [ + self.component_names.data_type_choices[0], + '', + 'https://modelscope.cn/api/v1/models/damo/scepter/repo?Revision=master&FilePath=datasets/3D_example_csv.zip', # noqa + '' + ], + [ + self.component_names.data_type_choices[1], 'damo', + 'style_custom_dataset', '3D' + ] + ], + inputs=[ + self.data_type, self.ms_data_space, self.ms_data_name, + self.ms_data_subname + ]) + + with gr.Row(variant='panel', equal_height=True): + with gr.Box(): + gr.Markdown(self.component_names.log_block) + self.training_message = gr.Markdown() + with gr.Row(variant='panel', equal_height=True): + self.training_button = gr.Button() + + def set_callbacks(self, inference_ui): + def change_data_type(data_type): + if data_type == self.component_names.data_type_choices[0]: + return gr.Box(visible=False) + elif data_type == self.component_names.data_type_choices[1]: + return gr.Box(visible=True) + + self.data_type.change(fn=change_data_type, + inputs=[self.data_type], + outputs=[self.ms_data_box], + queue=False) + + self.work_name_button.click(fn=get_work_name, + inputs=[ + self.base_model, + self.base_model_revision, + self.tuner_name, self.resolution + ], + outputs=[self.work_name], + queue=False) + + def change_train_value_by_model(base_model): + ''' + Changes to the base model will affect the training parameters, + and it is best to define the related default values in the YAML. + Training Iterations: + Learning Rate: + Training Prefix Used: + Training Batch Size: + Supported Resolutions: + Supported Fine-tuning Methods: + Supported Fine-tuning Methods: + Prefix for Saved Model: + ''' + ret_data = get_values_by_model(self.BASE_CFG_VALUE, base_model) + return ret_data.get('EPOCHS', 10), \ + ret_data.get('LEARNING_RATE', 0.0001), \ + ret_data.get('SAVE_INTERVAL', 10), \ + ret_data.get('TRAIN_BATCH_SIZE', 4), \ + ret_data.get('TRAIN_PREFIX', ''), \ + gr.Dropdown(value=ret_data.get('version_default', ''), choices=ret_data.get('version_choices', []), + interactive=True), \ + gr.Dropdown(value=ret_data.get('tuner_default', ''), choices=ret_data.get('tuner_choices', []), + interactive=True), \ + gr.Dropdown(value=ret_data.get('resolution_default', 1024), + choices=ret_data.get('resolution_choices', []), interactive=True) + + self.base_model.change(fn=change_train_value_by_model, + inputs=[self.base_model], + outputs=[ + self.train_epoch, self.learning_rate, + self.save_interval, self.train_batch_size, + self.prompt_prefix, + self.base_model_revision, self.tuner_name, + self.resolution + ], + queue=False) + + # + def change_train_value_by_model_version(base_model, + base_model_revision): + ''' + Changes to the base model will affect the training parameters, + and it is best to define the related default values in the YAML. + Training Iterations: + Learning Rate: + Training Prefix Used: + Training Batch Size: + Supported Resolutions: + Supported Fine-tuning Methods: + Supported Fine-tuning Methods: + Prefix for Saved Model: + ''' + ret_data = get_values_by_model_version(self.BASE_CFG_VALUE, + base_model, + base_model_revision) + return ret_data.get('EPOCHS', 10), \ + ret_data.get('LEARNING_RATE', 0.0001), \ + ret_data.get('SAVE_INTERVAL', 10), \ + ret_data.get('TRAIN_BATCH_SIZE', 4), \ + ret_data.get('TRAIN_PREFIX', ''), \ + gr.Dropdown(value=ret_data.get('tuner_default', ''), choices=ret_data.get('tuner_choices', []), + interactive=True), \ + gr.Dropdown(value=ret_data.get('resolution_default', 1024), + choices=ret_data.get('resolution_choices', []), interactive=True) + + # + self.base_model_revision.change( + fn=change_train_value_by_model_version, + inputs=[self.base_model, self.base_model_revision], + outputs=[ + self.train_epoch, self.learning_rate, self.save_interval, + self.train_batch_size, self.prompt_prefix, self.tuner_name, + self.resolution + ], + queue=False) + + # + # + def change_train_value_by_model_version_tuner(base_model, + base_model_revision, + tuner_name): + ''' + Changes to the base model will affect the training parameters, + and it is best to define the related default values in the YAML. + Training Iterations: + Learning Rate: + Training Prefix Used: + Training Batch Size: + Supported Resolutions: + Supported Fine-tuning Methods: + Supported Fine-tuning Methods: + Prefix for Saved Model: + ''' + ret_data = get_values_by_model_version_tuner( + self.BASE_CFG_VALUE, base_model, base_model_revision, + tuner_name) + return ret_data.get('EPOCHS', 10), \ + ret_data.get('LEARNING_RATE', 0.0001), \ + ret_data.get('SAVE_INTERVAL', 10), \ + ret_data.get('TRAIN_BATCH_SIZE', 4), \ + ret_data.get('TRAIN_PREFIX', ''), \ + gr.Dropdown(value=ret_data.get('resolution_default', 1024), + choices=ret_data.get('resolution_choices', []), interactive=True) + + # + self.tuner_name.change(fn=change_train_value_by_model_version_tuner, + inputs=[ + self.base_model, self.base_model_revision, + self.tuner_name + ], + outputs=[ + self.train_epoch, self.learning_rate, + self.save_interval, self.train_batch_size, + self.prompt_prefix, self.resolution + ], + queue=False) + + # + def change_train_value_by_model_version_tuner_resolution( + base_model, base_model_revision, tuner_name, resolution): + ''' + Changes to the base model will affect the training parameters, + and it is best to define the related default values in the YAML. + Training Iterations: + Learning Rate: + Training Prefix Used: + Training Batch Size: + Supported Resolutions: + Supported Fine-tuning Methods: + Supported Fine-tuning Methods: + Prefix for Saved Model: + ''' + ret_data = get_values_by_model_version_tuner_resolution( + self.BASE_CFG_VALUE, base_model, base_model_revision, + tuner_name, resolution) + print('change_train_value_by_model_version_tuner_resolution', + ret_data) + # work_name = get_work_name(base_model, base_model_revision, + # tuner_name, resolution) + return ret_data.get('EPOCHS', 10), \ + ret_data.get('LEARNING_RATE', 0.0001), \ + ret_data.get('SAVE_INTERVAL', 10), \ + ret_data.get('TRAIN_BATCH_SIZE', 4), \ + ret_data.get('TRAIN_PREFIX', '') + + # + self.resolution.change( + fn=change_train_value_by_model_version_tuner_resolution, + inputs=[ + self.base_model, self.base_model_revision, self.tuner_name, + self.resolution + ], + outputs=[ + self.train_epoch, self.learning_rate, self.save_interval, + self.train_batch_size, self.prompt_prefix + ], + queue=False) + + def run_train(work_name, data_type, ms_data_space, ms_data_name, + ms_data_subname, base_model, base_model_revision, + tuner_name, resolution, train_epoch, learning_rate, + save_interval, train_batch_size, prompt_prefix, + replace_keywords, push_to_hub): + # Check Cuda + if not torch.cuda.is_available() and not self.is_debug: + raise gr.Error(self.component_names.training_err1) + + if work_name == 'custom' or work_name is None or work_name == '': + raise gr.Error(self.component_names.training_err4) + work_dir = os.path.join(self.work_dir_pre, work_name) + if not os.path.exists(work_dir): + os.makedirs(work_dir) + else: + raise gr.Error(self.component_names.training_err4) + + if push_to_hub: + model_id = work_name + model_id = model_id.replace('@', '-') + hub_model_id = f'scepter/{model_id}' + else: + hub_model_id = '' + + # Check Cuda Memory + if torch.cuda.is_available() and not self.is_debug: + device = torch.device('cuda:0') + required_memory_bytes = 40 * (1024**3) + try: + tensor = torch.empty( # noqa + (required_memory_bytes // 4, ), device=device + ) # create 18GB tensor to check the memory if enough + del tensor + except RuntimeError: + raise gr.Error(self.component_names.training_err2) + + # Check Instance Valid + if ms_data_name is None: + raise gr.Error(self.component_names.training_err3) + + st_time = time.time() + + def prepare_data(data_cfg): + data_cfg['BATCH_SIZE'] = int(train_batch_size) + data_cfg['PROMPT_PREFIX'] = prompt_prefix + data_cfg['REPLACE_KEYWORDS'] = replace_keywords + if data_type in self.component_names.data_type_choices: + if ms_data_name.startswith( + 'http') or ms_data_name.endswith('zip'): + work_data_dir = os.path.join(work_dir, 'data') + if not os.path.exists(work_data_dir): + os.makedirs(work_data_dir) + ms_data_http_zip_path = ms_data_name + ms_data_local_name = ms_data_name.split( + '/')[-1].replace('.zip', '') + ms_data_local_zip_path = os.path.join( + work_data_dir, + ms_data_name.split('/')[-1]) + ms_data_local_file_path = os.path.join( + work_data_dir, ms_data_local_name) + if not os.path.exists(ms_data_local_file_path): + if ms_data_http_zip_path.startswith('http'): + os.system( + f"wget '{ms_data_http_zip_path}' -O '{ms_data_local_zip_path}'" + ) + elif os.path.exists(ms_data_http_zip_path): + ms_data_local_zip_path = ms_data_http_zip_path + else: + raise gr.Error( + self.component_names.training_err6) + print( + f"unzip -o '{ms_data_local_zip_path}' -d '{work_data_dir}'" + ) + os.system( + f"unzip -o '{ms_data_local_zip_path}' -d '{work_data_dir}'" + ) + data_cfg['MS_DATASET_NAME'] = ms_data_local_file_path + data_cfg['MS_DATASET_NAMESPACE'] = '' + data_cfg['MS_DATASET_SUBNAME'] = '' + data_cfg['MS_REMAP_PATH'] = ms_data_local_file_path + data_cfg['MS_REMAP_KEYS'] = None + elif (os.path.exists(ms_data_name) and os.path.exists( + os.path.join(ms_data_name, 'train.csv')) + and os.path.exists( + os.path.join(ms_data_name, 'images'))): + data_cfg['MS_DATASET_NAME'] = ms_data_name + data_cfg['MS_DATASET_NAMESPACE'] = '' + data_cfg['MS_DATASET_SUBNAME'] = '' + data_cfg['MS_REMAP_PATH'] = ms_data_name + data_cfg['MS_REMAP_KEYS'] = None + else: + data_cfg['MS_DATASET_NAME'] = ms_data_name + data_cfg['MS_DATASET_NAMESPACE'] = ms_data_space + data_cfg['MS_DATASET_SUBNAME'] = ms_data_subname + if ms_data_name == 'style_custom_dataset': + data_cfg['MS_REMAP_KEYS'] = { + 'Image:FILE': 'Target:FILE' + } + elif ms_data_name == 'lora-stable-diffusion-finetune': + data_cfg['MS_REMAP_KEYS'] = {'Text': 'Prompt'} + else: + data_cfg['MS_REMAP_KEYS'] = None + data_cfg['OUTPUT_SIZE'] = int(resolution) + return data_cfg + + def prepare_train_config(): + cfg_file = os.path.join(work_dir, 'train.yaml') + current_model_info = self.BASE_CFG_VALUE[base_model][ + base_model_revision] + modify_para = current_model_info['modify_para'] + cfg = current_model_info['config_value'] + if isinstance(modify_para, dict) and tuner_name in modify_para: + modify_c = modify_para[tuner_name] + if isinstance(modify_c, dict) and 'TRAIN' in modify_c: + train_modify_c = modify_c['TRAIN'] + if isinstance(train_modify_c, dict): + for key, val in train_modify_c.items(): + cache_value = [cfg] + c_k_list = key.split('.') + for idx, c_k in enumerate(c_k_list): + if c_k.strip() == '': + continue + cache_value.append( + copy.deepcopy(cache_value[idx][c_k])) + current_val = copy.deepcopy(val) + for c_k, v in zip(c_k_list[::-1], + cache_value[:-1][::-1]): + v[c_k] = current_val + current_val = v + cfg = current_val + + # update config + cfg['SOLVER']['WORK_DIR'] = work_dir + cfg['SOLVER']['OPTIMIZER']['LEARNING_RATE'] = float( + learning_rate * 640 / int(train_batch_size)) + cfg['SOLVER']['MAX_EPOCHS'] = int(train_epoch) + cfg['SOLVER']['TRAIN_DATA']['BATCH_SIZE'] = int( + train_batch_size) + cfg['SOLVER']['TUNER'] = current_model_info[ + 'tuner_para'][tuner_name] if isinstance( + current_model_info['tuner_para'], + dict) and tuner_name in current_model_info[ + 'tuner_para'] else None + cfg['SOLVER']['TRAIN_DATA'] = prepare_data( + cfg['SOLVER']['TRAIN_DATA']) + for hook in cfg['SOLVER']['TRAIN_HOOKS']: + if hook['NAME'] == 'CheckpointHook': + hook['INTERVAL'] = save_interval + hook['PUSH_TO_HUB'] = push_to_hub + hook['HUB_MODEL_ID'] = hub_model_id + + with open(cfg_file, 'w') as f_out: + yaml.dump(cfg, + f_out, + encoding='utf-8', + allow_unicode=True, + default_flow_style=False) + return cfg_file + + cfg = prepare_train_config() + + def train_fn(cfg_file): + torch.cuda.empty_cache() + cmd = f'PYTHONPATH=. python {self.run_script} ' \ + f'--cfg={cfg_file} 2> {self.work_dir_pre}/std_out.txt' + print(cmd) + if not self.is_debug: + res = os.system(cmd) + else: + res = 0 + if res != 0: + error_info = '\n'.join( + open(f'{self.work_dir_pre}/std_out.txt', + 'r').read().split('\n')[-20:]) + raise gr.Error( + f'{self.component_names.training_err5} ({error_info}) ' + ) + + train_fn(cfg) + + if work_name not in inference_ui.model_list: + inference_ui.model_list.append(work_name) + message = f''' + Training completed! \n + Save in [ {work_name} ] \n + Take time [ {time.time() - st_time:.4f}s ] \n + Mem: [ {print_memory_status(self.is_debug)} ] + ''' + print(message) + return message, gr.Dropdown.update(choices=inference_ui.model_list, + value=work_name) + + self.training_button.click( + run_train, + inputs=[ + self.work_name, self.data_type, self.ms_data_space, + self.ms_data_name, self.ms_data_subname, self.base_model, + self.base_model_revision, self.tuner_name, self.resolution, + self.train_epoch, self.learning_rate, self.save_interval, + self.train_batch_size, self.prompt_prefix, + self.replace_keywords, self.push_to_hub + ], + outputs=[self.training_message, inference_ui.output_model_name], + queue=True) diff --git a/scepter/studio/self_train/utils/__init__.py b/scepter/studio/self_train/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/studio/self_train/utils/config_parser.py b/scepter/studio/self_train/utils/config_parser.py new file mode 100644 index 0000000..5d2c350 --- /dev/null +++ b/scepter/studio/self_train/utils/config_parser.py @@ -0,0 +1,384 @@ +# -*- coding: utf-8 -*- +import os +from glob import glob + +import yaml + +paras_keys = [ + 'TRAIN_BATCH_SIZE', 'TRAIN_PREFIX', 'TRAIN_N_PROMPT', 'RESOLUTION', + 'MEMORY', 'EPOCHS', 'SAVE_INTERVAL', 'EPSEC', 'LEARNING_RATE', + 'IS_DEFAULT', 'TUNER' +] + +control_paras_keys = ['CONTROL_MODE', 'RESOLUTION', 'IS_DEFAULT'] + + +def build_meta_index(meta_cfg, config_file): + tuner_type = {} + paras = meta_cfg.get('PARAS', None) + if paras: + for idx, para in enumerate(paras): + for key in paras_keys: + if key not in para: + print( + f'Para key {key} not defined in {config_file} META/RARAS[{idx}]' + ) + assert key in para + tuner_type[para['TUNER'] + '@' + str(para['RESOLUTION'])] = para + if para['IS_DEFAULT']: + tuner_type['default'] = para['TUNER'] + '@' + str( + para['RESOLUTION']) + + tuner_type['choices'] = list(tuner_type.keys()) + if 'default' in tuner_type['choices']: + tuner_type['choices'].remove('default') + if 'default' not in tuner_type: + tuner_type['default'] = tuner_type['choices'][0] if len( + tuner_type['choices']) > 0 else '' + + # 重新组织选项 + choices = {} + for t_type in tuner_type['choices']: + t_name, resolution = t_type.split('@') + if t_name not in choices: + choices[t_name] = [] + choices[t_name].append(int(resolution)) + tuner_type['choices'] = choices + tuner_paras = meta_cfg.get('TUNERS', None) + return tuner_type, tuner_paras + + +def build_meta_index_control(meta_cfg, config_file): + control_type = {} + paras = meta_cfg.get('CONTROL_PARAS', None) + if paras: + for idx, para in enumerate(paras): + for key in control_paras_keys: + if key not in para: + print( + f'Para key {key} not defined in {config_file} META/RARAS[{idx}]' + ) + assert key in para + control_type[para['CONTROL_MODE'] + '@' + + str(para['RESOLUTION'])] = para + # control_type[para["CONTROL_MODE"]] = para + if para['IS_DEFAULT']: + control_type['default'] = para['CONTROL_MODE'] + '@' + str( + para['RESOLUTION']) + # control_type["default"] = para["CONTROL_MODE"] + + control_type['choices'] = list(control_type.keys()) + if 'default' in control_type['choices']: + control_type['choices'].remove('default') + if 'default' not in control_type: + control_type['default'] = control_type['choices'][0] if len( + control_type['choices']) > 0 else '' + + # 重新组织选项 + choices = {} + for t_type in control_type['choices']: + t_name, resolution = t_type.split('@') + if t_name not in choices: + choices[t_name] = [] + choices[t_name].append(int(resolution)) + control_type['choices'] = choices + return control_type, paras + + +def get_all_config(config_root, global_meta): + config_dict = {} + config_list = glob(os.path.join(config_root, '*/*_pro.yaml'), + recursive=True) + for config_file in config_list: + base_model_name = config_file.split('/')[-2] + with open(config_file, 'r') as f: + cfg = yaml.load(f.read(), Loader=yaml.SafeLoader) + if base_model_name not in config_dict: + config_dict[base_model_name] = {} + + meta_cfg = cfg.pop('META') + inference_paras = meta_cfg.pop('INFERENCE_PARAS') + if 'MODIFY_PARAS' in meta_cfg: + modify_para = meta_cfg['MODIFY_PARAS'] + else: + modify_para = {} + version = meta_cfg['VERSION'] + if version in config_dict[base_model_name]: + ori_config = config_dict[base_model_name][version]['config_file'] + print( + f'Current config {config_file} for {base_model_name}_{version} will be replaced by {ori_config}.' + ) + + tuner_type, tuner_para = build_meta_index(meta_cfg, config_file) + config_dict[base_model_name][version] = { + 'config_file': config_file, + 'config_value': cfg, + 'inference_para': inference_paras, + 'tuner_type': tuner_type, + 'tuner_para': tuner_para, + 'modify_para': modify_para + } + if 'CONTROL_PARAS' in meta_cfg: + control_type, control_para = build_meta_index_control( + meta_cfg, config_file) + config_dict[base_model_name][version].update({ + 'control_type': + control_type, + 'control_para': + control_para + }) + if meta_cfg['IS_DEFAULT']: + config_dict[base_model_name]['default'] = version + + for base_model_name in config_dict: + config_dict[base_model_name]['choices'] = list( + config_dict[base_model_name].keys()) + if 'default' in config_dict[base_model_name]['choices']: + config_dict[base_model_name]['choices'].remove('default') + if 'default' not in config_dict[base_model_name]: + config_dict[base_model_name][ + 'default'] = config_dict[base_model_name]['choices'][0] if len( + config_dict[base_model_name]['choices']) > 0 else '' + + config_dict['choices'] = list(config_dict.keys()) + config_dict['default'] = config_dict['choices'][0] if len( + config_dict['choices']) > 0 else '' + default_base_model = global_meta.DEFAULT_FOLDER + if default_base_model in config_dict: + config_dict['default'] = default_base_model + config_dict['samplers'] = { + sampler['NAME']: sampler + for sampler in global_meta.SAMPLERS + } + config_dict.update(cfg) + return config_dict + + +def get_default(config_dict): + ret_data = {} + # 默认的模型 + ret_data['model_choices'] = config_dict['choices'] + ret_data['model_default'] = config_dict['default'] + default_version_cfg = config_dict.get(config_dict['default'], None) + # 默认的版本 + if default_version_cfg is None: + return ret_data + ret_data['version_choices'] = default_version_cfg['choices'] + ret_data['version_default'] = default_version_cfg['default'] + default_tuner_cfg = default_version_cfg.get(default_version_cfg['default'], + None) + if default_tuner_cfg is None: + return ret_data + if 'tuner_type' in default_tuner_cfg and default_tuner_cfg['tuner_type'][ + 'default'] != '': + default_tuner_cfg = default_tuner_cfg['tuner_type'] + else: + return ret_data + ret_data['tuner_choices'] = list(default_tuner_cfg['choices'].keys()) + defalt_t_type = default_tuner_cfg['default'] + type_paras = default_tuner_cfg.get(defalt_t_type, None) + + default_t_n = defalt_t_type.split('@')[0] + default_r_n = int(defalt_t_type.split('@')[1]) + + ret_data['resolution_choices'] = default_tuner_cfg['choices'].get( + default_t_n, []) + ret_data['tuner_default'] = default_t_n + ret_data['resolution_default'] = default_r_n + if type_paras is not None: + ret_data.update(type_paras) + return ret_data + + +def get_values_by_model(config_dict, model_name): + ret_data = {} + version_cfg = config_dict.get(model_name, None) + if version_cfg is None: + return ret_data + ret_data['version_choices'] = version_cfg['choices'] + ret_data['version_default'] = version_cfg['default'] + default_tuner_cfg = version_cfg.get(version_cfg['default'], None) + if default_tuner_cfg is None: + return ret_data + default_tuner_cfg = default_tuner_cfg['tuner_type'] + ret_data['tuner_choices'] = list(default_tuner_cfg['choices'].keys()) + defalt_t_type = default_tuner_cfg['default'] + type_paras = default_tuner_cfg.get(defalt_t_type, None) + + default_t_n = defalt_t_type.split('@')[0] + default_r_n = int(defalt_t_type.split('@')[1]) + + ret_data['resolution_choices'] = default_tuner_cfg['choices'].get( + default_t_n, []) + ret_data['tuner_default'] = default_t_n + ret_data['resolution_default'] = default_r_n + if type_paras is not None: + ret_data.update(type_paras) + return ret_data + + +def get_values_by_model_version(config_dict, model_name, version): + ret_data = {} + version_cfg = config_dict.get(model_name, None) + if version_cfg is None: + return ret_data + tuner_cfg = version_cfg.get(version, None) + if tuner_cfg is None: + return ret_data + default_tuner_cfg = tuner_cfg['tuner_type'] + ret_data['tuner_choices'] = list(default_tuner_cfg['choices'].keys()) + defalt_t_type = default_tuner_cfg['default'] + type_paras = default_tuner_cfg.get(defalt_t_type, None) + + default_t_n = defalt_t_type.split('@')[0] + default_r_n = int(defalt_t_type.split('@')[1]) + + ret_data['resolution_choices'] = default_tuner_cfg['choices'].get( + default_t_n, []) + ret_data['tuner_default'] = default_t_n + ret_data['resolution_default'] = default_r_n + if type_paras is not None: + ret_data.update(type_paras) + return ret_data + + +def get_values_by_model_version_tuner(config_dict, model_name, version, + tuner_name): + ret_data = {} + version_cfg = config_dict.get(model_name, None) + if version_cfg is None: + return ret_data + tuner_cfg = version_cfg.get(version, None) + if tuner_cfg is None: + return ret_data + tuner_cfg = tuner_cfg['tuner_type'] + + ret_data['resolution_choices'] = tuner_cfg['choices'].get(tuner_name, []) + + if len(ret_data['resolution_choices']) > 0: + t_type = '{}@{}'.format(tuner_name, ret_data['resolution_choices'][0]) + ret_data['resolution_default'] = ret_data['resolution_choices'][0] + type_paras = tuner_cfg.get(t_type, None) + if type_paras is not None: + ret_data.update(type_paras) + return ret_data + + +def get_values_by_model_version_tuner_resolution(config_dict, model_name, + version, tuner_name, + resolution): + ret_data = {} + version_cfg = config_dict.get(model_name, None) + if version_cfg is None: + return ret_data + tuner_cfg = version_cfg.get(version, None) + if tuner_cfg is None: + return ret_data + tuner_cfg = tuner_cfg['tuner_type'] + type_paras = tuner_cfg.get('{}@{}'.format(tuner_name, resolution), None) + if type_paras is not None: + ret_data.update(type_paras) + return ret_data + + +def get_inference_para_by_model_version(config_dict, model_name, version): + ret_data = {} + version_cfg = config_dict.get(model_name, None) + if version_cfg is None: + return ret_data + tuner_cfg = version_cfg.get(version, None) + if tuner_cfg is None: + return ret_data + samplers_list = list(config_dict['samplers'].keys()) + ret_data.update(tuner_cfg['inference_para']) + ret_data['sampler_default'] = ret_data['DEFAULT_SAMPLER'] + if ret_data['DEFAULT_SAMPLER'] in samplers_list: + samplers_list.remove(ret_data['DEFAULT_SAMPLER']) + ret_data['sampler_choices'] = [ret_data['DEFAULT_SAMPLER']] + samplers_list + return ret_data + + +def get_base_model_list(config_dict): + ret_data = {'model_choices': [], 'model_default': '@'} + default_model = config_dict['default'] + if not default_model == '': + default_version = config_dict[default_model]['default'] + else: + default_version = '' + ret_data['model_default'] = f'{default_model}@{default_version}' + for base_model_name in config_dict: + if base_model_name in ['default', 'choices', 'samplers']: + continue + for version in config_dict[base_model_name]: + if version in ['default', 'choices', 'samplers']: + continue + ret_data['model_choices'].append(f'{base_model_name}@{version}') + if not ret_data['model_default'] == '@': + ret_data['model_choices'].remove(ret_data['model_default']) + ret_data['model_choices'] = [ret_data['model_default'] + ] + ret_data['model_choices'] + else: + ret_data['model_default'] = ret_data['model_choices'][0] if len( + ret_data['model_choices']) > 0 else '' + + if not ret_data['model_default'] == '': + ret_data['model_name'] = ret_data['model_default'].split('@')[0] + ret_data['version_name'] = ret_data['model_default'].split('@')[1] + else: + ret_data['model_name'] = '' + ret_data['version_name'] = '' + return ret_data + + +def get_control_para_by_model_version(config_dict, model_name, version): + ret_data = {} + version_cfg = config_dict.get(model_name, None) + if version_cfg is None: + return ret_data + tuner_cfg = version_cfg.get(version, None) + if tuner_cfg is None: + return ret_data + samplers_list = list(config_dict['samplers'].keys()) + ret_data.update(tuner_cfg['inference_para']) + ret_data['sampler_default'] = ret_data['DEFAULT_SAMPLER'] + if ret_data['DEFAULT_SAMPLER'] in samplers_list: + samplers_list.remove(ret_data['DEFAULT_SAMPLER']) + ret_data['sampler_choices'] = [ret_data['DEFAULT_SAMPLER']] + samplers_list + return ret_data + + +def get_control_default(config_dict): + ret_data = {} + # 默认的模型 + ret_data['model_choices'] = config_dict['choices'] + ret_data['model_default'] = config_dict['default'] + default_version_cfg = config_dict.get(config_dict['default'], None) + # 默认的版本 + if default_version_cfg is None: + return ret_data + ret_data['version_choices'] = default_version_cfg['choices'] + ret_data['version_default'] = default_version_cfg['default'] + default_control_cfg = default_version_cfg.get( + default_version_cfg['default'], None) + if default_control_cfg is None: + return ret_data + if 'control_type' in default_control_cfg and default_control_cfg[ + 'control_type']['default'] != '': + default_control_cfg = default_control_cfg['control_type'] + else: + return ret_data + # import pdb; pdb.set_trace() + ret_data['control_choices'] = list(default_control_cfg['choices'].keys()) + defalt_t_type = default_control_cfg['default'] + type_paras = default_control_cfg.get(defalt_t_type, None) + + default_t_n = defalt_t_type.split('@')[0] + default_r_n = int(defalt_t_type.split('@')[1]) + + ret_data['resolution_choices'] = default_control_cfg['choices'].get( + default_t_n, []) + ret_data['control_default'] = default_t_n + ret_data['resolution_default'] = default_r_n + if type_paras is not None: + ret_data.update(type_paras) + return ret_data diff --git a/scepter/studio/utils/__init__.py b/scepter/studio/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scepter/studio/utils/env.py b/scepter/studio/utils/env.py new file mode 100644 index 0000000..d6755f6 --- /dev/null +++ b/scepter/studio/utils/env.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +from scepter.modules.utils.file_system import FS + + +def init_env(cfg_general): + work_dir = cfg_general.WORK_DIR + file_system = cfg_general.get('FILE_SYSTEM', None) + if file_system is not None: + if isinstance(file_system, list): + for file_sys in file_system: + _prefix = FS.init_fs_client(file_sys) + elif file_system is not None: + _prefix = FS.init_fs_client(file_system) # noqa + is_flag = FS.make_dir(work_dir) + assert is_flag + return cfg_general diff --git a/scepter/studio/utils/file.py b/scepter/studio/utils/file.py new file mode 100644 index 0000000..2ace679 --- /dev/null +++ b/scepter/studio/utils/file.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +import os + + +def get_tuner_choices(): + tuner_choices = [] + current_dir = os.path.dirname(__file__) + base_path = os.sep.join(current_dir.split(os.sep)[:-3]) + base_path = os.path.join(base_path, 'config') + for file in os.listdir(base_path): + if 'ipynb' in file: + continue + import json + + with open(os.path.join(base_path, file), 'r') as f: + content = json.load(f) + tuner_choices.append(content['name']) + return tuner_choices diff --git a/scepter/studio/utils/singleton.py b/scepter/studio/utils/singleton.py new file mode 100644 index 0000000..3ea30e0 --- /dev/null +++ b/scepter/studio/utils/singleton.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +class Singleton(object): + @classmethod + def get_instance(cls, cfg, **kwargs): + if not hasattr(cls, '_instance'): + cls._instance = cls(cfg, **kwargs) + return cls._instance diff --git a/scepter/studio/utils/uibase.py b/scepter/studio/utils/uibase.py new file mode 100644 index 0000000..3b81f72 --- /dev/null +++ b/scepter/studio/utils/uibase.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from scepter.studio.utils.singleton import Singleton + + +class UIBase(Singleton): + def create_ui(self, *args, **kwargs): + raise NotImplementedError() + + def set_callbacks(self, *args, **kwargs): + raise NotImplementedError() + + def func_to_set_value(self, name, type=None): + def func(value): + if type is not None: + value = type(value) + setattr(self, name, value) + return value + + return func diff --git a/scepter/tools/run_inference.py b/scepter/tools/run_inference.py index 2d0e98f..7376e33 100644 --- a/scepter/tools/run_inference.py +++ b/scepter/tools/run_inference.py @@ -7,6 +7,8 @@ import cv2 import numpy as np import torch import torch.cuda.amp as amp +import torchvision.transforms as TT +from PIL import Image from scepter.modules.solver.registry import SOLVERS from scepter.modules.utils.config import Config @@ -41,7 +43,7 @@ def run_task(cfg): image_size = [int(h), int(w)] else: image_size = [int(image_size), int(image_size)] - + batch_data = {} if solver.sample_args: batch_data.update(solver.sample_args.get_lowercase_dict()) @@ -56,7 +58,7 @@ def run_task(cfg): 'guide_scale': guide_scale, 'guide_rescale': guide_rescale, }) - + dtype = getattr(torch, cfg.SOLVER.DTYPE) with amp.autocast(enabled=True, dtype=dtype): batch_data = transfer_data_to_cuda(batch_data) @@ -74,8 +76,98 @@ def run_task(cfg): cv2.imwrite(local_path, image) +def run_task_control(cfg): + from scepter.modules.annotator.utils import AnnotatorProcessor + + std_logger = get_logger(name='scepter') + solver = SOLVERS.build(cfg.SOLVER, logger=std_logger) + solver.set_up() + if not cfg.args.pretrained_model == '': + with FS.get_from(cfg.args.pretrained_model, + wait_finish=True) as local_path: + state = torch.load(local_path, map_location='cuda') + state = state['model'] if 'model' in state else state + missing, unexpected = solver.model.model.control_blocks[ + 0].load_state_dict(state, strict=False) + if we.rank == 0: + std_logger.info( + f'Restored from {cfg.args.pretrained_model} with ' + f'{len(missing)} missing and {len(unexpected)} unexpected keys' + ) + + solver.test_mode() + num_samples = cfg.args.num_samples + prompt = [cfg.args.prompt] * num_samples + n_prompt = [cfg.args.n_prompt] * num_samples + sampler = cfg.args.sampler + sample_steps = cfg.args.sample_steps + seed = cfg.args.seed + guide_scale = cfg.args.guide_scale + guide_rescale = cfg.args.guide_rescale + image_size = cfg.args.image_size + if image_size is not None: + if ',' in image_size: + h, w = image_size.split(',') + image_size = [int(h), int(w)] + else: + image_size = int(image_size) + + with FS.get_from(cfg.args.image, wait_finish=True) as local_path: + image = Image.open(local_path) + if not image.mode == 'RGB': + image = image.convert('RGB') + image = TT.CenterCrop(image_size)(TT.Resize(image_size)(image)) + + if cfg.args.control_mode != 'source': + anno_processor = AnnotatorProcessor(anno_type=cfg.args.control_mode) + hint = anno_processor.run(image, cfg.args.control_mode) + else: + hint = image + hint = TT.ToTensor()(hint)[None, ...].repeat(num_samples, 1, 1, + 1).to(we.device_id) + + batch_data = {} + if solver.sample_args: + batch_data.update(solver.sample_args.get_lowercase_dict()) + if image_size is not None: + batch_data.update({'image_size': image_size}) + batch_data.update({ + 'prompt': prompt, + 'n_prompt': n_prompt, + 'sampler': sampler, + 'sample_steps': sample_steps, + 'seed': seed, + 'guide_scale': guide_scale, + 'guide_rescale': guide_rescale, + 'hint': hint + }) + + dtype = getattr(torch, cfg.SOLVER.DTYPE) + with amp.autocast(enabled=True, dtype=dtype): + batch_data = transfer_data_to_cuda(batch_data) + ret = solver.run_step_test(batch_data) + save_folder = os.path.join(solver.work_dir, cfg.args.save_folder) + for idx, out in enumerate(ret): + for name in ['image', 'hint']: + img = out[name] + img = img.permute(1, 2, 0).cpu().numpy() + img = (img * 255).astype(np.uint8) + filename = '{}_{}_{}.png'.format('inference', name, idx) + save_file = os.path.join(save_folder, filename) + with FS.put_to(save_file) as local_path: + image = img.copy() + cv2.cvtColor(image, cv2.COLOR_RGB2BGR, image) + cv2.imwrite(local_path, image) + std_logger.info(f'Processed {filename} save to {local_path}') + + if __name__ == '__main__': parser = argparse.ArgumentParser(description='Argparser for Scepter:\n') + parser.add_argument('--task', + dest='task', + help='Running task!', + default='t2i', + choices=['t2i', 'control']) parser.add_argument( '--prompt', dest='prompt', @@ -128,5 +220,18 @@ if __name__ == '__main__': dest='pretrained_model', help='The pretrained model for our network!', default='') + parser.add_argument('--image', + dest='image', + help='For image-guided task (control, upsample)', + default='') + parser.add_argument('--control_mode', + dest='control_mode', + help='For controllable image synthesis task', + choices=['source', 'canny', 'pose'], + default=None) cfg = Config(load=True, parser_ins=parser) - we.init_env(cfg, logger=None, fn=run_task) + if cfg.args.task == 'control': + task_fn = run_task_control + else: + task_fn = run_task + we.init_env(cfg, logger=None, fn=task_fn) diff --git a/scepter/tools/run_train.py b/scepter/tools/run_train.py index 0761a9e..e369035 100644 --- a/scepter/tools/run_train.py +++ b/scepter/tools/run_train.py @@ -16,8 +16,31 @@ def run_task(cfg): solver.solve() +def update_config(cfg): + if hasattr(cfg.args, 'learning_rate') and cfg.args.learning_rate: + print( + f'learning_rate change from {cfg.SOLVER.OPTIMIZER.LEARNING_RATE} to {cfg.args.learning_rate}' + ) + cfg.SOLVER.OPTIMIZER.LEARNING_RATE = float(cfg.args.learning_rate) + if hasattr(cfg.args, 'max_steps') and cfg.args.max_steps: + print( + f'max_steps change from {cfg.SOLVER.MAX_STEPS} to {cfg.args.max_steps}' + ) + cfg.SOLVER.MAX_STEPS = int(cfg.args.max_steps) + return cfg + + if __name__ == '__main__': parser = argparse.ArgumentParser(description='Argparser for Scepter:\n') + parser.add_argument('--learning_rate', + dest='learning_rate', + help='The learning rate for our network!', + default=None) + parser.add_argument('--max_steps', + dest='max_steps', + help='The max steps for training!', + default=None) cfg = Config(load=True, parser_ins=parser) + cfg = update_config(cfg) we.init_env(cfg, logger=None, fn=run_task) diff --git a/scepter/tools/webui.py b/scepter/tools/webui.py new file mode 100644 index 0000000..ea4abd3 --- /dev/null +++ b/scepter/tools/webui.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +import argparse +import datetime +import os +import random + +import gradio as gr + +import scepter +from scepter.modules.utils.config import Config +from scepter.modules.utils.file_system import FS +from scepter.modules.utils.logger import get_logger, init_logger + + +def prepare(config): + if 'FILE_SYSTEM' in config: + for fs_info in config['FILE_SYSTEM']: + FS.init_fs_client(fs_info) + + if 'LOG_FILE' in config: + logger = get_logger() + tid = '{0:%Y%m%d%H%M%S%f}'.format(datetime.datetime.now()) + ''.join( + [str(random.randint(1, 10)) for i in range(3)]) + init_logger(logger, log_file=config['LOG_FILE'].format(tid)) + + +class TabManager(): + def __init__(self): + pass + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--cfg', + dest='config', + type=str, + default='/config/config.yaml') + parser.add_argument('--debug', + dest='debug', + action='store_true', + help='Switch debug mode.') + parser.add_argument( + '--host', + dest='host', + default=None, + help='The host of Gradio, default is set in ui config.') + parser.add_argument('--port', + dest='port', + default=None, + help='The port of Gradio.') + parser.add_argument('--language', + dest='language', + choices=['en', 'zh'], + default='en', + help='Now we only support english(en) and chinese(zh)') + args = parser.parse_args() + config = Config(load=True, cfg_file=args.config) + prepare(config) + + tab_manager = TabManager() + interfaces = [] + for info in config['INTERFACE']: + name = info.get('NAME_EN', + '') if args.language == 'en' else info['NAME'] + ifid = info['IFID'] + if not FS.exists(info['CONFIG']): + info['CONFIG'] = os.path.join(os.path.dirname(scepter.dirname), + info['CONFIG']) + if not FS.exists(info['CONFIG']): + raise f"{info['CONFIG']} doesn't exist." + interface = None + if ifid == 'home': + from scepter.studio.home.home import HomeUI + interface = HomeUI(info['CONFIG'], + is_debug=args.debug, + language=args.language, + root_work_dir=config.WORK_DIR) + if ifid == 'preprocess': + from scepter.studio.preprocess.preprocess import PreprocessUI + interface = PreprocessUI(info['CONFIG'], + is_debug=args.debug, + language=args.language, + root_work_dir=config.WORK_DIR) + if ifid == 'self_train': + from scepter.studio.self_train.self_train import SelfTrainUI + interface = SelfTrainUI(info['CONFIG'], + is_debug=args.debug, + language=args.language, + root_work_dir=config.WORK_DIR) + if ifid == 'inference': + from scepter.studio.inference.inference import InferenceUI + interface = InferenceUI(info['CONFIG'], + is_debug=args.debug, + language=args.language, + root_work_dir=config.WORK_DIR) + if ifid == '': + pass # TODO: Add New Features + if interface: + interfaces.append((interface, name, ifid)) + setattr(tab_manager, ifid, interface) + + with gr.Blocks() as demo: + if 'BANNER' in config: + gr.HTML(config.BANNER) + else: + gr.Markdown( + f"

{config.get('TITLE', 'scepter studio')}

" + ) + with gr.Tabs(elem_id='tabs') as tabs: + setattr(tab_manager, 'tabs', tabs) + for interface, label, ifid in interfaces: + with gr.TabItem(label, id=ifid, elem_id=f'tab_{ifid}'): + interface.create_ui() + for interface, label, ifid in interfaces: + interface.set_callbacks(tab_manager) + + demo.queue(status_update_rate=1).launch( + server_name=args.host if args.host else config['HOST'], + server_port=args.port if args.port else config['PORT'], + root_path=config['ROOT'], + show_error=True, + debug=True, + enable_queue=True) diff --git a/scepter/version.py b/scepter/version.py index a0d74d0..1c5ccae 100644 --- a/scepter/version.py +++ b/scepter/version.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Copyright (c) Alibaba, Inc. and its affiliates. -__version__ = '0.0.1' +__version__ = '0.0.2' version_info = tuple(int(x) for x in __version__.split('.')[0:3]) diff --git a/setup.py b/setup.py index ca3df25..c7eeeed 100644 --- a/setup.py +++ b/setup.py @@ -131,7 +131,10 @@ def restorefile(contents): required = parse_requirements() contents = backupfile() - +print([ + pkg for pkg in setuptools.find_packages() + if '__pycache__' not in pkg and 'scepter' in pkg +]) setuptools.setup( name='scepter', version=get_version(), @@ -146,6 +149,8 @@ setuptools.setup( pkg for pkg in setuptools.find_packages() if '__pycache__' not in pkg and 'scepter' in pkg ], + include_package_data=True, + # package_data={'': ['*.yaml']}, data_files=[('lib/docs', glob.glob('docs/*.md') + glob.glob('docs/*/*.md')) ], classifiers=[ diff --git a/tests/tools/test_annotators.py b/tests/tools/test_annotators.py new file mode 100644 index 0000000..631daac --- /dev/null +++ b/tests/tools/test_annotators.py @@ -0,0 +1,209 @@ +# -*- coding: utf-8 -*- +# Copyright (c) Alibaba, Inc. and its affiliates. + +import os +import unittest + +import numpy as np +from PIL import Image + +from scepter.modules.annotator.registry import ANNOTATORS +from scepter.modules.utils.config import Config +from scepter.modules.utils.distribute import we +from scepter.modules.utils.file_system import FS + + +class AnnotatorTest(unittest.TestCase): + def setUp(self): + print(('Testing %s.%s' % (type(self).__name__, self._testMethodName))) + _ = FS.init_fs_client(Config(cfg_dict={ + 'NAME': 'ModelscopeFs', + 'TEMP_DIR': './cache/data' + }, + load=False), + overwrite=False) + image_path = 'asset/images/sunflower.jpeg' + image = Image.open(image_path) + if image.mode != 'RGB': + image = image.convert('RGB') + self.image = np.array(image) + + self.save_dir = './cache/save_data/images' + if not os.path.exists(self.save_dir): + os.makedirs(self.save_dir) + + def tearDown(self): + super().tearDown() + + @unittest.skip('') + def test_annotator_canny(self): + # canny + canny_dict = { + 'NAME': 'CannyAnnotator', + 'LOW_THRESHOLD': 100, + 'HIGH_THRESHOLD': 200 + } + canny_anno = Config(cfg_dict=canny_dict, load=False) + canny_ins = ANNOTATORS.build(canny_anno).to(we.device_id) + canny_image = canny_ins(self.image) + print("canny's shape:", canny_image.shape) + Image.fromarray(canny_image).save( + os.path.join(self.save_dir, 'sunflower_canny.png')) + + @unittest.skip('') + def test_annotator_hed(self): + # hed + hed_dict = { + 'NAME': + 'HedAnnotator', + 'PRETRAINED_MODEL': + 'ms://damo/scepter_scedit@annotator/ckpts/ControlNetHED.pth' + } + hed_anno = Config(cfg_dict=hed_dict, load=False) + hed_ins = ANNOTATORS.build(hed_anno).to(we.device_id) + hed_image = hed_ins(self.image) + print("hed's shape:", hed_image.shape) + Image.fromarray(hed_image).save( + os.path.join(self.save_dir, 'sunflower_hed.png')) + + @unittest.skip('') + def test_annotator_openpose(self): + # openpose + openpose_dict = { + 'NAME': + 'OpenposeAnnotator', + 'BODY_MODEL_PATH': + 'ms://damo/scepter_scedit@annotator/ckpts/body_pose_model.pth', + 'HAND_MODEL_PATH': + 'ms://damo/scepter_scedit@annotator/ckpts/hand_pose_model.pth' + } + openpose_anno = Config(cfg_dict=openpose_dict, load=False) + openpose_ins = ANNOTATORS.build(openpose_anno).to(we.device_id) + openpose_image = openpose_ins(self.image) + print("openpose's shape:", openpose_image.shape) + Image.fromarray(openpose_image).save( + os.path.join(self.save_dir, 'sunflower_openpose.png')) + + @unittest.skip('') + def test_annotator_midas(self): + # midas + midas_dict = { + 'NAME': 'MidasDetector', + 'PRETRAINED_MODEL': + 'ms://damo/scepter_scedit@annotator/ckpts/dpt_hybrid-midas-501f0c75.pt', + 'A': 6.2, + 'BG_TH': 0.1 + } + midas_anno = Config(cfg_dict=midas_dict, load=False) + midas_ins = ANNOTATORS.build(midas_anno).to(we.device_id) + midas_image = midas_ins(self.image) + print("midas's shape:", midas_image.shape) + Image.fromarray(midas_image).save( + os.path.join(self.save_dir, 'sunflower_midas.png')) + + @unittest.skip('') + def test_annotator_mlsd(self): + # mlsd + mlsd_dict = { + 'NAME': 'MLSDdetector', + 'PRETRAINED_MODEL': + 'ms://damo/scepter_scedit@annotator/ckpts/mlsd_large_512_fp32.pth', + 'THR_V': 0.1, + 'THR_D': 0.1 + } + mlsd_anno = Config(cfg_dict=mlsd_dict, load=False) + mlsd_ins = ANNOTATORS.build(mlsd_anno).to(we.device_id) + mlsd_image = mlsd_ins(self.image) + print("mlsd's shape:", mlsd_image.shape) + Image.fromarray(mlsd_image).save( + os.path.join(self.save_dir, 'sunflower_mlsd.png')) + + @unittest.skip('') + def test_annotator_color(self): + # color + color_dict = {'NAME': 'ColorAnnotator', 'RATIO': 64} + color_anno = Config(cfg_dict=color_dict, load=False) + color_ins = ANNOTATORS.build(color_anno).to(we.device_id) + color_image = color_ins(self.image) + print("color's shape:", color_image.shape) + Image.fromarray(color_image).save( + os.path.join(self.save_dir, 'sunflower_color.png')) + + @unittest.skip('') + def test_annotator_multi(self): + # multi annotators + canny_dict = { + 'NAME': 'CannyAnnotator', + 'LOW_THRESHOLD': 100, + 'HIGH_THRESHOLD': 200, + 'INPUT_KEYS': ['img'], + 'OUTPUT_KEYS': ['canny_img'] + } + hed_dict = { + 'NAME': 'HedAnnotator', + 'PRETRAINED_MODEL': + 'ms://damo/scepter_scedit@annotator/ckpts/ControlNetHED.pth', + 'INPUT_KEYS': ['img'], + 'OUTPUT_KEYS': ['hed_img'] + } + openpose_dict = { + 'NAME': 'OpenposeAnnotator', + 'BODY_MODEL_PATH': + 'ms://damo/scepter_scedit@annotator/ckpts/body_pose_model.pth', + 'HAND_MODEL_PATH': + 'ms://damo/scepter_scedit@annotator/ckpts/hand_pose_model.pth', + 'INPUT_KEYS': ['img'], + 'OUTPUT_KEYS': ['openpose_img'] + } + midas_dict = { + 'NAME': 'MidasDetector', + 'PRETRAINED_MODEL': + 'ms://damo/scepter_scedit@annotator/ckpts/dpt_hybrid-midas-501f0c75.pt', + 'INPUT_KEYS': ['img'], + 'OUTPUT_KEYS': ['midas_img'] + } + mlsd_dict = { + 'NAME': 'MLSDdetector', + 'PRETRAINED_MODEL': + 'ms://damo/scepter_scedit@annotator/ckpts/mlsd_large_512_fp32.pth', + 'INPUT_KEYS': ['img'], + 'OUTPUT_KEYS': ['mlsd_img'] + } + color_dict = {'NAME': 'ColorAnnotator', 'RATIO': 64} + general_dict = { + 'NAME': + 'GeneralAnnotator', + 'ANNOTATORS': [ + canny_dict, hed_dict, openpose_dict, midas_dict, mlsd_dict, + color_dict + ] + } + general_anno = Config(cfg_dict=general_dict, load=False) + general_ins = ANNOTATORS.build(general_anno).to(we.device_id) + output_image = general_ins({'img': self.image}) + for key, save_image in output_image.items(): + Image.fromarray(save_image).save( + os.path.join(self.save_dir, f'sunflower_multi_{key}.png')) + + # @unittest.skip('') + def test_annotator_processor(self): + from scepter.modules.annotator.utils import AnnotatorProcessor + anno_processor = AnnotatorProcessor(anno_type='hed') + output_image = anno_processor.run(self.image, 'hed') + Image.fromarray(output_image).save( + os.path.join(self.save_dir, 'sunflower_processor_hed.png')) + + anno_processor = AnnotatorProcessor( + anno_type=['canny', 'color', 'depth']) + output_image = anno_processor.run(self.image, 'color') + Image.fromarray(output_image).save( + os.path.join(self.save_dir, 'sunflower_processor_color.png')) + + output_image = anno_processor.run(self.image, ['canny', 'depth']) + for key, save_image in output_image.items(): + Image.fromarray(save_image).save( + os.path.join(self.save_dir, f'sunflower_processor_{key}.png')) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/tools/test_inference.py b/tests/tools/test_inference.py index 1462e49..e77f133 100644 --- a/tests/tools/test_inference.py +++ b/tests/tools/test_inference.py @@ -12,53 +12,171 @@ class InferenceTest(unittest.TestCase): def tearDown(self): super().tearDown() - # @unittest.skip('') + @unittest.skip('') def test_infer_args(self): - os.system("python scepter/tools/run_inference.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml " - "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_2023'") - os.system("python scepter/tools/run_inference.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml " - "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_2024' --seed 2024") - os.system("python scepter/tools/run_inference.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml " - "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_size768' " - "--image_size '768'") - os.system("python scepter/tools/run_inference.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml " - "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_1280_720' " - "--image_size '1280,720'") - os.system("python scepter/tools/run_inference.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml " - "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_720_1280_step10' " - "--image_size '720,1280' --sample_steps 10") - os.system("python scepter/tools/run_inference.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml " - "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_num2' --num_samples 2") - os.system("python scepter/tools/run_inference.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml " - "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_dpmpp_2s_ancestral' " - "--sampler 'dpmpp_2s_ancestral'") - os.system("python scepter/tools/run_inference.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml " - "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_scale5' " - "--guide_scale 5.0") - os.system("python scepter/tools/run_inference.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml " - "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_rescale0_1' " - "--guide_rescale 0.1") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml ' + "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_2023'" + ) + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml ' + "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_2024' --seed 2024" + ) + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml ' + "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_size768' " + "--image_size '768'") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml ' + "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_1280_720' " + "--image_size '1280,720'") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml ' + "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_720_1280_step10' " + "--image_size '720,1280' --sample_steps 10") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml ' + "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_num2' --num_samples 2" + ) + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml ' + "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_dpmpp_2s_ancestral' " + "--sampler 'dpmpp_2s_ancestral'") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml ' + "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_scale5' " + '--guide_scale 5.0') + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml ' + "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog_rescale0_1' " + '--guide_rescale 0.1') + + @unittest.skip('') + def test_example_infer(self): + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml ' + "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog'") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_2.1_768.yaml ' + "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog'") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_xl_1024.yaml ' + "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog'") + + @unittest.skip('') + def test_trained_infer(self): + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml ' + "--pretrained_model 'cache/save_data/sd15_512_full/checkpoints/ldm_step-100.pth' " + "--prompt 'A close up of a small rabbit wearing a hat and scarf' " + "--save_folder 'trained_test_prompt_rabbit' ") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_2.1_768.yaml ' + "--pretrained_model 'cache/save_data/sd21_768_full/checkpoints/ldm_step-100.pth' " + "--prompt 'A close up of a small rabbit wearing a hat and scarf' " + "--save_folder 'trained_test_prompt_rabbit' ") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_xl_1024.yaml --guide_scale 5.0 ' + "--pretrained_model 'cache/save_data/sdxl_1024_full/checkpoints/ldm_step-100.pth' " + "--prompt 'A close up of a small rabbit wearing a hat and scarf' " + "--save_folder 'trained_test_prompt_rabbit' ") + + @unittest.skip('') + def test_trained_tuning_infer(self): + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512_lora.yaml ' + "--pretrained_model 'cache/save_data/sd15_512_lora/checkpoints/ldm_step-100.pth' " + "--prompt 'A close up of a small rabbit wearing a hat and scarf' " + "--save_folder 'trained_test_prompt_rabbit' ") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_2.1_768_lora.yaml ' + "--pretrained_model 'cache/save_data/sd21_768_lora/checkpoints/ldm_step-100.pth' " + "--prompt 'A close up of a small rabbit wearing a hat and scarf' " + "--save_folder 'trained_test_prompt_rabbit' ") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_xl_1024_lora.yaml ' + "--pretrained_model 'cache/save_data/sdxl_1024_lora/checkpoints/ldm_step-100.pth' " + "--prompt 'A close up of a small rabbit wearing a hat and scarf' " + "--save_folder 'trained_test_prompt_rabbit' ") + + @unittest.skip('') + def test_trained_scedit_infer(self): + # swift + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/scedit/t2i/sd15_512_sce_t2i_swift.yaml ' + "--pretrained_model 'cache/save_data/sd15_512_sce_t2i_swift/checkpoints/ldm_step-100.pth' " + "--prompt 'A close up of a small rabbit wearing a hat and scarf' " + "--save_folder 'trained_test_prompt_rabbit' ") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/scedit/t2i/sd21_768_sce_t2i_swift.yaml ' + "--pretrained_model 'cache/save_data/sd21_768_sce_t2i_swift/checkpoints/ldm_step-100.pth' " + "--prompt 'A close up of a small rabbit wearing a hat and scarf' " + "--save_folder 'trained_test_prompt_rabbit' ") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/scedit/t2i/sdxl_1024_sce_t2i_swift.yaml ' + "--pretrained_model 'cache/save_data/sdxl_1024_sce_t2i_swift/checkpoints/ldm_step-100.pth' " + "--prompt 'A close up of a small rabbit wearing a hat and scarf' " + "--save_folder 'trained_test_prompt_rabbit' ") + # original + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/scedit/t2i/sd15_512_sce_t2i.yaml ' + "--pretrained_model 'cache/save_data/sd15_512_sce_t2i/checkpoints/ldm_step-100.pth' " + "--prompt 'A close up of a small rabbit wearing a hat and scarf' " + "--save_folder 'trained_test_prompt_rabbit' ") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/scedit/t2i/sd21_768_sce_t2i.yaml ' + "--pretrained_model 'cache/save_data/sd21_768_sce_t2i/checkpoints/ldm_step-100.pth' " + "--prompt 'A close up of a small rabbit wearing a hat and scarf' " + "--save_folder 'trained_test_prompt_rabbit' ") + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/scedit/t2i/sdxl_1024_sce_t2i.yaml ' + "--pretrained_model 'cache/save_data/sdxl_1024_sce_t2i/checkpoints/ldm_step-100.pth' " + "--prompt 'A close up of a small rabbit wearing a hat and scarf' " + "--save_folder 'trained_test_prompt_rabbit' ") # @unittest.skip('') - def test_example_infer(self): - os.system("python scepter/tools/run_inference.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml " - "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog'") - os.system("python scepter/tools/run_inference.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_2.1_768.yaml " - "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog'") - os.system("python scepter/tools/run_inference.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_xl_1024.yaml " - "--prompt 'a cute dog' --save_folder 'test_prompt_a_cute_dog'") + def test_pretrained_scedit_control_infer(self): + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/scedit/ctr/sd21_768_sce_ctr_canny.yaml --num_samples 1 ' + "--prompt 'a single flower is shown in front of a tree' --save_folder 'test_flower_canny' " + "--image_size 768 --task control --image 'asset/images/flower.jpg' --control_mode canny " + '--pretrained_model ' + 'ms://damo/scepter_scedit@controllable_model/SD2.1/canny_control/0_SwiftSCETuning/pytorch_model.bin' + ) + + os.system( + 'python scepter/tools/run_inference.py ' + '--cfg scepter/methods/scedit/ctr/sd21_768_sce_ctr_pose.yaml --num_samples 1 ' + "--prompt 'super mario' --save_folder 'test_mario_pose' " + "--image_size 768 --task control --image 'asset/images/pose_source.png' --control_mode source " + '--pretrained_model ' + 'ms://damo/scepter_scedit@controllable_model/SD2.1/pose_control/0_SwiftSCETuning/pytorch_model.bin' + ) if __name__ == '__main__': diff --git a/tests/tools/test_train.py b/tests/tools/test_train.py index 7f0216c..0752644 100644 --- a/tests/tools/test_train.py +++ b/tests/tools/test_train.py @@ -8,37 +8,178 @@ import unittest class TrainTest(unittest.TestCase): def setUp(self): print(('Testing %s.%s' % (type(self).__name__, self._testMethodName))) + self.tmp_dir = './cache/save_data' def tearDown(self): super().tearDown() - # @unittest.skip('') + @unittest.skip('') def test_generation_example_full(self): - os.system("python scepter/tools/run_train.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml ") - os.system("python scepter/tools/run_train.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_2.1_768.yaml ") - os.system("python scepter/tools/run_train.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_xl_1024.yaml ") - - # @unittest.skip('') + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, 'sd15_512_full/checkpoints'))) + + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_2.1_768.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, 'sd21_768_full/checkpoints'))) + + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_xl_1024.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, 'sdxl_1024_full/checkpoints'))) + + @unittest.skip('') def test_generation_example_lora(self): - os.system("python scepter/tools/run_train.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512_lora.yaml ") - os.system("python scepter/tools/run_train.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_2.1_768_lora.yaml ") - os.system("python scepter/tools/run_train.py " - "--cfg scepter/methods/examples/generation/stable_diffusion_xl_1024_lora.yaml ") - + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_1.5_512_lora.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, 'sd15_512_lora/checkpoints'))) + + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_2.1_768_lora.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, 'sd21_768_lora/checkpoints'))) + + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/examples/generation/stable_diffusion_xl_1024_lora.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, 'sdxl_1024_lora/checkpoints'))) + + @unittest.skip('') + def test_generation_example_scedit_t2i_swift(self): + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/scedit/t2i/sd15_512_sce_t2i_swift.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, + 'sd15_512_sce_t2i_swift/checkpoints'))) + + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/scedit/t2i/sd21_768_sce_t2i_swift.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, + 'sd21_768_sce_t2i_swift/checkpoints'))) + + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/scedit/t2i/sdxl_1024_sce_t2i_swift.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, + 'sdxl_1024_sce_t2i_swift/checkpoints'))) + + @unittest.skip('') + def test_generation_example_scedit_t2i(self): + os.system('python scepter/tools/run_train.py ' + '--cfg scepter/methods/scedit/t2i/sd15_512_sce_t2i.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, 'sd15_512_sce_t2i/checkpoints'))) + + os.system('python scepter/tools/run_train.py ' + '--cfg scepter/methods/scedit/t2i/sd21_768_sce_t2i.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, 'sd21_768_sce_t2i/checkpoints'))) + + os.system('python scepter/tools/run_train.py ' + '--cfg scepter/methods/scedit/t2i/sdxl_1024_sce_t2i.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, 'sdxl_1024_sce_t2i/checkpoints'))) + + @unittest.skip('') + def test_generation_example_scedit_ctr(self): + os.system('python scepter/tools/run_train.py ' + '--cfg scepter/methods/scedit/ctr/sd15_512_sce_ctr_hed.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, + 'sd15_512_sce_ctr_hed/checkpoints'))) + + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/scedit/ctr/sd21_768_sce_ctr_canny.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, + 'sd21_768_sce_ctr_canny/checkpoints'))) + + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/scedit/ctr/sd21_768_sce_ctr_pose.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, + 'sd21_768_sce_ctr_pose/checkpoints'))) + + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_depth.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, + 'sdxl_1024_sce_ctr_depth/checkpoints'))) + + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_color.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, + 'sdxl_1024_sce_ctr_color/checkpoints'))) + # @unittest.skip('') - def test_generation_example_scedit(self): - os.system("python scepter/tools/run_train.py " - "--cfg scepter/methods/SCEdit/t2i_sd15_512_sce.yaml ") - os.system("python scepter/tools/run_train.py " - "--cfg scepter/methods/SCEdit/t2i_sd21_768_sce.yaml ") - os.system("python scepter/tools/run_train.py " - "--cfg scepter/methods/SCEdit/t2i_sdxl_1024_sce.yaml ") - + def test_generation_example_datatxt(self): + # os.system( + # 'python scepter/tools/run_train.py ' + # '--cfg scepter/methods/scedit/t2i/sdxl_1024_sce_t2i_datatxt.yaml ' + # '--max_steps 100' + # ) + # self.assertTrue(os.path.exists(os.path.join(self.tmp_dir, 'sdxl_1024_sce_t2i_datatxt/checkpoints'))) + + os.system( + 'python scepter/tools/run_train.py ' + '--cfg scepter/methods/scedit/ctr/sdxl_1024_sce_ctr_color_datatxt.yaml ' + '--max_steps 100') + self.assertTrue( + os.path.exists( + os.path.join(self.tmp_dir, + 'sdxl_1024_sce_ctr_color_datatxt/checkpoints'))) if __name__ == '__main__': diff --git a/tests/utils/test_fs.py b/tests/utils/test_fs.py index 969ba93..3286b65 100644 --- a/tests/utils/test_fs.py +++ b/tests/utils/test_fs.py @@ -45,6 +45,11 @@ class FSTest(unittest.TestCase): print(f'Download from {path} to {local_path}') self.assertTrue(os.path.exists(local_path)) + path = 'ms://AI-ModelScope/clip-vit-large-patch14' + with FS.get_dir_to_local_dir(path, wait_finish=True) as local_path: + print(f'Download from {path} to {local_path}') + self.assertTrue(os.path.exists(local_path)) + if __name__ == '__main__': unittest.main()