Spaces:
Running on Zero
Running on Zero
Migrated files batch 32
Browse files- diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_1/special_tokens_map.json +30 -0
- diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_1/tokenizer_config.json +30 -0
- diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_1/vocab.json +0 -0
- diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_2/merges.txt +0 -0
- diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_2/special_tokens_map.json +30 -0
- diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_2/tokenizer_config.json +38 -0
- diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_2/vocab.json +0 -0
- diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_3/special_tokens_map.json +125 -0
- diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_3/spiece.model +3 -0
- diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_3/tokenizer.json +0 -0
- diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_3/tokenizer_config.json +940 -0
- diffsynth/tokenizer_configs/stable_diffusion_xl/tokenizer_2/merges.txt +0 -0
- diffsynth/tokenizer_configs/stable_diffusion_xl/tokenizer_2/special_tokens_map.json +24 -0
- diffsynth/tokenizer_configs/stable_diffusion_xl/tokenizer_2/tokenizer_config.json +38 -0
- diffsynth/tokenizer_configs/stable_diffusion_xl/tokenizer_2/vocab.json +0 -0
- diffsynth/trainers/__init__.py +0 -0
- diffsynth/trainers/text_to_image.py +318 -0
- diffsynth/trainers/utils.py +506 -0
- diffsynth/utils/__init__.py +261 -0
- diffsynth/vram_management/__init__.py +2 -0
- diffsynth/vram_management/gradient_checkpointing.py +34 -0
- diffsynth/vram_management/layers.py +167 -0
- third_party/Optional.md +0 -0
- tools/full_inference_modules_gradio.sh +162 -0
- tools/process_env_maps.py +599 -0
- tools/reorg_gbuffer_from_dr_delighting.py +129 -0
diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_1/special_tokens_map.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"bos_token": {
|
| 3 |
+
"content": "<|startoftext|>",
|
| 4 |
+
"lstrip": false,
|
| 5 |
+
"normalized": true,
|
| 6 |
+
"rstrip": false,
|
| 7 |
+
"single_word": false
|
| 8 |
+
},
|
| 9 |
+
"eos_token": {
|
| 10 |
+
"content": "<|endoftext|>",
|
| 11 |
+
"lstrip": false,
|
| 12 |
+
"normalized": false,
|
| 13 |
+
"rstrip": false,
|
| 14 |
+
"single_word": false
|
| 15 |
+
},
|
| 16 |
+
"pad_token": {
|
| 17 |
+
"content": "<|endoftext|>",
|
| 18 |
+
"lstrip": false,
|
| 19 |
+
"normalized": false,
|
| 20 |
+
"rstrip": false,
|
| 21 |
+
"single_word": false
|
| 22 |
+
},
|
| 23 |
+
"unk_token": {
|
| 24 |
+
"content": "<|endoftext|>",
|
| 25 |
+
"lstrip": false,
|
| 26 |
+
"normalized": false,
|
| 27 |
+
"rstrip": false,
|
| 28 |
+
"single_word": false
|
| 29 |
+
}
|
| 30 |
+
}
|
diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_1/tokenizer_config.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": false,
|
| 3 |
+
"added_tokens_decoder": {
|
| 4 |
+
"49406": {
|
| 5 |
+
"content": "<|startoftext|>",
|
| 6 |
+
"lstrip": false,
|
| 7 |
+
"normalized": true,
|
| 8 |
+
"rstrip": false,
|
| 9 |
+
"single_word": false,
|
| 10 |
+
"special": true
|
| 11 |
+
},
|
| 12 |
+
"49407": {
|
| 13 |
+
"content": "<|endoftext|>",
|
| 14 |
+
"lstrip": false,
|
| 15 |
+
"normalized": false,
|
| 16 |
+
"rstrip": false,
|
| 17 |
+
"single_word": false,
|
| 18 |
+
"special": true
|
| 19 |
+
}
|
| 20 |
+
},
|
| 21 |
+
"bos_token": "<|startoftext|>",
|
| 22 |
+
"clean_up_tokenization_spaces": true,
|
| 23 |
+
"do_lower_case": true,
|
| 24 |
+
"eos_token": "<|endoftext|>",
|
| 25 |
+
"errors": "replace",
|
| 26 |
+
"model_max_length": 77,
|
| 27 |
+
"pad_token": "<|endoftext|>",
|
| 28 |
+
"tokenizer_class": "CLIPTokenizer",
|
| 29 |
+
"unk_token": "<|endoftext|>"
|
| 30 |
+
}
|
diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_1/vocab.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_2/merges.txt
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_2/special_tokens_map.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"bos_token": {
|
| 3 |
+
"content": "<|startoftext|>",
|
| 4 |
+
"lstrip": false,
|
| 5 |
+
"normalized": true,
|
| 6 |
+
"rstrip": false,
|
| 7 |
+
"single_word": false
|
| 8 |
+
},
|
| 9 |
+
"eos_token": {
|
| 10 |
+
"content": "<|endoftext|>",
|
| 11 |
+
"lstrip": false,
|
| 12 |
+
"normalized": false,
|
| 13 |
+
"rstrip": false,
|
| 14 |
+
"single_word": false
|
| 15 |
+
},
|
| 16 |
+
"pad_token": {
|
| 17 |
+
"content": "!",
|
| 18 |
+
"lstrip": false,
|
| 19 |
+
"normalized": false,
|
| 20 |
+
"rstrip": false,
|
| 21 |
+
"single_word": false
|
| 22 |
+
},
|
| 23 |
+
"unk_token": {
|
| 24 |
+
"content": "<|endoftext|>",
|
| 25 |
+
"lstrip": false,
|
| 26 |
+
"normalized": false,
|
| 27 |
+
"rstrip": false,
|
| 28 |
+
"single_word": false
|
| 29 |
+
}
|
| 30 |
+
}
|
diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_2/tokenizer_config.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": false,
|
| 3 |
+
"added_tokens_decoder": {
|
| 4 |
+
"0": {
|
| 5 |
+
"content": "!",
|
| 6 |
+
"lstrip": false,
|
| 7 |
+
"normalized": false,
|
| 8 |
+
"rstrip": false,
|
| 9 |
+
"single_word": false,
|
| 10 |
+
"special": true
|
| 11 |
+
},
|
| 12 |
+
"49406": {
|
| 13 |
+
"content": "<|startoftext|>",
|
| 14 |
+
"lstrip": false,
|
| 15 |
+
"normalized": true,
|
| 16 |
+
"rstrip": false,
|
| 17 |
+
"single_word": false,
|
| 18 |
+
"special": true
|
| 19 |
+
},
|
| 20 |
+
"49407": {
|
| 21 |
+
"content": "<|endoftext|>",
|
| 22 |
+
"lstrip": false,
|
| 23 |
+
"normalized": false,
|
| 24 |
+
"rstrip": false,
|
| 25 |
+
"single_word": false,
|
| 26 |
+
"special": true
|
| 27 |
+
}
|
| 28 |
+
},
|
| 29 |
+
"bos_token": "<|startoftext|>",
|
| 30 |
+
"clean_up_tokenization_spaces": true,
|
| 31 |
+
"do_lower_case": true,
|
| 32 |
+
"eos_token": "<|endoftext|>",
|
| 33 |
+
"errors": "replace",
|
| 34 |
+
"model_max_length": 77,
|
| 35 |
+
"pad_token": "!",
|
| 36 |
+
"tokenizer_class": "CLIPTokenizer",
|
| 37 |
+
"unk_token": "<|endoftext|>"
|
| 38 |
+
}
|
diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_2/vocab.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_3/special_tokens_map.json
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"additional_special_tokens": [
|
| 3 |
+
"<extra_id_0>",
|
| 4 |
+
"<extra_id_1>",
|
| 5 |
+
"<extra_id_2>",
|
| 6 |
+
"<extra_id_3>",
|
| 7 |
+
"<extra_id_4>",
|
| 8 |
+
"<extra_id_5>",
|
| 9 |
+
"<extra_id_6>",
|
| 10 |
+
"<extra_id_7>",
|
| 11 |
+
"<extra_id_8>",
|
| 12 |
+
"<extra_id_9>",
|
| 13 |
+
"<extra_id_10>",
|
| 14 |
+
"<extra_id_11>",
|
| 15 |
+
"<extra_id_12>",
|
| 16 |
+
"<extra_id_13>",
|
| 17 |
+
"<extra_id_14>",
|
| 18 |
+
"<extra_id_15>",
|
| 19 |
+
"<extra_id_16>",
|
| 20 |
+
"<extra_id_17>",
|
| 21 |
+
"<extra_id_18>",
|
| 22 |
+
"<extra_id_19>",
|
| 23 |
+
"<extra_id_20>",
|
| 24 |
+
"<extra_id_21>",
|
| 25 |
+
"<extra_id_22>",
|
| 26 |
+
"<extra_id_23>",
|
| 27 |
+
"<extra_id_24>",
|
| 28 |
+
"<extra_id_25>",
|
| 29 |
+
"<extra_id_26>",
|
| 30 |
+
"<extra_id_27>",
|
| 31 |
+
"<extra_id_28>",
|
| 32 |
+
"<extra_id_29>",
|
| 33 |
+
"<extra_id_30>",
|
| 34 |
+
"<extra_id_31>",
|
| 35 |
+
"<extra_id_32>",
|
| 36 |
+
"<extra_id_33>",
|
| 37 |
+
"<extra_id_34>",
|
| 38 |
+
"<extra_id_35>",
|
| 39 |
+
"<extra_id_36>",
|
| 40 |
+
"<extra_id_37>",
|
| 41 |
+
"<extra_id_38>",
|
| 42 |
+
"<extra_id_39>",
|
| 43 |
+
"<extra_id_40>",
|
| 44 |
+
"<extra_id_41>",
|
| 45 |
+
"<extra_id_42>",
|
| 46 |
+
"<extra_id_43>",
|
| 47 |
+
"<extra_id_44>",
|
| 48 |
+
"<extra_id_45>",
|
| 49 |
+
"<extra_id_46>",
|
| 50 |
+
"<extra_id_47>",
|
| 51 |
+
"<extra_id_48>",
|
| 52 |
+
"<extra_id_49>",
|
| 53 |
+
"<extra_id_50>",
|
| 54 |
+
"<extra_id_51>",
|
| 55 |
+
"<extra_id_52>",
|
| 56 |
+
"<extra_id_53>",
|
| 57 |
+
"<extra_id_54>",
|
| 58 |
+
"<extra_id_55>",
|
| 59 |
+
"<extra_id_56>",
|
| 60 |
+
"<extra_id_57>",
|
| 61 |
+
"<extra_id_58>",
|
| 62 |
+
"<extra_id_59>",
|
| 63 |
+
"<extra_id_60>",
|
| 64 |
+
"<extra_id_61>",
|
| 65 |
+
"<extra_id_62>",
|
| 66 |
+
"<extra_id_63>",
|
| 67 |
+
"<extra_id_64>",
|
| 68 |
+
"<extra_id_65>",
|
| 69 |
+
"<extra_id_66>",
|
| 70 |
+
"<extra_id_67>",
|
| 71 |
+
"<extra_id_68>",
|
| 72 |
+
"<extra_id_69>",
|
| 73 |
+
"<extra_id_70>",
|
| 74 |
+
"<extra_id_71>",
|
| 75 |
+
"<extra_id_72>",
|
| 76 |
+
"<extra_id_73>",
|
| 77 |
+
"<extra_id_74>",
|
| 78 |
+
"<extra_id_75>",
|
| 79 |
+
"<extra_id_76>",
|
| 80 |
+
"<extra_id_77>",
|
| 81 |
+
"<extra_id_78>",
|
| 82 |
+
"<extra_id_79>",
|
| 83 |
+
"<extra_id_80>",
|
| 84 |
+
"<extra_id_81>",
|
| 85 |
+
"<extra_id_82>",
|
| 86 |
+
"<extra_id_83>",
|
| 87 |
+
"<extra_id_84>",
|
| 88 |
+
"<extra_id_85>",
|
| 89 |
+
"<extra_id_86>",
|
| 90 |
+
"<extra_id_87>",
|
| 91 |
+
"<extra_id_88>",
|
| 92 |
+
"<extra_id_89>",
|
| 93 |
+
"<extra_id_90>",
|
| 94 |
+
"<extra_id_91>",
|
| 95 |
+
"<extra_id_92>",
|
| 96 |
+
"<extra_id_93>",
|
| 97 |
+
"<extra_id_94>",
|
| 98 |
+
"<extra_id_95>",
|
| 99 |
+
"<extra_id_96>",
|
| 100 |
+
"<extra_id_97>",
|
| 101 |
+
"<extra_id_98>",
|
| 102 |
+
"<extra_id_99>"
|
| 103 |
+
],
|
| 104 |
+
"eos_token": {
|
| 105 |
+
"content": "</s>",
|
| 106 |
+
"lstrip": false,
|
| 107 |
+
"normalized": false,
|
| 108 |
+
"rstrip": false,
|
| 109 |
+
"single_word": false
|
| 110 |
+
},
|
| 111 |
+
"pad_token": {
|
| 112 |
+
"content": "<pad>",
|
| 113 |
+
"lstrip": false,
|
| 114 |
+
"normalized": false,
|
| 115 |
+
"rstrip": false,
|
| 116 |
+
"single_word": false
|
| 117 |
+
},
|
| 118 |
+
"unk_token": {
|
| 119 |
+
"content": "<unk>",
|
| 120 |
+
"lstrip": false,
|
| 121 |
+
"normalized": false,
|
| 122 |
+
"rstrip": false,
|
| 123 |
+
"single_word": false
|
| 124 |
+
}
|
| 125 |
+
}
|
diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_3/spiece.model
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d60acb128cf7b7f2536e8f38a5b18a05535c9e14c7a355904270e15b0945ea86
|
| 3 |
+
size 791656
|
diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_3/tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
diffsynth/tokenizer_configs/stable_diffusion_3/tokenizer_3/tokenizer_config.json
ADDED
|
@@ -0,0 +1,940 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": true,
|
| 3 |
+
"added_tokens_decoder": {
|
| 4 |
+
"0": {
|
| 5 |
+
"content": "<pad>",
|
| 6 |
+
"lstrip": false,
|
| 7 |
+
"normalized": false,
|
| 8 |
+
"rstrip": false,
|
| 9 |
+
"single_word": false,
|
| 10 |
+
"special": true
|
| 11 |
+
},
|
| 12 |
+
"1": {
|
| 13 |
+
"content": "</s>",
|
| 14 |
+
"lstrip": false,
|
| 15 |
+
"normalized": false,
|
| 16 |
+
"rstrip": false,
|
| 17 |
+
"single_word": false,
|
| 18 |
+
"special": true
|
| 19 |
+
},
|
| 20 |
+
"2": {
|
| 21 |
+
"content": "<unk>",
|
| 22 |
+
"lstrip": false,
|
| 23 |
+
"normalized": false,
|
| 24 |
+
"rstrip": false,
|
| 25 |
+
"single_word": false,
|
| 26 |
+
"special": true
|
| 27 |
+
},
|
| 28 |
+
"32000": {
|
| 29 |
+
"content": "<extra_id_99>",
|
| 30 |
+
"lstrip": true,
|
| 31 |
+
"normalized": false,
|
| 32 |
+
"rstrip": true,
|
| 33 |
+
"single_word": false,
|
| 34 |
+
"special": true
|
| 35 |
+
},
|
| 36 |
+
"32001": {
|
| 37 |
+
"content": "<extra_id_98>",
|
| 38 |
+
"lstrip": true,
|
| 39 |
+
"normalized": false,
|
| 40 |
+
"rstrip": true,
|
| 41 |
+
"single_word": false,
|
| 42 |
+
"special": true
|
| 43 |
+
},
|
| 44 |
+
"32002": {
|
| 45 |
+
"content": "<extra_id_97>",
|
| 46 |
+
"lstrip": true,
|
| 47 |
+
"normalized": false,
|
| 48 |
+
"rstrip": true,
|
| 49 |
+
"single_word": false,
|
| 50 |
+
"special": true
|
| 51 |
+
},
|
| 52 |
+
"32003": {
|
| 53 |
+
"content": "<extra_id_96>",
|
| 54 |
+
"lstrip": true,
|
| 55 |
+
"normalized": false,
|
| 56 |
+
"rstrip": true,
|
| 57 |
+
"single_word": false,
|
| 58 |
+
"special": true
|
| 59 |
+
},
|
| 60 |
+
"32004": {
|
| 61 |
+
"content": "<extra_id_95>",
|
| 62 |
+
"lstrip": true,
|
| 63 |
+
"normalized": false,
|
| 64 |
+
"rstrip": true,
|
| 65 |
+
"single_word": false,
|
| 66 |
+
"special": true
|
| 67 |
+
},
|
| 68 |
+
"32005": {
|
| 69 |
+
"content": "<extra_id_94>",
|
| 70 |
+
"lstrip": true,
|
| 71 |
+
"normalized": false,
|
| 72 |
+
"rstrip": true,
|
| 73 |
+
"single_word": false,
|
| 74 |
+
"special": true
|
| 75 |
+
},
|
| 76 |
+
"32006": {
|
| 77 |
+
"content": "<extra_id_93>",
|
| 78 |
+
"lstrip": true,
|
| 79 |
+
"normalized": false,
|
| 80 |
+
"rstrip": true,
|
| 81 |
+
"single_word": false,
|
| 82 |
+
"special": true
|
| 83 |
+
},
|
| 84 |
+
"32007": {
|
| 85 |
+
"content": "<extra_id_92>",
|
| 86 |
+
"lstrip": true,
|
| 87 |
+
"normalized": false,
|
| 88 |
+
"rstrip": true,
|
| 89 |
+
"single_word": false,
|
| 90 |
+
"special": true
|
| 91 |
+
},
|
| 92 |
+
"32008": {
|
| 93 |
+
"content": "<extra_id_91>",
|
| 94 |
+
"lstrip": true,
|
| 95 |
+
"normalized": false,
|
| 96 |
+
"rstrip": true,
|
| 97 |
+
"single_word": false,
|
| 98 |
+
"special": true
|
| 99 |
+
},
|
| 100 |
+
"32009": {
|
| 101 |
+
"content": "<extra_id_90>",
|
| 102 |
+
"lstrip": true,
|
| 103 |
+
"normalized": false,
|
| 104 |
+
"rstrip": true,
|
| 105 |
+
"single_word": false,
|
| 106 |
+
"special": true
|
| 107 |
+
},
|
| 108 |
+
"32010": {
|
| 109 |
+
"content": "<extra_id_89>",
|
| 110 |
+
"lstrip": true,
|
| 111 |
+
"normalized": false,
|
| 112 |
+
"rstrip": true,
|
| 113 |
+
"single_word": false,
|
| 114 |
+
"special": true
|
| 115 |
+
},
|
| 116 |
+
"32011": {
|
| 117 |
+
"content": "<extra_id_88>",
|
| 118 |
+
"lstrip": true,
|
| 119 |
+
"normalized": false,
|
| 120 |
+
"rstrip": true,
|
| 121 |
+
"single_word": false,
|
| 122 |
+
"special": true
|
| 123 |
+
},
|
| 124 |
+
"32012": {
|
| 125 |
+
"content": "<extra_id_87>",
|
| 126 |
+
"lstrip": true,
|
| 127 |
+
"normalized": false,
|
| 128 |
+
"rstrip": true,
|
| 129 |
+
"single_word": false,
|
| 130 |
+
"special": true
|
| 131 |
+
},
|
| 132 |
+
"32013": {
|
| 133 |
+
"content": "<extra_id_86>",
|
| 134 |
+
"lstrip": true,
|
| 135 |
+
"normalized": false,
|
| 136 |
+
"rstrip": true,
|
| 137 |
+
"single_word": false,
|
| 138 |
+
"special": true
|
| 139 |
+
},
|
| 140 |
+
"32014": {
|
| 141 |
+
"content": "<extra_id_85>",
|
| 142 |
+
"lstrip": true,
|
| 143 |
+
"normalized": false,
|
| 144 |
+
"rstrip": true,
|
| 145 |
+
"single_word": false,
|
| 146 |
+
"special": true
|
| 147 |
+
},
|
| 148 |
+
"32015": {
|
| 149 |
+
"content": "<extra_id_84>",
|
| 150 |
+
"lstrip": true,
|
| 151 |
+
"normalized": false,
|
| 152 |
+
"rstrip": true,
|
| 153 |
+
"single_word": false,
|
| 154 |
+
"special": true
|
| 155 |
+
},
|
| 156 |
+
"32016": {
|
| 157 |
+
"content": "<extra_id_83>",
|
| 158 |
+
"lstrip": true,
|
| 159 |
+
"normalized": false,
|
| 160 |
+
"rstrip": true,
|
| 161 |
+
"single_word": false,
|
| 162 |
+
"special": true
|
| 163 |
+
},
|
| 164 |
+
"32017": {
|
| 165 |
+
"content": "<extra_id_82>",
|
| 166 |
+
"lstrip": true,
|
| 167 |
+
"normalized": false,
|
| 168 |
+
"rstrip": true,
|
| 169 |
+
"single_word": false,
|
| 170 |
+
"special": true
|
| 171 |
+
},
|
| 172 |
+
"32018": {
|
| 173 |
+
"content": "<extra_id_81>",
|
| 174 |
+
"lstrip": true,
|
| 175 |
+
"normalized": false,
|
| 176 |
+
"rstrip": true,
|
| 177 |
+
"single_word": false,
|
| 178 |
+
"special": true
|
| 179 |
+
},
|
| 180 |
+
"32019": {
|
| 181 |
+
"content": "<extra_id_80>",
|
| 182 |
+
"lstrip": true,
|
| 183 |
+
"normalized": false,
|
| 184 |
+
"rstrip": true,
|
| 185 |
+
"single_word": false,
|
| 186 |
+
"special": true
|
| 187 |
+
},
|
| 188 |
+
"32020": {
|
| 189 |
+
"content": "<extra_id_79>",
|
| 190 |
+
"lstrip": true,
|
| 191 |
+
"normalized": false,
|
| 192 |
+
"rstrip": true,
|
| 193 |
+
"single_word": false,
|
| 194 |
+
"special": true
|
| 195 |
+
},
|
| 196 |
+
"32021": {
|
| 197 |
+
"content": "<extra_id_78>",
|
| 198 |
+
"lstrip": true,
|
| 199 |
+
"normalized": false,
|
| 200 |
+
"rstrip": true,
|
| 201 |
+
"single_word": false,
|
| 202 |
+
"special": true
|
| 203 |
+
},
|
| 204 |
+
"32022": {
|
| 205 |
+
"content": "<extra_id_77>",
|
| 206 |
+
"lstrip": true,
|
| 207 |
+
"normalized": false,
|
| 208 |
+
"rstrip": true,
|
| 209 |
+
"single_word": false,
|
| 210 |
+
"special": true
|
| 211 |
+
},
|
| 212 |
+
"32023": {
|
| 213 |
+
"content": "<extra_id_76>",
|
| 214 |
+
"lstrip": true,
|
| 215 |
+
"normalized": false,
|
| 216 |
+
"rstrip": true,
|
| 217 |
+
"single_word": false,
|
| 218 |
+
"special": true
|
| 219 |
+
},
|
| 220 |
+
"32024": {
|
| 221 |
+
"content": "<extra_id_75>",
|
| 222 |
+
"lstrip": true,
|
| 223 |
+
"normalized": false,
|
| 224 |
+
"rstrip": true,
|
| 225 |
+
"single_word": false,
|
| 226 |
+
"special": true
|
| 227 |
+
},
|
| 228 |
+
"32025": {
|
| 229 |
+
"content": "<extra_id_74>",
|
| 230 |
+
"lstrip": true,
|
| 231 |
+
"normalized": false,
|
| 232 |
+
"rstrip": true,
|
| 233 |
+
"single_word": false,
|
| 234 |
+
"special": true
|
| 235 |
+
},
|
| 236 |
+
"32026": {
|
| 237 |
+
"content": "<extra_id_73>",
|
| 238 |
+
"lstrip": true,
|
| 239 |
+
"normalized": false,
|
| 240 |
+
"rstrip": true,
|
| 241 |
+
"single_word": false,
|
| 242 |
+
"special": true
|
| 243 |
+
},
|
| 244 |
+
"32027": {
|
| 245 |
+
"content": "<extra_id_72>",
|
| 246 |
+
"lstrip": true,
|
| 247 |
+
"normalized": false,
|
| 248 |
+
"rstrip": true,
|
| 249 |
+
"single_word": false,
|
| 250 |
+
"special": true
|
| 251 |
+
},
|
| 252 |
+
"32028": {
|
| 253 |
+
"content": "<extra_id_71>",
|
| 254 |
+
"lstrip": true,
|
| 255 |
+
"normalized": false,
|
| 256 |
+
"rstrip": true,
|
| 257 |
+
"single_word": false,
|
| 258 |
+
"special": true
|
| 259 |
+
},
|
| 260 |
+
"32029": {
|
| 261 |
+
"content": "<extra_id_70>",
|
| 262 |
+
"lstrip": true,
|
| 263 |
+
"normalized": false,
|
| 264 |
+
"rstrip": true,
|
| 265 |
+
"single_word": false,
|
| 266 |
+
"special": true
|
| 267 |
+
},
|
| 268 |
+
"32030": {
|
| 269 |
+
"content": "<extra_id_69>",
|
| 270 |
+
"lstrip": true,
|
| 271 |
+
"normalized": false,
|
| 272 |
+
"rstrip": true,
|
| 273 |
+
"single_word": false,
|
| 274 |
+
"special": true
|
| 275 |
+
},
|
| 276 |
+
"32031": {
|
| 277 |
+
"content": "<extra_id_68>",
|
| 278 |
+
"lstrip": true,
|
| 279 |
+
"normalized": false,
|
| 280 |
+
"rstrip": true,
|
| 281 |
+
"single_word": false,
|
| 282 |
+
"special": true
|
| 283 |
+
},
|
| 284 |
+
"32032": {
|
| 285 |
+
"content": "<extra_id_67>",
|
| 286 |
+
"lstrip": true,
|
| 287 |
+
"normalized": false,
|
| 288 |
+
"rstrip": true,
|
| 289 |
+
"single_word": false,
|
| 290 |
+
"special": true
|
| 291 |
+
},
|
| 292 |
+
"32033": {
|
| 293 |
+
"content": "<extra_id_66>",
|
| 294 |
+
"lstrip": true,
|
| 295 |
+
"normalized": false,
|
| 296 |
+
"rstrip": true,
|
| 297 |
+
"single_word": false,
|
| 298 |
+
"special": true
|
| 299 |
+
},
|
| 300 |
+
"32034": {
|
| 301 |
+
"content": "<extra_id_65>",
|
| 302 |
+
"lstrip": true,
|
| 303 |
+
"normalized": false,
|
| 304 |
+
"rstrip": true,
|
| 305 |
+
"single_word": false,
|
| 306 |
+
"special": true
|
| 307 |
+
},
|
| 308 |
+
"32035": {
|
| 309 |
+
"content": "<extra_id_64>",
|
| 310 |
+
"lstrip": true,
|
| 311 |
+
"normalized": false,
|
| 312 |
+
"rstrip": true,
|
| 313 |
+
"single_word": false,
|
| 314 |
+
"special": true
|
| 315 |
+
},
|
| 316 |
+
"32036": {
|
| 317 |
+
"content": "<extra_id_63>",
|
| 318 |
+
"lstrip": true,
|
| 319 |
+
"normalized": false,
|
| 320 |
+
"rstrip": true,
|
| 321 |
+
"single_word": false,
|
| 322 |
+
"special": true
|
| 323 |
+
},
|
| 324 |
+
"32037": {
|
| 325 |
+
"content": "<extra_id_62>",
|
| 326 |
+
"lstrip": true,
|
| 327 |
+
"normalized": false,
|
| 328 |
+
"rstrip": true,
|
| 329 |
+
"single_word": false,
|
| 330 |
+
"special": true
|
| 331 |
+
},
|
| 332 |
+
"32038": {
|
| 333 |
+
"content": "<extra_id_61>",
|
| 334 |
+
"lstrip": true,
|
| 335 |
+
"normalized": false,
|
| 336 |
+
"rstrip": true,
|
| 337 |
+
"single_word": false,
|
| 338 |
+
"special": true
|
| 339 |
+
},
|
| 340 |
+
"32039": {
|
| 341 |
+
"content": "<extra_id_60>",
|
| 342 |
+
"lstrip": true,
|
| 343 |
+
"normalized": false,
|
| 344 |
+
"rstrip": true,
|
| 345 |
+
"single_word": false,
|
| 346 |
+
"special": true
|
| 347 |
+
},
|
| 348 |
+
"32040": {
|
| 349 |
+
"content": "<extra_id_59>",
|
| 350 |
+
"lstrip": true,
|
| 351 |
+
"normalized": false,
|
| 352 |
+
"rstrip": true,
|
| 353 |
+
"single_word": false,
|
| 354 |
+
"special": true
|
| 355 |
+
},
|
| 356 |
+
"32041": {
|
| 357 |
+
"content": "<extra_id_58>",
|
| 358 |
+
"lstrip": true,
|
| 359 |
+
"normalized": false,
|
| 360 |
+
"rstrip": true,
|
| 361 |
+
"single_word": false,
|
| 362 |
+
"special": true
|
| 363 |
+
},
|
| 364 |
+
"32042": {
|
| 365 |
+
"content": "<extra_id_57>",
|
| 366 |
+
"lstrip": true,
|
| 367 |
+
"normalized": false,
|
| 368 |
+
"rstrip": true,
|
| 369 |
+
"single_word": false,
|
| 370 |
+
"special": true
|
| 371 |
+
},
|
| 372 |
+
"32043": {
|
| 373 |
+
"content": "<extra_id_56>",
|
| 374 |
+
"lstrip": true,
|
| 375 |
+
"normalized": false,
|
| 376 |
+
"rstrip": true,
|
| 377 |
+
"single_word": false,
|
| 378 |
+
"special": true
|
| 379 |
+
},
|
| 380 |
+
"32044": {
|
| 381 |
+
"content": "<extra_id_55>",
|
| 382 |
+
"lstrip": true,
|
| 383 |
+
"normalized": false,
|
| 384 |
+
"rstrip": true,
|
| 385 |
+
"single_word": false,
|
| 386 |
+
"special": true
|
| 387 |
+
},
|
| 388 |
+
"32045": {
|
| 389 |
+
"content": "<extra_id_54>",
|
| 390 |
+
"lstrip": true,
|
| 391 |
+
"normalized": false,
|
| 392 |
+
"rstrip": true,
|
| 393 |
+
"single_word": false,
|
| 394 |
+
"special": true
|
| 395 |
+
},
|
| 396 |
+
"32046": {
|
| 397 |
+
"content": "<extra_id_53>",
|
| 398 |
+
"lstrip": true,
|
| 399 |
+
"normalized": false,
|
| 400 |
+
"rstrip": true,
|
| 401 |
+
"single_word": false,
|
| 402 |
+
"special": true
|
| 403 |
+
},
|
| 404 |
+
"32047": {
|
| 405 |
+
"content": "<extra_id_52>",
|
| 406 |
+
"lstrip": true,
|
| 407 |
+
"normalized": false,
|
| 408 |
+
"rstrip": true,
|
| 409 |
+
"single_word": false,
|
| 410 |
+
"special": true
|
| 411 |
+
},
|
| 412 |
+
"32048": {
|
| 413 |
+
"content": "<extra_id_51>",
|
| 414 |
+
"lstrip": true,
|
| 415 |
+
"normalized": false,
|
| 416 |
+
"rstrip": true,
|
| 417 |
+
"single_word": false,
|
| 418 |
+
"special": true
|
| 419 |
+
},
|
| 420 |
+
"32049": {
|
| 421 |
+
"content": "<extra_id_50>",
|
| 422 |
+
"lstrip": true,
|
| 423 |
+
"normalized": false,
|
| 424 |
+
"rstrip": true,
|
| 425 |
+
"single_word": false,
|
| 426 |
+
"special": true
|
| 427 |
+
},
|
| 428 |
+
"32050": {
|
| 429 |
+
"content": "<extra_id_49>",
|
| 430 |
+
"lstrip": true,
|
| 431 |
+
"normalized": false,
|
| 432 |
+
"rstrip": true,
|
| 433 |
+
"single_word": false,
|
| 434 |
+
"special": true
|
| 435 |
+
},
|
| 436 |
+
"32051": {
|
| 437 |
+
"content": "<extra_id_48>",
|
| 438 |
+
"lstrip": true,
|
| 439 |
+
"normalized": false,
|
| 440 |
+
"rstrip": true,
|
| 441 |
+
"single_word": false,
|
| 442 |
+
"special": true
|
| 443 |
+
},
|
| 444 |
+
"32052": {
|
| 445 |
+
"content": "<extra_id_47>",
|
| 446 |
+
"lstrip": true,
|
| 447 |
+
"normalized": false,
|
| 448 |
+
"rstrip": true,
|
| 449 |
+
"single_word": false,
|
| 450 |
+
"special": true
|
| 451 |
+
},
|
| 452 |
+
"32053": {
|
| 453 |
+
"content": "<extra_id_46>",
|
| 454 |
+
"lstrip": true,
|
| 455 |
+
"normalized": false,
|
| 456 |
+
"rstrip": true,
|
| 457 |
+
"single_word": false,
|
| 458 |
+
"special": true
|
| 459 |
+
},
|
| 460 |
+
"32054": {
|
| 461 |
+
"content": "<extra_id_45>",
|
| 462 |
+
"lstrip": true,
|
| 463 |
+
"normalized": false,
|
| 464 |
+
"rstrip": true,
|
| 465 |
+
"single_word": false,
|
| 466 |
+
"special": true
|
| 467 |
+
},
|
| 468 |
+
"32055": {
|
| 469 |
+
"content": "<extra_id_44>",
|
| 470 |
+
"lstrip": true,
|
| 471 |
+
"normalized": false,
|
| 472 |
+
"rstrip": true,
|
| 473 |
+
"single_word": false,
|
| 474 |
+
"special": true
|
| 475 |
+
},
|
| 476 |
+
"32056": {
|
| 477 |
+
"content": "<extra_id_43>",
|
| 478 |
+
"lstrip": true,
|
| 479 |
+
"normalized": false,
|
| 480 |
+
"rstrip": true,
|
| 481 |
+
"single_word": false,
|
| 482 |
+
"special": true
|
| 483 |
+
},
|
| 484 |
+
"32057": {
|
| 485 |
+
"content": "<extra_id_42>",
|
| 486 |
+
"lstrip": true,
|
| 487 |
+
"normalized": false,
|
| 488 |
+
"rstrip": true,
|
| 489 |
+
"single_word": false,
|
| 490 |
+
"special": true
|
| 491 |
+
},
|
| 492 |
+
"32058": {
|
| 493 |
+
"content": "<extra_id_41>",
|
| 494 |
+
"lstrip": true,
|
| 495 |
+
"normalized": false,
|
| 496 |
+
"rstrip": true,
|
| 497 |
+
"single_word": false,
|
| 498 |
+
"special": true
|
| 499 |
+
},
|
| 500 |
+
"32059": {
|
| 501 |
+
"content": "<extra_id_40>",
|
| 502 |
+
"lstrip": true,
|
| 503 |
+
"normalized": false,
|
| 504 |
+
"rstrip": true,
|
| 505 |
+
"single_word": false,
|
| 506 |
+
"special": true
|
| 507 |
+
},
|
| 508 |
+
"32060": {
|
| 509 |
+
"content": "<extra_id_39>",
|
| 510 |
+
"lstrip": true,
|
| 511 |
+
"normalized": false,
|
| 512 |
+
"rstrip": true,
|
| 513 |
+
"single_word": false,
|
| 514 |
+
"special": true
|
| 515 |
+
},
|
| 516 |
+
"32061": {
|
| 517 |
+
"content": "<extra_id_38>",
|
| 518 |
+
"lstrip": true,
|
| 519 |
+
"normalized": false,
|
| 520 |
+
"rstrip": true,
|
| 521 |
+
"single_word": false,
|
| 522 |
+
"special": true
|
| 523 |
+
},
|
| 524 |
+
"32062": {
|
| 525 |
+
"content": "<extra_id_37>",
|
| 526 |
+
"lstrip": true,
|
| 527 |
+
"normalized": false,
|
| 528 |
+
"rstrip": true,
|
| 529 |
+
"single_word": false,
|
| 530 |
+
"special": true
|
| 531 |
+
},
|
| 532 |
+
"32063": {
|
| 533 |
+
"content": "<extra_id_36>",
|
| 534 |
+
"lstrip": true,
|
| 535 |
+
"normalized": false,
|
| 536 |
+
"rstrip": true,
|
| 537 |
+
"single_word": false,
|
| 538 |
+
"special": true
|
| 539 |
+
},
|
| 540 |
+
"32064": {
|
| 541 |
+
"content": "<extra_id_35>",
|
| 542 |
+
"lstrip": true,
|
| 543 |
+
"normalized": false,
|
| 544 |
+
"rstrip": true,
|
| 545 |
+
"single_word": false,
|
| 546 |
+
"special": true
|
| 547 |
+
},
|
| 548 |
+
"32065": {
|
| 549 |
+
"content": "<extra_id_34>",
|
| 550 |
+
"lstrip": true,
|
| 551 |
+
"normalized": false,
|
| 552 |
+
"rstrip": true,
|
| 553 |
+
"single_word": false,
|
| 554 |
+
"special": true
|
| 555 |
+
},
|
| 556 |
+
"32066": {
|
| 557 |
+
"content": "<extra_id_33>",
|
| 558 |
+
"lstrip": true,
|
| 559 |
+
"normalized": false,
|
| 560 |
+
"rstrip": true,
|
| 561 |
+
"single_word": false,
|
| 562 |
+
"special": true
|
| 563 |
+
},
|
| 564 |
+
"32067": {
|
| 565 |
+
"content": "<extra_id_32>",
|
| 566 |
+
"lstrip": true,
|
| 567 |
+
"normalized": false,
|
| 568 |
+
"rstrip": true,
|
| 569 |
+
"single_word": false,
|
| 570 |
+
"special": true
|
| 571 |
+
},
|
| 572 |
+
"32068": {
|
| 573 |
+
"content": "<extra_id_31>",
|
| 574 |
+
"lstrip": true,
|
| 575 |
+
"normalized": false,
|
| 576 |
+
"rstrip": true,
|
| 577 |
+
"single_word": false,
|
| 578 |
+
"special": true
|
| 579 |
+
},
|
| 580 |
+
"32069": {
|
| 581 |
+
"content": "<extra_id_30>",
|
| 582 |
+
"lstrip": true,
|
| 583 |
+
"normalized": false,
|
| 584 |
+
"rstrip": true,
|
| 585 |
+
"single_word": false,
|
| 586 |
+
"special": true
|
| 587 |
+
},
|
| 588 |
+
"32070": {
|
| 589 |
+
"content": "<extra_id_29>",
|
| 590 |
+
"lstrip": true,
|
| 591 |
+
"normalized": false,
|
| 592 |
+
"rstrip": true,
|
| 593 |
+
"single_word": false,
|
| 594 |
+
"special": true
|
| 595 |
+
},
|
| 596 |
+
"32071": {
|
| 597 |
+
"content": "<extra_id_28>",
|
| 598 |
+
"lstrip": true,
|
| 599 |
+
"normalized": false,
|
| 600 |
+
"rstrip": true,
|
| 601 |
+
"single_word": false,
|
| 602 |
+
"special": true
|
| 603 |
+
},
|
| 604 |
+
"32072": {
|
| 605 |
+
"content": "<extra_id_27>",
|
| 606 |
+
"lstrip": true,
|
| 607 |
+
"normalized": false,
|
| 608 |
+
"rstrip": true,
|
| 609 |
+
"single_word": false,
|
| 610 |
+
"special": true
|
| 611 |
+
},
|
| 612 |
+
"32073": {
|
| 613 |
+
"content": "<extra_id_26>",
|
| 614 |
+
"lstrip": true,
|
| 615 |
+
"normalized": false,
|
| 616 |
+
"rstrip": true,
|
| 617 |
+
"single_word": false,
|
| 618 |
+
"special": true
|
| 619 |
+
},
|
| 620 |
+
"32074": {
|
| 621 |
+
"content": "<extra_id_25>",
|
| 622 |
+
"lstrip": true,
|
| 623 |
+
"normalized": false,
|
| 624 |
+
"rstrip": true,
|
| 625 |
+
"single_word": false,
|
| 626 |
+
"special": true
|
| 627 |
+
},
|
| 628 |
+
"32075": {
|
| 629 |
+
"content": "<extra_id_24>",
|
| 630 |
+
"lstrip": true,
|
| 631 |
+
"normalized": false,
|
| 632 |
+
"rstrip": true,
|
| 633 |
+
"single_word": false,
|
| 634 |
+
"special": true
|
| 635 |
+
},
|
| 636 |
+
"32076": {
|
| 637 |
+
"content": "<extra_id_23>",
|
| 638 |
+
"lstrip": true,
|
| 639 |
+
"normalized": false,
|
| 640 |
+
"rstrip": true,
|
| 641 |
+
"single_word": false,
|
| 642 |
+
"special": true
|
| 643 |
+
},
|
| 644 |
+
"32077": {
|
| 645 |
+
"content": "<extra_id_22>",
|
| 646 |
+
"lstrip": true,
|
| 647 |
+
"normalized": false,
|
| 648 |
+
"rstrip": true,
|
| 649 |
+
"single_word": false,
|
| 650 |
+
"special": true
|
| 651 |
+
},
|
| 652 |
+
"32078": {
|
| 653 |
+
"content": "<extra_id_21>",
|
| 654 |
+
"lstrip": true,
|
| 655 |
+
"normalized": false,
|
| 656 |
+
"rstrip": true,
|
| 657 |
+
"single_word": false,
|
| 658 |
+
"special": true
|
| 659 |
+
},
|
| 660 |
+
"32079": {
|
| 661 |
+
"content": "<extra_id_20>",
|
| 662 |
+
"lstrip": true,
|
| 663 |
+
"normalized": false,
|
| 664 |
+
"rstrip": true,
|
| 665 |
+
"single_word": false,
|
| 666 |
+
"special": true
|
| 667 |
+
},
|
| 668 |
+
"32080": {
|
| 669 |
+
"content": "<extra_id_19>",
|
| 670 |
+
"lstrip": true,
|
| 671 |
+
"normalized": false,
|
| 672 |
+
"rstrip": true,
|
| 673 |
+
"single_word": false,
|
| 674 |
+
"special": true
|
| 675 |
+
},
|
| 676 |
+
"32081": {
|
| 677 |
+
"content": "<extra_id_18>",
|
| 678 |
+
"lstrip": true,
|
| 679 |
+
"normalized": false,
|
| 680 |
+
"rstrip": true,
|
| 681 |
+
"single_word": false,
|
| 682 |
+
"special": true
|
| 683 |
+
},
|
| 684 |
+
"32082": {
|
| 685 |
+
"content": "<extra_id_17>",
|
| 686 |
+
"lstrip": true,
|
| 687 |
+
"normalized": false,
|
| 688 |
+
"rstrip": true,
|
| 689 |
+
"single_word": false,
|
| 690 |
+
"special": true
|
| 691 |
+
},
|
| 692 |
+
"32083": {
|
| 693 |
+
"content": "<extra_id_16>",
|
| 694 |
+
"lstrip": true,
|
| 695 |
+
"normalized": false,
|
| 696 |
+
"rstrip": true,
|
| 697 |
+
"single_word": false,
|
| 698 |
+
"special": true
|
| 699 |
+
},
|
| 700 |
+
"32084": {
|
| 701 |
+
"content": "<extra_id_15>",
|
| 702 |
+
"lstrip": true,
|
| 703 |
+
"normalized": false,
|
| 704 |
+
"rstrip": true,
|
| 705 |
+
"single_word": false,
|
| 706 |
+
"special": true
|
| 707 |
+
},
|
| 708 |
+
"32085": {
|
| 709 |
+
"content": "<extra_id_14>",
|
| 710 |
+
"lstrip": true,
|
| 711 |
+
"normalized": false,
|
| 712 |
+
"rstrip": true,
|
| 713 |
+
"single_word": false,
|
| 714 |
+
"special": true
|
| 715 |
+
},
|
| 716 |
+
"32086": {
|
| 717 |
+
"content": "<extra_id_13>",
|
| 718 |
+
"lstrip": true,
|
| 719 |
+
"normalized": false,
|
| 720 |
+
"rstrip": true,
|
| 721 |
+
"single_word": false,
|
| 722 |
+
"special": true
|
| 723 |
+
},
|
| 724 |
+
"32087": {
|
| 725 |
+
"content": "<extra_id_12>",
|
| 726 |
+
"lstrip": true,
|
| 727 |
+
"normalized": false,
|
| 728 |
+
"rstrip": true,
|
| 729 |
+
"single_word": false,
|
| 730 |
+
"special": true
|
| 731 |
+
},
|
| 732 |
+
"32088": {
|
| 733 |
+
"content": "<extra_id_11>",
|
| 734 |
+
"lstrip": true,
|
| 735 |
+
"normalized": false,
|
| 736 |
+
"rstrip": true,
|
| 737 |
+
"single_word": false,
|
| 738 |
+
"special": true
|
| 739 |
+
},
|
| 740 |
+
"32089": {
|
| 741 |
+
"content": "<extra_id_10>",
|
| 742 |
+
"lstrip": true,
|
| 743 |
+
"normalized": false,
|
| 744 |
+
"rstrip": true,
|
| 745 |
+
"single_word": false,
|
| 746 |
+
"special": true
|
| 747 |
+
},
|
| 748 |
+
"32090": {
|
| 749 |
+
"content": "<extra_id_9>",
|
| 750 |
+
"lstrip": true,
|
| 751 |
+
"normalized": false,
|
| 752 |
+
"rstrip": true,
|
| 753 |
+
"single_word": false,
|
| 754 |
+
"special": true
|
| 755 |
+
},
|
| 756 |
+
"32091": {
|
| 757 |
+
"content": "<extra_id_8>",
|
| 758 |
+
"lstrip": true,
|
| 759 |
+
"normalized": false,
|
| 760 |
+
"rstrip": true,
|
| 761 |
+
"single_word": false,
|
| 762 |
+
"special": true
|
| 763 |
+
},
|
| 764 |
+
"32092": {
|
| 765 |
+
"content": "<extra_id_7>",
|
| 766 |
+
"lstrip": true,
|
| 767 |
+
"normalized": false,
|
| 768 |
+
"rstrip": true,
|
| 769 |
+
"single_word": false,
|
| 770 |
+
"special": true
|
| 771 |
+
},
|
| 772 |
+
"32093": {
|
| 773 |
+
"content": "<extra_id_6>",
|
| 774 |
+
"lstrip": true,
|
| 775 |
+
"normalized": false,
|
| 776 |
+
"rstrip": true,
|
| 777 |
+
"single_word": false,
|
| 778 |
+
"special": true
|
| 779 |
+
},
|
| 780 |
+
"32094": {
|
| 781 |
+
"content": "<extra_id_5>",
|
| 782 |
+
"lstrip": true,
|
| 783 |
+
"normalized": false,
|
| 784 |
+
"rstrip": true,
|
| 785 |
+
"single_word": false,
|
| 786 |
+
"special": true
|
| 787 |
+
},
|
| 788 |
+
"32095": {
|
| 789 |
+
"content": "<extra_id_4>",
|
| 790 |
+
"lstrip": true,
|
| 791 |
+
"normalized": false,
|
| 792 |
+
"rstrip": true,
|
| 793 |
+
"single_word": false,
|
| 794 |
+
"special": true
|
| 795 |
+
},
|
| 796 |
+
"32096": {
|
| 797 |
+
"content": "<extra_id_3>",
|
| 798 |
+
"lstrip": true,
|
| 799 |
+
"normalized": false,
|
| 800 |
+
"rstrip": true,
|
| 801 |
+
"single_word": false,
|
| 802 |
+
"special": true
|
| 803 |
+
},
|
| 804 |
+
"32097": {
|
| 805 |
+
"content": "<extra_id_2>",
|
| 806 |
+
"lstrip": true,
|
| 807 |
+
"normalized": false,
|
| 808 |
+
"rstrip": true,
|
| 809 |
+
"single_word": false,
|
| 810 |
+
"special": true
|
| 811 |
+
},
|
| 812 |
+
"32098": {
|
| 813 |
+
"content": "<extra_id_1>",
|
| 814 |
+
"lstrip": true,
|
| 815 |
+
"normalized": false,
|
| 816 |
+
"rstrip": true,
|
| 817 |
+
"single_word": false,
|
| 818 |
+
"special": true
|
| 819 |
+
},
|
| 820 |
+
"32099": {
|
| 821 |
+
"content": "<extra_id_0>",
|
| 822 |
+
"lstrip": true,
|
| 823 |
+
"normalized": false,
|
| 824 |
+
"rstrip": true,
|
| 825 |
+
"single_word": false,
|
| 826 |
+
"special": true
|
| 827 |
+
}
|
| 828 |
+
},
|
| 829 |
+
"additional_special_tokens": [
|
| 830 |
+
"<extra_id_0>",
|
| 831 |
+
"<extra_id_1>",
|
| 832 |
+
"<extra_id_2>",
|
| 833 |
+
"<extra_id_3>",
|
| 834 |
+
"<extra_id_4>",
|
| 835 |
+
"<extra_id_5>",
|
| 836 |
+
"<extra_id_6>",
|
| 837 |
+
"<extra_id_7>",
|
| 838 |
+
"<extra_id_8>",
|
| 839 |
+
"<extra_id_9>",
|
| 840 |
+
"<extra_id_10>",
|
| 841 |
+
"<extra_id_11>",
|
| 842 |
+
"<extra_id_12>",
|
| 843 |
+
"<extra_id_13>",
|
| 844 |
+
"<extra_id_14>",
|
| 845 |
+
"<extra_id_15>",
|
| 846 |
+
"<extra_id_16>",
|
| 847 |
+
"<extra_id_17>",
|
| 848 |
+
"<extra_id_18>",
|
| 849 |
+
"<extra_id_19>",
|
| 850 |
+
"<extra_id_20>",
|
| 851 |
+
"<extra_id_21>",
|
| 852 |
+
"<extra_id_22>",
|
| 853 |
+
"<extra_id_23>",
|
| 854 |
+
"<extra_id_24>",
|
| 855 |
+
"<extra_id_25>",
|
| 856 |
+
"<extra_id_26>",
|
| 857 |
+
"<extra_id_27>",
|
| 858 |
+
"<extra_id_28>",
|
| 859 |
+
"<extra_id_29>",
|
| 860 |
+
"<extra_id_30>",
|
| 861 |
+
"<extra_id_31>",
|
| 862 |
+
"<extra_id_32>",
|
| 863 |
+
"<extra_id_33>",
|
| 864 |
+
"<extra_id_34>",
|
| 865 |
+
"<extra_id_35>",
|
| 866 |
+
"<extra_id_36>",
|
| 867 |
+
"<extra_id_37>",
|
| 868 |
+
"<extra_id_38>",
|
| 869 |
+
"<extra_id_39>",
|
| 870 |
+
"<extra_id_40>",
|
| 871 |
+
"<extra_id_41>",
|
| 872 |
+
"<extra_id_42>",
|
| 873 |
+
"<extra_id_43>",
|
| 874 |
+
"<extra_id_44>",
|
| 875 |
+
"<extra_id_45>",
|
| 876 |
+
"<extra_id_46>",
|
| 877 |
+
"<extra_id_47>",
|
| 878 |
+
"<extra_id_48>",
|
| 879 |
+
"<extra_id_49>",
|
| 880 |
+
"<extra_id_50>",
|
| 881 |
+
"<extra_id_51>",
|
| 882 |
+
"<extra_id_52>",
|
| 883 |
+
"<extra_id_53>",
|
| 884 |
+
"<extra_id_54>",
|
| 885 |
+
"<extra_id_55>",
|
| 886 |
+
"<extra_id_56>",
|
| 887 |
+
"<extra_id_57>",
|
| 888 |
+
"<extra_id_58>",
|
| 889 |
+
"<extra_id_59>",
|
| 890 |
+
"<extra_id_60>",
|
| 891 |
+
"<extra_id_61>",
|
| 892 |
+
"<extra_id_62>",
|
| 893 |
+
"<extra_id_63>",
|
| 894 |
+
"<extra_id_64>",
|
| 895 |
+
"<extra_id_65>",
|
| 896 |
+
"<extra_id_66>",
|
| 897 |
+
"<extra_id_67>",
|
| 898 |
+
"<extra_id_68>",
|
| 899 |
+
"<extra_id_69>",
|
| 900 |
+
"<extra_id_70>",
|
| 901 |
+
"<extra_id_71>",
|
| 902 |
+
"<extra_id_72>",
|
| 903 |
+
"<extra_id_73>",
|
| 904 |
+
"<extra_id_74>",
|
| 905 |
+
"<extra_id_75>",
|
| 906 |
+
"<extra_id_76>",
|
| 907 |
+
"<extra_id_77>",
|
| 908 |
+
"<extra_id_78>",
|
| 909 |
+
"<extra_id_79>",
|
| 910 |
+
"<extra_id_80>",
|
| 911 |
+
"<extra_id_81>",
|
| 912 |
+
"<extra_id_82>",
|
| 913 |
+
"<extra_id_83>",
|
| 914 |
+
"<extra_id_84>",
|
| 915 |
+
"<extra_id_85>",
|
| 916 |
+
"<extra_id_86>",
|
| 917 |
+
"<extra_id_87>",
|
| 918 |
+
"<extra_id_88>",
|
| 919 |
+
"<extra_id_89>",
|
| 920 |
+
"<extra_id_90>",
|
| 921 |
+
"<extra_id_91>",
|
| 922 |
+
"<extra_id_92>",
|
| 923 |
+
"<extra_id_93>",
|
| 924 |
+
"<extra_id_94>",
|
| 925 |
+
"<extra_id_95>",
|
| 926 |
+
"<extra_id_96>",
|
| 927 |
+
"<extra_id_97>",
|
| 928 |
+
"<extra_id_98>",
|
| 929 |
+
"<extra_id_99>"
|
| 930 |
+
],
|
| 931 |
+
"clean_up_tokenization_spaces": true,
|
| 932 |
+
"eos_token": "</s>",
|
| 933 |
+
"extra_ids": 100,
|
| 934 |
+
"legacy": true,
|
| 935 |
+
"model_max_length": 512,
|
| 936 |
+
"pad_token": "<pad>",
|
| 937 |
+
"sp_model_kwargs": {},
|
| 938 |
+
"tokenizer_class": "T5Tokenizer",
|
| 939 |
+
"unk_token": "<unk>"
|
| 940 |
+
}
|
diffsynth/tokenizer_configs/stable_diffusion_xl/tokenizer_2/merges.txt
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
diffsynth/tokenizer_configs/stable_diffusion_xl/tokenizer_2/special_tokens_map.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"bos_token": {
|
| 3 |
+
"content": "<|startoftext|>",
|
| 4 |
+
"lstrip": false,
|
| 5 |
+
"normalized": true,
|
| 6 |
+
"rstrip": false,
|
| 7 |
+
"single_word": false
|
| 8 |
+
},
|
| 9 |
+
"eos_token": {
|
| 10 |
+
"content": "<|endoftext|>",
|
| 11 |
+
"lstrip": false,
|
| 12 |
+
"normalized": true,
|
| 13 |
+
"rstrip": false,
|
| 14 |
+
"single_word": false
|
| 15 |
+
},
|
| 16 |
+
"pad_token": "!",
|
| 17 |
+
"unk_token": {
|
| 18 |
+
"content": "<|endoftext|>",
|
| 19 |
+
"lstrip": false,
|
| 20 |
+
"normalized": true,
|
| 21 |
+
"rstrip": false,
|
| 22 |
+
"single_word": false
|
| 23 |
+
}
|
| 24 |
+
}
|
diffsynth/tokenizer_configs/stable_diffusion_xl/tokenizer_2/tokenizer_config.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": false,
|
| 3 |
+
"added_tokens_decoder": {
|
| 4 |
+
"0": {
|
| 5 |
+
"content": "!",
|
| 6 |
+
"lstrip": false,
|
| 7 |
+
"normalized": false,
|
| 8 |
+
"rstrip": false,
|
| 9 |
+
"single_word": false,
|
| 10 |
+
"special": true
|
| 11 |
+
},
|
| 12 |
+
"49406": {
|
| 13 |
+
"content": "<|startoftext|>",
|
| 14 |
+
"lstrip": false,
|
| 15 |
+
"normalized": true,
|
| 16 |
+
"rstrip": false,
|
| 17 |
+
"single_word": false,
|
| 18 |
+
"special": true
|
| 19 |
+
},
|
| 20 |
+
"49407": {
|
| 21 |
+
"content": "<|endoftext|>",
|
| 22 |
+
"lstrip": false,
|
| 23 |
+
"normalized": true,
|
| 24 |
+
"rstrip": false,
|
| 25 |
+
"single_word": false,
|
| 26 |
+
"special": true
|
| 27 |
+
}
|
| 28 |
+
},
|
| 29 |
+
"bos_token": "<|startoftext|>",
|
| 30 |
+
"clean_up_tokenization_spaces": true,
|
| 31 |
+
"do_lower_case": true,
|
| 32 |
+
"eos_token": "<|endoftext|>",
|
| 33 |
+
"errors": "replace",
|
| 34 |
+
"model_max_length": 77,
|
| 35 |
+
"pad_token": "!",
|
| 36 |
+
"tokenizer_class": "CLIPTokenizer",
|
| 37 |
+
"unk_token": "<|endoftext|>"
|
| 38 |
+
}
|
diffsynth/tokenizer_configs/stable_diffusion_xl/tokenizer_2/vocab.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
diffsynth/trainers/__init__.py
ADDED
|
File without changes
|
diffsynth/trainers/text_to_image.py
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import lightning as pl
|
| 2 |
+
from peft import LoraConfig, inject_adapter_in_model
|
| 3 |
+
import torch, os
|
| 4 |
+
from ..data.simple_text_image import TextImageDataset
|
| 5 |
+
from modelscope.hub.api import HubApi
|
| 6 |
+
from ..models.utils import load_state_dict
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class LightningModelForT2ILoRA(pl.LightningModule):
|
| 11 |
+
def __init__(
|
| 12 |
+
self,
|
| 13 |
+
learning_rate=1e-4,
|
| 14 |
+
use_gradient_checkpointing=True,
|
| 15 |
+
state_dict_converter=None,
|
| 16 |
+
):
|
| 17 |
+
super().__init__()
|
| 18 |
+
# Set parameters
|
| 19 |
+
self.learning_rate = learning_rate
|
| 20 |
+
self.use_gradient_checkpointing = use_gradient_checkpointing
|
| 21 |
+
self.state_dict_converter = state_dict_converter
|
| 22 |
+
self.lora_alpha = None
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def load_models(self):
|
| 26 |
+
# This function is implemented in other modules
|
| 27 |
+
self.pipe = None
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def freeze_parameters(self):
|
| 31 |
+
# Freeze parameters
|
| 32 |
+
self.pipe.requires_grad_(False)
|
| 33 |
+
self.pipe.eval()
|
| 34 |
+
self.pipe.denoising_model().train()
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def add_lora_to_model(self, model, lora_rank=4, lora_alpha=4, lora_target_modules="to_q,to_k,to_v,to_out", init_lora_weights="gaussian", pretrained_lora_path=None, state_dict_converter=None):
|
| 38 |
+
# Add LoRA to UNet
|
| 39 |
+
self.lora_alpha = lora_alpha
|
| 40 |
+
if init_lora_weights == "kaiming":
|
| 41 |
+
init_lora_weights = True
|
| 42 |
+
|
| 43 |
+
lora_config = LoraConfig(
|
| 44 |
+
r=lora_rank,
|
| 45 |
+
lora_alpha=lora_alpha,
|
| 46 |
+
init_lora_weights=init_lora_weights,
|
| 47 |
+
target_modules=lora_target_modules.split(","),
|
| 48 |
+
)
|
| 49 |
+
model = inject_adapter_in_model(lora_config, model)
|
| 50 |
+
for param in model.parameters():
|
| 51 |
+
# Upcast LoRA parameters into fp32
|
| 52 |
+
if param.requires_grad:
|
| 53 |
+
param.data = param.to(torch.float32)
|
| 54 |
+
|
| 55 |
+
# Lora pretrained lora weights
|
| 56 |
+
if pretrained_lora_path is not None:
|
| 57 |
+
state_dict = load_state_dict(pretrained_lora_path)
|
| 58 |
+
if state_dict_converter is not None:
|
| 59 |
+
state_dict = state_dict_converter(state_dict)
|
| 60 |
+
missing_keys, unexpected_keys = model.load_state_dict(state_dict, strict=False)
|
| 61 |
+
all_keys = [i for i, _ in model.named_parameters()]
|
| 62 |
+
num_updated_keys = len(all_keys) - len(missing_keys)
|
| 63 |
+
num_unexpected_keys = len(unexpected_keys)
|
| 64 |
+
print(f"{num_updated_keys} parameters are loaded from {pretrained_lora_path}. {num_unexpected_keys} parameters are unexpected.")
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def training_step(self, batch, batch_idx):
|
| 68 |
+
# Data
|
| 69 |
+
text, image = batch["text"], batch["image"]
|
| 70 |
+
|
| 71 |
+
# Prepare input parameters
|
| 72 |
+
self.pipe.device = self.device
|
| 73 |
+
prompt_emb = self.pipe.encode_prompt(text, positive=True)
|
| 74 |
+
if "latents" in batch:
|
| 75 |
+
latents = batch["latents"].to(dtype=self.pipe.torch_dtype, device=self.device)
|
| 76 |
+
else:
|
| 77 |
+
latents = self.pipe.vae_encoder(image.to(dtype=self.pipe.torch_dtype, device=self.device))
|
| 78 |
+
noise = torch.randn_like(latents)
|
| 79 |
+
timestep_id = torch.randint(0, self.pipe.scheduler.num_train_timesteps, (1,))
|
| 80 |
+
timestep = self.pipe.scheduler.timesteps[timestep_id].to(self.device)
|
| 81 |
+
extra_input = self.pipe.prepare_extra_input(latents)
|
| 82 |
+
noisy_latents = self.pipe.scheduler.add_noise(latents, noise, timestep)
|
| 83 |
+
training_target = self.pipe.scheduler.training_target(latents, noise, timestep)
|
| 84 |
+
|
| 85 |
+
# Compute loss
|
| 86 |
+
noise_pred = self.pipe.denoising_model()(
|
| 87 |
+
noisy_latents, timestep=timestep, **prompt_emb, **extra_input,
|
| 88 |
+
use_gradient_checkpointing=self.use_gradient_checkpointing
|
| 89 |
+
)
|
| 90 |
+
loss = torch.nn.functional.mse_loss(noise_pred.float(), training_target.float())
|
| 91 |
+
loss = loss * self.pipe.scheduler.training_weight(timestep)
|
| 92 |
+
|
| 93 |
+
# Record log
|
| 94 |
+
self.log("train_loss", loss, prog_bar=True)
|
| 95 |
+
return loss
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def configure_optimizers(self):
|
| 99 |
+
trainable_modules = filter(lambda p: p.requires_grad, self.pipe.denoising_model().parameters())
|
| 100 |
+
optimizer = torch.optim.AdamW(trainable_modules, lr=self.learning_rate)
|
| 101 |
+
return optimizer
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
def on_save_checkpoint(self, checkpoint):
|
| 105 |
+
checkpoint.clear()
|
| 106 |
+
trainable_param_names = list(filter(lambda named_param: named_param[1].requires_grad, self.pipe.denoising_model().named_parameters()))
|
| 107 |
+
trainable_param_names = set([named_param[0] for named_param in trainable_param_names])
|
| 108 |
+
state_dict = self.pipe.denoising_model().state_dict()
|
| 109 |
+
lora_state_dict = {}
|
| 110 |
+
for name, param in state_dict.items():
|
| 111 |
+
if name in trainable_param_names:
|
| 112 |
+
lora_state_dict[name] = param
|
| 113 |
+
if self.state_dict_converter is not None:
|
| 114 |
+
lora_state_dict = self.state_dict_converter(lora_state_dict, alpha=self.lora_alpha)
|
| 115 |
+
checkpoint.update(lora_state_dict)
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def add_general_parsers(parser):
|
| 120 |
+
parser.add_argument(
|
| 121 |
+
"--dataset_path",
|
| 122 |
+
type=str,
|
| 123 |
+
default=None,
|
| 124 |
+
required=True,
|
| 125 |
+
help="The path of the Dataset.",
|
| 126 |
+
)
|
| 127 |
+
parser.add_argument(
|
| 128 |
+
"--output_path",
|
| 129 |
+
type=str,
|
| 130 |
+
default="./",
|
| 131 |
+
help="Path to save the model.",
|
| 132 |
+
)
|
| 133 |
+
parser.add_argument(
|
| 134 |
+
"--steps_per_epoch",
|
| 135 |
+
type=int,
|
| 136 |
+
default=500,
|
| 137 |
+
help="Number of steps per epoch.",
|
| 138 |
+
)
|
| 139 |
+
parser.add_argument(
|
| 140 |
+
"--height",
|
| 141 |
+
type=int,
|
| 142 |
+
default=1024,
|
| 143 |
+
help="Image height.",
|
| 144 |
+
)
|
| 145 |
+
parser.add_argument(
|
| 146 |
+
"--width",
|
| 147 |
+
type=int,
|
| 148 |
+
default=1024,
|
| 149 |
+
help="Image width.",
|
| 150 |
+
)
|
| 151 |
+
parser.add_argument(
|
| 152 |
+
"--center_crop",
|
| 153 |
+
default=False,
|
| 154 |
+
action="store_true",
|
| 155 |
+
help=(
|
| 156 |
+
"Whether to center crop the input images to the resolution. If not set, the images will be randomly"
|
| 157 |
+
" cropped. The images will be resized to the resolution first before cropping."
|
| 158 |
+
),
|
| 159 |
+
)
|
| 160 |
+
parser.add_argument(
|
| 161 |
+
"--random_flip",
|
| 162 |
+
default=False,
|
| 163 |
+
action="store_true",
|
| 164 |
+
help="Whether to randomly flip images horizontally",
|
| 165 |
+
)
|
| 166 |
+
parser.add_argument(
|
| 167 |
+
"--batch_size",
|
| 168 |
+
type=int,
|
| 169 |
+
default=1,
|
| 170 |
+
help="Batch size (per device) for the training dataloader.",
|
| 171 |
+
)
|
| 172 |
+
parser.add_argument(
|
| 173 |
+
"--dataloader_num_workers",
|
| 174 |
+
type=int,
|
| 175 |
+
default=0,
|
| 176 |
+
help="Number of subprocesses to use for data loading. 0 means that the data will be loaded in the main process.",
|
| 177 |
+
)
|
| 178 |
+
parser.add_argument(
|
| 179 |
+
"--precision",
|
| 180 |
+
type=str,
|
| 181 |
+
default="16-mixed",
|
| 182 |
+
choices=["32", "16", "16-mixed", "bf16"],
|
| 183 |
+
help="Training precision",
|
| 184 |
+
)
|
| 185 |
+
parser.add_argument(
|
| 186 |
+
"--learning_rate",
|
| 187 |
+
type=float,
|
| 188 |
+
default=1e-4,
|
| 189 |
+
help="Learning rate.",
|
| 190 |
+
)
|
| 191 |
+
parser.add_argument(
|
| 192 |
+
"--lora_rank",
|
| 193 |
+
type=int,
|
| 194 |
+
default=4,
|
| 195 |
+
help="The dimension of the LoRA update matrices.",
|
| 196 |
+
)
|
| 197 |
+
parser.add_argument(
|
| 198 |
+
"--lora_alpha",
|
| 199 |
+
type=float,
|
| 200 |
+
default=4.0,
|
| 201 |
+
help="The weight of the LoRA update matrices.",
|
| 202 |
+
)
|
| 203 |
+
parser.add_argument(
|
| 204 |
+
"--init_lora_weights",
|
| 205 |
+
type=str,
|
| 206 |
+
default="kaiming",
|
| 207 |
+
choices=["gaussian", "kaiming"],
|
| 208 |
+
help="The initializing method of LoRA weight.",
|
| 209 |
+
)
|
| 210 |
+
parser.add_argument(
|
| 211 |
+
"--use_gradient_checkpointing",
|
| 212 |
+
default=False,
|
| 213 |
+
action="store_true",
|
| 214 |
+
help="Whether to use gradient checkpointing.",
|
| 215 |
+
)
|
| 216 |
+
parser.add_argument(
|
| 217 |
+
"--accumulate_grad_batches",
|
| 218 |
+
type=int,
|
| 219 |
+
default=1,
|
| 220 |
+
help="The number of batches in gradient accumulation.",
|
| 221 |
+
)
|
| 222 |
+
parser.add_argument(
|
| 223 |
+
"--training_strategy",
|
| 224 |
+
type=str,
|
| 225 |
+
default="auto",
|
| 226 |
+
choices=["auto", "deepspeed_stage_1", "deepspeed_stage_2", "deepspeed_stage_3"],
|
| 227 |
+
help="Training strategy",
|
| 228 |
+
)
|
| 229 |
+
parser.add_argument(
|
| 230 |
+
"--max_epochs",
|
| 231 |
+
type=int,
|
| 232 |
+
default=1,
|
| 233 |
+
help="Number of epochs.",
|
| 234 |
+
)
|
| 235 |
+
parser.add_argument(
|
| 236 |
+
"--modelscope_model_id",
|
| 237 |
+
type=str,
|
| 238 |
+
default=None,
|
| 239 |
+
help="Model ID on ModelScope (https://www.modelscope.cn/). The model will be uploaded to ModelScope automatically if you provide a Model ID.",
|
| 240 |
+
)
|
| 241 |
+
parser.add_argument(
|
| 242 |
+
"--modelscope_access_token",
|
| 243 |
+
type=str,
|
| 244 |
+
default=None,
|
| 245 |
+
help="Access key on ModelScope (https://www.modelscope.cn/). Required if you want to upload the model to ModelScope.",
|
| 246 |
+
)
|
| 247 |
+
parser.add_argument(
|
| 248 |
+
"--pretrained_lora_path",
|
| 249 |
+
type=str,
|
| 250 |
+
default=None,
|
| 251 |
+
help="Pretrained LoRA path. Required if the training is resumed.",
|
| 252 |
+
)
|
| 253 |
+
parser.add_argument(
|
| 254 |
+
"--use_swanlab",
|
| 255 |
+
default=False,
|
| 256 |
+
action="store_true",
|
| 257 |
+
help="Whether to use SwanLab logger.",
|
| 258 |
+
)
|
| 259 |
+
parser.add_argument(
|
| 260 |
+
"--swanlab_mode",
|
| 261 |
+
default=None,
|
| 262 |
+
help="SwanLab mode (cloud or local).",
|
| 263 |
+
)
|
| 264 |
+
return parser
|
| 265 |
+
|
| 266 |
+
|
| 267 |
+
def launch_training_task(model, args):
|
| 268 |
+
# dataset and data loader
|
| 269 |
+
dataset = TextImageDataset(
|
| 270 |
+
args.dataset_path,
|
| 271 |
+
steps_per_epoch=args.steps_per_epoch * args.batch_size,
|
| 272 |
+
height=args.height,
|
| 273 |
+
width=args.width,
|
| 274 |
+
center_crop=args.center_crop,
|
| 275 |
+
random_flip=args.random_flip
|
| 276 |
+
)
|
| 277 |
+
train_loader = torch.utils.data.DataLoader(
|
| 278 |
+
dataset,
|
| 279 |
+
shuffle=True,
|
| 280 |
+
batch_size=args.batch_size,
|
| 281 |
+
num_workers=args.dataloader_num_workers
|
| 282 |
+
)
|
| 283 |
+
# train
|
| 284 |
+
if args.use_swanlab:
|
| 285 |
+
from swanlab.integration.pytorch_lightning import SwanLabLogger
|
| 286 |
+
swanlab_config = {"UPPERFRAMEWORK": "DiffSynth-Studio"}
|
| 287 |
+
swanlab_config.update(vars(args))
|
| 288 |
+
swanlab_logger = SwanLabLogger(
|
| 289 |
+
project="diffsynth_studio",
|
| 290 |
+
name="diffsynth_studio",
|
| 291 |
+
config=swanlab_config,
|
| 292 |
+
mode=args.swanlab_mode,
|
| 293 |
+
logdir=os.path.join(args.output_path, "swanlog"),
|
| 294 |
+
)
|
| 295 |
+
logger = [swanlab_logger]
|
| 296 |
+
else:
|
| 297 |
+
logger = None
|
| 298 |
+
trainer = pl.Trainer(
|
| 299 |
+
max_epochs=args.max_epochs,
|
| 300 |
+
accelerator="gpu",
|
| 301 |
+
devices="auto",
|
| 302 |
+
precision=args.precision,
|
| 303 |
+
strategy=args.training_strategy,
|
| 304 |
+
default_root_dir=args.output_path,
|
| 305 |
+
accumulate_grad_batches=args.accumulate_grad_batches,
|
| 306 |
+
callbacks=[pl.pytorch.callbacks.ModelCheckpoint(save_top_k=-1)],
|
| 307 |
+
logger=logger,
|
| 308 |
+
)
|
| 309 |
+
trainer.fit(model=model, train_dataloaders=train_loader)
|
| 310 |
+
|
| 311 |
+
# Upload models
|
| 312 |
+
if args.modelscope_model_id is not None and args.modelscope_access_token is not None:
|
| 313 |
+
print(f"Uploading models to modelscope. model_id: {args.modelscope_model_id} local_path: {trainer.log_dir}")
|
| 314 |
+
with open(os.path.join(trainer.log_dir, "configuration.json"), "w", encoding="utf-8") as f:
|
| 315 |
+
f.write('{"framework":"Pytorch","task":"text-to-image-synthesis"}\n')
|
| 316 |
+
api = HubApi()
|
| 317 |
+
api.login(args.modelscope_access_token)
|
| 318 |
+
api.push_model(model_id=args.modelscope_model_id, model_dir=trainer.log_dir)
|
diffsynth/trainers/utils.py
ADDED
|
@@ -0,0 +1,506 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import imageio, os, torch, warnings, torchvision, argparse, json
|
| 2 |
+
from peft import LoraConfig, inject_adapter_in_model
|
| 3 |
+
from PIL import Image
|
| 4 |
+
import pandas as pd
|
| 5 |
+
from tqdm import tqdm
|
| 6 |
+
from accelerate import Accelerator
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class ImageDataset(torch.utils.data.Dataset):
|
| 11 |
+
def __init__(
|
| 12 |
+
self,
|
| 13 |
+
base_path=None, metadata_path=None,
|
| 14 |
+
max_pixels=1920*1080, height=None, width=None,
|
| 15 |
+
height_division_factor=16, width_division_factor=16,
|
| 16 |
+
data_file_keys=("image",),
|
| 17 |
+
image_file_extension=("jpg", "jpeg", "png", "webp"),
|
| 18 |
+
repeat=1,
|
| 19 |
+
args=None,
|
| 20 |
+
):
|
| 21 |
+
if args is not None:
|
| 22 |
+
base_path = args.dataset_base_path
|
| 23 |
+
metadata_path = args.dataset_metadata_path
|
| 24 |
+
height = args.height
|
| 25 |
+
width = args.width
|
| 26 |
+
max_pixels = args.max_pixels
|
| 27 |
+
data_file_keys = args.data_file_keys.split(",")
|
| 28 |
+
repeat = args.dataset_repeat
|
| 29 |
+
|
| 30 |
+
self.base_path = base_path
|
| 31 |
+
self.max_pixels = max_pixels
|
| 32 |
+
self.height = height
|
| 33 |
+
self.width = width
|
| 34 |
+
self.height_division_factor = height_division_factor
|
| 35 |
+
self.width_division_factor = width_division_factor
|
| 36 |
+
self.data_file_keys = data_file_keys
|
| 37 |
+
self.image_file_extension = image_file_extension
|
| 38 |
+
self.repeat = repeat
|
| 39 |
+
|
| 40 |
+
if height is not None and width is not None:
|
| 41 |
+
print("Height and width are fixed. Setting `dynamic_resolution` to False.")
|
| 42 |
+
self.dynamic_resolution = False
|
| 43 |
+
elif height is None and width is None:
|
| 44 |
+
print("Height and width are none. Setting `dynamic_resolution` to True.")
|
| 45 |
+
self.dynamic_resolution = True
|
| 46 |
+
|
| 47 |
+
if metadata_path is None:
|
| 48 |
+
print("No metadata. Trying to generate it.")
|
| 49 |
+
metadata = self.generate_metadata(base_path)
|
| 50 |
+
print(f"{len(metadata)} lines in metadata.")
|
| 51 |
+
self.data = [metadata.iloc[i].to_dict() for i in range(len(metadata))]
|
| 52 |
+
elif metadata_path.endswith(".json"):
|
| 53 |
+
with open(metadata_path, "r") as f:
|
| 54 |
+
metadata = json.load(f)
|
| 55 |
+
self.data = metadata
|
| 56 |
+
elif metadata_path.endswith(".jsonl"):
|
| 57 |
+
metadata = []
|
| 58 |
+
with open(metadata_path, 'r') as f:
|
| 59 |
+
for line in tqdm(f):
|
| 60 |
+
metadata.append(json.loads(line.strip()))
|
| 61 |
+
self.data = metadata
|
| 62 |
+
else:
|
| 63 |
+
metadata = pd.read_csv(metadata_path)
|
| 64 |
+
self.data = [metadata.iloc[i].to_dict() for i in range(len(metadata))]
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def generate_metadata(self, folder):
|
| 68 |
+
image_list, prompt_list = [], []
|
| 69 |
+
file_set = set(os.listdir(folder))
|
| 70 |
+
for file_name in file_set:
|
| 71 |
+
if "." not in file_name:
|
| 72 |
+
continue
|
| 73 |
+
file_ext_name = file_name.split(".")[-1].lower()
|
| 74 |
+
file_base_name = file_name[:-len(file_ext_name)-1]
|
| 75 |
+
if file_ext_name not in self.image_file_extension:
|
| 76 |
+
continue
|
| 77 |
+
prompt_file_name = file_base_name + ".txt"
|
| 78 |
+
if prompt_file_name not in file_set:
|
| 79 |
+
continue
|
| 80 |
+
with open(os.path.join(folder, prompt_file_name), "r", encoding="utf-8") as f:
|
| 81 |
+
prompt = f.read().strip()
|
| 82 |
+
image_list.append(file_name)
|
| 83 |
+
prompt_list.append(prompt)
|
| 84 |
+
metadata = pd.DataFrame()
|
| 85 |
+
metadata["image"] = image_list
|
| 86 |
+
metadata["prompt"] = prompt_list
|
| 87 |
+
return metadata
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def crop_and_resize(self, image, target_height, target_width):
|
| 91 |
+
width, height = image.size
|
| 92 |
+
scale = max(target_width / width, target_height / height)
|
| 93 |
+
image = torchvision.transforms.functional.resize(
|
| 94 |
+
image,
|
| 95 |
+
(round(height*scale), round(width*scale)),
|
| 96 |
+
interpolation=torchvision.transforms.InterpolationMode.BILINEAR
|
| 97 |
+
)
|
| 98 |
+
image = torchvision.transforms.functional.center_crop(image, (target_height, target_width))
|
| 99 |
+
return image
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
def get_height_width(self, image):
|
| 103 |
+
if self.dynamic_resolution:
|
| 104 |
+
width, height = image.size
|
| 105 |
+
if width * height > self.max_pixels:
|
| 106 |
+
scale = (width * height / self.max_pixels) ** 0.5
|
| 107 |
+
height, width = int(height / scale), int(width / scale)
|
| 108 |
+
height = height // self.height_division_factor * self.height_division_factor
|
| 109 |
+
width = width // self.width_division_factor * self.width_division_factor
|
| 110 |
+
else:
|
| 111 |
+
height, width = self.height, self.width
|
| 112 |
+
return height, width
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def load_image(self, file_path):
|
| 116 |
+
image = Image.open(file_path).convert("RGB")
|
| 117 |
+
image = self.crop_and_resize(image, *self.get_height_width(image))
|
| 118 |
+
return image
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
def load_data(self, file_path):
|
| 122 |
+
return self.load_image(file_path)
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def __getitem__(self, data_id):
|
| 126 |
+
data = self.data[data_id % len(self.data)].copy()
|
| 127 |
+
for key in self.data_file_keys:
|
| 128 |
+
if key in data:
|
| 129 |
+
if isinstance(data[key], list):
|
| 130 |
+
path = [os.path.join(self.base_path, p) for p in data[key]]
|
| 131 |
+
data[key] = [self.load_data(p) for p in path]
|
| 132 |
+
else:
|
| 133 |
+
path = os.path.join(self.base_path, data[key])
|
| 134 |
+
data[key] = self.load_data(path)
|
| 135 |
+
if data[key] is None:
|
| 136 |
+
warnings.warn(f"cannot load file {data[key]}.")
|
| 137 |
+
return None
|
| 138 |
+
return data
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def __len__(self):
|
| 142 |
+
return len(self.data) * self.repeat
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
class VideoDataset(torch.utils.data.Dataset):
|
| 147 |
+
def __init__(
|
| 148 |
+
self,
|
| 149 |
+
base_path=None, metadata_path=None,
|
| 150 |
+
num_frames=81,
|
| 151 |
+
time_division_factor=4, time_division_remainder=1,
|
| 152 |
+
max_pixels=1920*1080, height=None, width=None,
|
| 153 |
+
height_division_factor=16, width_division_factor=16,
|
| 154 |
+
data_file_keys=("video",),
|
| 155 |
+
image_file_extension=("jpg", "jpeg", "png", "webp"),
|
| 156 |
+
video_file_extension=("mp4", "avi", "mov", "wmv", "mkv", "flv", "webm"),
|
| 157 |
+
repeat=1,
|
| 158 |
+
args=None,
|
| 159 |
+
):
|
| 160 |
+
if args is not None:
|
| 161 |
+
base_path = args.dataset_base_path
|
| 162 |
+
metadata_path = args.dataset_metadata_path
|
| 163 |
+
height = args.height
|
| 164 |
+
width = args.width
|
| 165 |
+
max_pixels = args.max_pixels
|
| 166 |
+
num_frames = args.num_frames
|
| 167 |
+
data_file_keys = args.data_file_keys.split(",")
|
| 168 |
+
repeat = args.dataset_repeat
|
| 169 |
+
|
| 170 |
+
self.base_path = base_path
|
| 171 |
+
self.num_frames = num_frames
|
| 172 |
+
self.time_division_factor = time_division_factor
|
| 173 |
+
self.time_division_remainder = time_division_remainder
|
| 174 |
+
self.max_pixels = max_pixels
|
| 175 |
+
self.height = height
|
| 176 |
+
self.width = width
|
| 177 |
+
self.height_division_factor = height_division_factor
|
| 178 |
+
self.width_division_factor = width_division_factor
|
| 179 |
+
self.data_file_keys = data_file_keys
|
| 180 |
+
self.image_file_extension = image_file_extension
|
| 181 |
+
self.video_file_extension = video_file_extension
|
| 182 |
+
self.repeat = repeat
|
| 183 |
+
|
| 184 |
+
if height is not None and width is not None:
|
| 185 |
+
print("Height and width are fixed. Setting `dynamic_resolution` to False.")
|
| 186 |
+
self.dynamic_resolution = False
|
| 187 |
+
elif height is None and width is None:
|
| 188 |
+
print("Height and width are none. Setting `dynamic_resolution` to True.")
|
| 189 |
+
self.dynamic_resolution = True
|
| 190 |
+
|
| 191 |
+
if metadata_path is None:
|
| 192 |
+
print("No metadata. Trying to generate it.")
|
| 193 |
+
metadata = self.generate_metadata(base_path)
|
| 194 |
+
print(f"{len(metadata)} lines in metadata.")
|
| 195 |
+
self.data = [metadata.iloc[i].to_dict() for i in range(len(metadata))]
|
| 196 |
+
elif metadata_path.endswith(".json"):
|
| 197 |
+
with open(metadata_path, "r") as f:
|
| 198 |
+
metadata = json.load(f)
|
| 199 |
+
self.data = metadata
|
| 200 |
+
else:
|
| 201 |
+
metadata = pd.read_csv(metadata_path)
|
| 202 |
+
self.data = [metadata.iloc[i].to_dict() for i in range(len(metadata))]
|
| 203 |
+
|
| 204 |
+
|
| 205 |
+
def generate_metadata(self, folder):
|
| 206 |
+
video_list, prompt_list = [], []
|
| 207 |
+
file_set = set(os.listdir(folder))
|
| 208 |
+
for file_name in file_set:
|
| 209 |
+
if "." not in file_name:
|
| 210 |
+
continue
|
| 211 |
+
file_ext_name = file_name.split(".")[-1].lower()
|
| 212 |
+
file_base_name = file_name[:-len(file_ext_name)-1]
|
| 213 |
+
if file_ext_name not in self.image_file_extension and file_ext_name not in self.video_file_extension:
|
| 214 |
+
continue
|
| 215 |
+
prompt_file_name = file_base_name + ".txt"
|
| 216 |
+
if prompt_file_name not in file_set:
|
| 217 |
+
continue
|
| 218 |
+
with open(os.path.join(folder, prompt_file_name), "r", encoding="utf-8") as f:
|
| 219 |
+
prompt = f.read().strip()
|
| 220 |
+
video_list.append(file_name)
|
| 221 |
+
prompt_list.append(prompt)
|
| 222 |
+
metadata = pd.DataFrame()
|
| 223 |
+
metadata["video"] = video_list
|
| 224 |
+
metadata["prompt"] = prompt_list
|
| 225 |
+
return metadata
|
| 226 |
+
|
| 227 |
+
|
| 228 |
+
def crop_and_resize(self, image, target_height, target_width):
|
| 229 |
+
width, height = image.size
|
| 230 |
+
scale = max(target_width / width, target_height / height)
|
| 231 |
+
image = torchvision.transforms.functional.resize(
|
| 232 |
+
image,
|
| 233 |
+
(round(height*scale), round(width*scale)),
|
| 234 |
+
interpolation=torchvision.transforms.InterpolationMode.BILINEAR
|
| 235 |
+
)
|
| 236 |
+
image = torchvision.transforms.functional.center_crop(image, (target_height, target_width))
|
| 237 |
+
return image
|
| 238 |
+
|
| 239 |
+
|
| 240 |
+
def get_height_width(self, image):
|
| 241 |
+
if self.dynamic_resolution:
|
| 242 |
+
width, height = image.size
|
| 243 |
+
if width * height > self.max_pixels:
|
| 244 |
+
scale = (width * height / self.max_pixels) ** 0.5
|
| 245 |
+
height, width = int(height / scale), int(width / scale)
|
| 246 |
+
height = height // self.height_division_factor * self.height_division_factor
|
| 247 |
+
width = width // self.width_division_factor * self.width_division_factor
|
| 248 |
+
else:
|
| 249 |
+
height, width = self.height, self.width
|
| 250 |
+
return height, width
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
def get_num_frames(self, reader):
|
| 254 |
+
num_frames = self.num_frames
|
| 255 |
+
if int(reader.count_frames()) < num_frames:
|
| 256 |
+
num_frames = int(reader.count_frames())
|
| 257 |
+
while num_frames > 1 and num_frames % self.time_division_factor != self.time_division_remainder:
|
| 258 |
+
num_frames -= 1
|
| 259 |
+
return num_frames
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
def load_video(self, file_path):
|
| 263 |
+
reader = imageio.get_reader(file_path)
|
| 264 |
+
num_frames = self.get_num_frames(reader)
|
| 265 |
+
frames = []
|
| 266 |
+
for frame_id in range(num_frames):
|
| 267 |
+
frame = reader.get_data(frame_id)
|
| 268 |
+
frame = Image.fromarray(frame)
|
| 269 |
+
frame = self.crop_and_resize(frame, *self.get_height_width(frame))
|
| 270 |
+
frames.append(frame)
|
| 271 |
+
reader.close()
|
| 272 |
+
return frames
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
def load_image(self, file_path):
|
| 276 |
+
image = Image.open(file_path).convert("RGB")
|
| 277 |
+
image = self.crop_and_resize(image, *self.get_height_width(image))
|
| 278 |
+
frames = [image]
|
| 279 |
+
return frames
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
def is_image(self, file_path):
|
| 283 |
+
file_ext_name = file_path.split(".")[-1]
|
| 284 |
+
return file_ext_name.lower() in self.image_file_extension
|
| 285 |
+
|
| 286 |
+
|
| 287 |
+
def is_video(self, file_path):
|
| 288 |
+
file_ext_name = file_path.split(".")[-1]
|
| 289 |
+
return file_ext_name.lower() in self.video_file_extension
|
| 290 |
+
|
| 291 |
+
|
| 292 |
+
def load_data(self, file_path):
|
| 293 |
+
if self.is_image(file_path):
|
| 294 |
+
return self.load_image(file_path)
|
| 295 |
+
elif self.is_video(file_path):
|
| 296 |
+
return self.load_video(file_path)
|
| 297 |
+
else:
|
| 298 |
+
return None
|
| 299 |
+
|
| 300 |
+
|
| 301 |
+
def __getitem__(self, data_id):
|
| 302 |
+
data = self.data[data_id % len(self.data)].copy()
|
| 303 |
+
for key in self.data_file_keys:
|
| 304 |
+
if key in data:
|
| 305 |
+
path = os.path.join(self.base_path, data[key])
|
| 306 |
+
data[key] = self.load_data(path)
|
| 307 |
+
if data[key] is None:
|
| 308 |
+
warnings.warn(f"cannot load file {data[key]}.")
|
| 309 |
+
return None
|
| 310 |
+
return data
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
def __len__(self):
|
| 314 |
+
return len(self.data) * self.repeat
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
|
| 318 |
+
class DiffusionTrainingModule(torch.nn.Module):
|
| 319 |
+
def __init__(self):
|
| 320 |
+
super().__init__()
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
def to(self, *args, **kwargs):
|
| 324 |
+
for name, model in self.named_children():
|
| 325 |
+
model.to(*args, **kwargs)
|
| 326 |
+
return self
|
| 327 |
+
|
| 328 |
+
|
| 329 |
+
def trainable_modules(self):
|
| 330 |
+
trainable_modules = filter(lambda p: p.requires_grad, self.parameters())
|
| 331 |
+
return trainable_modules
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
def trainable_param_names(self):
|
| 335 |
+
trainable_param_names = list(filter(lambda named_param: named_param[1].requires_grad, self.named_parameters()))
|
| 336 |
+
trainable_param_names = set([named_param[0] for named_param in trainable_param_names])
|
| 337 |
+
return trainable_param_names
|
| 338 |
+
|
| 339 |
+
|
| 340 |
+
def add_lora_to_model(self, model, target_modules, lora_rank, lora_alpha=None):
|
| 341 |
+
if lora_alpha is None:
|
| 342 |
+
lora_alpha = lora_rank
|
| 343 |
+
lora_config = LoraConfig(r=lora_rank, lora_alpha=lora_alpha, target_modules=target_modules)
|
| 344 |
+
model = inject_adapter_in_model(lora_config, model)
|
| 345 |
+
return model
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
def export_trainable_state_dict(self, state_dict, remove_prefix=None):
|
| 349 |
+
trainable_param_names = self.trainable_param_names()
|
| 350 |
+
state_dict = {name: param for name, param in state_dict.items() if name in trainable_param_names}
|
| 351 |
+
if remove_prefix is not None:
|
| 352 |
+
state_dict_ = {}
|
| 353 |
+
for name, param in state_dict.items():
|
| 354 |
+
if name.startswith(remove_prefix):
|
| 355 |
+
name = name[len(remove_prefix):]
|
| 356 |
+
state_dict_[name] = param
|
| 357 |
+
state_dict = state_dict_
|
| 358 |
+
return state_dict
|
| 359 |
+
|
| 360 |
+
|
| 361 |
+
|
| 362 |
+
class ModelLogger:
|
| 363 |
+
def __init__(self, output_path, remove_prefix_in_ckpt=None, state_dict_converter=lambda x:x):
|
| 364 |
+
self.output_path = output_path
|
| 365 |
+
self.remove_prefix_in_ckpt = remove_prefix_in_ckpt
|
| 366 |
+
self.state_dict_converter = state_dict_converter
|
| 367 |
+
|
| 368 |
+
|
| 369 |
+
def on_step_end(self, loss):
|
| 370 |
+
pass
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
def on_epoch_end(self, accelerator, model, epoch_id):
|
| 374 |
+
accelerator.wait_for_everyone()
|
| 375 |
+
if accelerator.is_main_process:
|
| 376 |
+
state_dict = accelerator.get_state_dict(model)
|
| 377 |
+
state_dict = accelerator.unwrap_model(model).export_trainable_state_dict(state_dict, remove_prefix=self.remove_prefix_in_ckpt)
|
| 378 |
+
state_dict = self.state_dict_converter(state_dict)
|
| 379 |
+
os.makedirs(self.output_path, exist_ok=True)
|
| 380 |
+
path = os.path.join(self.output_path, f"epoch-{epoch_id}.safetensors")
|
| 381 |
+
accelerator.save(state_dict, path, safe_serialization=True)
|
| 382 |
+
|
| 383 |
+
|
| 384 |
+
|
| 385 |
+
def launch_training_task(
|
| 386 |
+
dataset: torch.utils.data.Dataset,
|
| 387 |
+
model: DiffusionTrainingModule,
|
| 388 |
+
model_logger: ModelLogger,
|
| 389 |
+
optimizer: torch.optim.Optimizer,
|
| 390 |
+
scheduler: torch.optim.lr_scheduler.LRScheduler,
|
| 391 |
+
num_epochs: int = 1,
|
| 392 |
+
gradient_accumulation_steps: int = 1,
|
| 393 |
+
):
|
| 394 |
+
dataloader = torch.utils.data.DataLoader(dataset, shuffle=True, collate_fn=lambda x: x[0])
|
| 395 |
+
accelerator = Accelerator(gradient_accumulation_steps=gradient_accumulation_steps)
|
| 396 |
+
model, optimizer, dataloader, scheduler = accelerator.prepare(model, optimizer, dataloader, scheduler)
|
| 397 |
+
|
| 398 |
+
for epoch_id in range(num_epochs):
|
| 399 |
+
for data in tqdm(dataloader):
|
| 400 |
+
with accelerator.accumulate(model):
|
| 401 |
+
optimizer.zero_grad()
|
| 402 |
+
loss = model(data)
|
| 403 |
+
accelerator.backward(loss)
|
| 404 |
+
optimizer.step()
|
| 405 |
+
model_logger.on_step_end(loss)
|
| 406 |
+
scheduler.step()
|
| 407 |
+
model_logger.on_epoch_end(accelerator, model, epoch_id)
|
| 408 |
+
|
| 409 |
+
|
| 410 |
+
|
| 411 |
+
def launch_data_process_task(model: DiffusionTrainingModule, dataset, output_path="./models"):
|
| 412 |
+
dataloader = torch.utils.data.DataLoader(dataset, shuffle=False, collate_fn=lambda x: x[0])
|
| 413 |
+
accelerator = Accelerator()
|
| 414 |
+
model, dataloader = accelerator.prepare(model, dataloader)
|
| 415 |
+
os.makedirs(os.path.join(output_path, "data_cache"), exist_ok=True)
|
| 416 |
+
for data_id, data in enumerate(tqdm(dataloader)):
|
| 417 |
+
with torch.no_grad():
|
| 418 |
+
inputs = model.forward_preprocess(data)
|
| 419 |
+
inputs = {key: inputs[key] for key in model.model_input_keys if key in inputs}
|
| 420 |
+
torch.save(inputs, os.path.join(output_path, "data_cache", f"{data_id}.pth"))
|
| 421 |
+
|
| 422 |
+
|
| 423 |
+
|
| 424 |
+
def wan_parser():
|
| 425 |
+
parser = argparse.ArgumentParser(description="Simple example of a training script.")
|
| 426 |
+
parser.add_argument("--dataset_base_path", type=str, default="", required=True, help="Base path of the dataset.")
|
| 427 |
+
parser.add_argument("--dataset_metadata_path", type=str, default=None, help="Path to the metadata file of the dataset.")
|
| 428 |
+
parser.add_argument("--max_pixels", type=int, default=1280*720, help="Maximum number of pixels per frame, used for dynamic resolution..")
|
| 429 |
+
parser.add_argument("--height", type=int, default=None, help="Height of images or videos. Leave `height` and `width` empty to enable dynamic resolution.")
|
| 430 |
+
parser.add_argument("--width", type=int, default=None, help="Width of images or videos. Leave `height` and `width` empty to enable dynamic resolution.")
|
| 431 |
+
parser.add_argument("--num_frames", type=int, default=81, help="Number of frames per video. Frames are sampled from the video prefix.")
|
| 432 |
+
parser.add_argument("--data_file_keys", type=str, default="image,video", help="Data file keys in the metadata. Comma-separated.")
|
| 433 |
+
parser.add_argument("--dataset_repeat", type=int, default=1, help="Number of times to repeat the dataset per epoch.")
|
| 434 |
+
parser.add_argument("--model_paths", type=str, default=None, help="Paths to load models. In JSON format.")
|
| 435 |
+
parser.add_argument("--model_id_with_origin_paths", type=str, default=None, help="Model ID with origin paths, e.g., Wan-AI/Wan2.1-T2V-1.3B:diffusion_pytorch_model*.safetensors. Comma-separated.")
|
| 436 |
+
parser.add_argument("--learning_rate", type=float, default=1e-4, help="Learning rate.")
|
| 437 |
+
parser.add_argument("--num_epochs", type=int, default=1, help="Number of epochs.")
|
| 438 |
+
parser.add_argument("--output_path", type=str, default="./models", help="Output save path.")
|
| 439 |
+
parser.add_argument("--remove_prefix_in_ckpt", type=str, default="pipe.dit.", help="Remove prefix in ckpt.")
|
| 440 |
+
parser.add_argument("--trainable_models", type=str, default=None, help="Models to train, e.g., dit, vae, text_encoder.")
|
| 441 |
+
parser.add_argument("--lora_base_model", type=str, default=None, help="Which model LoRA is added to.")
|
| 442 |
+
parser.add_argument("--lora_target_modules", type=str, default="q,k,v,o,ffn.0,ffn.2", help="Which layers LoRA is added to.")
|
| 443 |
+
parser.add_argument("--lora_rank", type=int, default=32, help="Rank of LoRA.")
|
| 444 |
+
parser.add_argument("--extra_inputs", default=None, help="Additional model inputs, comma-separated.")
|
| 445 |
+
parser.add_argument("--use_gradient_checkpointing_offload", default=False, action="store_true", help="Whether to offload gradient checkpointing to CPU memory.")
|
| 446 |
+
parser.add_argument("--gradient_accumulation_steps", type=int, default=1, help="Gradient accumulation steps.")
|
| 447 |
+
parser.add_argument("--max_timestep_boundary", type=float, default=1.0, help="Max timestep boundary (for mixed models, e.g., Wan-AI/Wan2.2-I2V-A14B).")
|
| 448 |
+
parser.add_argument("--min_timestep_boundary", type=float, default=0.0, help="Min timestep boundary (for mixed models, e.g., Wan-AI/Wan2.2-I2V-A14B).")
|
| 449 |
+
return parser
|
| 450 |
+
|
| 451 |
+
|
| 452 |
+
|
| 453 |
+
def flux_parser():
|
| 454 |
+
parser = argparse.ArgumentParser(description="Simple example of a training script.")
|
| 455 |
+
parser.add_argument("--dataset_base_path", type=str, default="", required=True, help="Base path of the dataset.")
|
| 456 |
+
parser.add_argument("--dataset_metadata_path", type=str, default=None, help="Path to the metadata file of the dataset.")
|
| 457 |
+
parser.add_argument("--max_pixels", type=int, default=1024*1024, help="Maximum number of pixels per frame, used for dynamic resolution..")
|
| 458 |
+
parser.add_argument("--height", type=int, default=None, help="Height of images. Leave `height` and `width` empty to enable dynamic resolution.")
|
| 459 |
+
parser.add_argument("--width", type=int, default=None, help="Width of images. Leave `height` and `width` empty to enable dynamic resolution.")
|
| 460 |
+
parser.add_argument("--data_file_keys", type=str, default="image", help="Data file keys in the metadata. Comma-separated.")
|
| 461 |
+
parser.add_argument("--dataset_repeat", type=int, default=1, help="Number of times to repeat the dataset per epoch.")
|
| 462 |
+
parser.add_argument("--model_paths", type=str, default=None, help="Paths to load models. In JSON format.")
|
| 463 |
+
parser.add_argument("--model_id_with_origin_paths", type=str, default=None, help="Model ID with origin paths, e.g., Wan-AI/Wan2.1-T2V-1.3B:diffusion_pytorch_model*.safetensors. Comma-separated.")
|
| 464 |
+
parser.add_argument("--learning_rate", type=float, default=1e-4, help="Learning rate.")
|
| 465 |
+
parser.add_argument("--num_epochs", type=int, default=1, help="Number of epochs.")
|
| 466 |
+
parser.add_argument("--output_path", type=str, default="./models", help="Output save path.")
|
| 467 |
+
parser.add_argument("--remove_prefix_in_ckpt", type=str, default="pipe.dit.", help="Remove prefix in ckpt.")
|
| 468 |
+
parser.add_argument("--trainable_models", type=str, default=None, help="Models to train, e.g., dit, vae, text_encoder.")
|
| 469 |
+
parser.add_argument("--lora_base_model", type=str, default=None, help="Which model LoRA is added to.")
|
| 470 |
+
parser.add_argument("--lora_target_modules", type=str, default="q,k,v,o,ffn.0,ffn.2", help="Which layers LoRA is added to.")
|
| 471 |
+
parser.add_argument("--lora_rank", type=int, default=32, help="Rank of LoRA.")
|
| 472 |
+
parser.add_argument("--extra_inputs", default=None, help="Additional model inputs, comma-separated.")
|
| 473 |
+
parser.add_argument("--align_to_opensource_format", default=False, action="store_true", help="Whether to align the lora format to opensource format. Only for DiT's LoRA.")
|
| 474 |
+
parser.add_argument("--use_gradient_checkpointing", default=False, action="store_true", help="Whether to use gradient checkpointing.")
|
| 475 |
+
parser.add_argument("--use_gradient_checkpointing_offload", default=False, action="store_true", help="Whether to offload gradient checkpointing to CPU memory.")
|
| 476 |
+
parser.add_argument("--gradient_accumulation_steps", type=int, default=1, help="Gradient accumulation steps.")
|
| 477 |
+
return parser
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
|
| 481 |
+
def qwen_image_parser():
|
| 482 |
+
parser = argparse.ArgumentParser(description="Simple example of a training script.")
|
| 483 |
+
parser.add_argument("--dataset_base_path", type=str, default="", required=True, help="Base path of the dataset.")
|
| 484 |
+
parser.add_argument("--dataset_metadata_path", type=str, default=None, help="Path to the metadata file of the dataset.")
|
| 485 |
+
parser.add_argument("--max_pixels", type=int, default=1024*1024, help="Maximum number of pixels per frame, used for dynamic resolution..")
|
| 486 |
+
parser.add_argument("--height", type=int, default=None, help="Height of images. Leave `height` and `width` empty to enable dynamic resolution.")
|
| 487 |
+
parser.add_argument("--width", type=int, default=None, help="Width of images. Leave `height` and `width` empty to enable dynamic resolution.")
|
| 488 |
+
parser.add_argument("--data_file_keys", type=str, default="image", help="Data file keys in the metadata. Comma-separated.")
|
| 489 |
+
parser.add_argument("--dataset_repeat", type=int, default=1, help="Number of times to repeat the dataset per epoch.")
|
| 490 |
+
parser.add_argument("--model_paths", type=str, default=None, help="Paths to load models. In JSON format.")
|
| 491 |
+
parser.add_argument("--model_id_with_origin_paths", type=str, default=None, help="Model ID with origin paths, e.g., Wan-AI/Wan2.1-T2V-1.3B:diffusion_pytorch_model*.safetensors. Comma-separated.")
|
| 492 |
+
parser.add_argument("--tokenizer_path", type=str, default=None, help="Paths to tokenizer.")
|
| 493 |
+
parser.add_argument("--learning_rate", type=float, default=1e-4, help="Learning rate.")
|
| 494 |
+
parser.add_argument("--num_epochs", type=int, default=1, help="Number of epochs.")
|
| 495 |
+
parser.add_argument("--output_path", type=str, default="./models", help="Output save path.")
|
| 496 |
+
parser.add_argument("--remove_prefix_in_ckpt", type=str, default="pipe.dit.", help="Remove prefix in ckpt.")
|
| 497 |
+
parser.add_argument("--trainable_models", type=str, default=None, help="Models to train, e.g., dit, vae, text_encoder.")
|
| 498 |
+
parser.add_argument("--lora_base_model", type=str, default=None, help="Which model LoRA is added to.")
|
| 499 |
+
parser.add_argument("--lora_target_modules", type=str, default="q,k,v,o,ffn.0,ffn.2", help="Which layers LoRA is added to.")
|
| 500 |
+
parser.add_argument("--lora_rank", type=int, default=32, help="Rank of LoRA.")
|
| 501 |
+
parser.add_argument("--extra_inputs", default=None, help="Additional model inputs, comma-separated.")
|
| 502 |
+
parser.add_argument("--align_to_opensource_format", default=False, action="store_true", help="Whether to align the lora format to opensource format. Only for DiT's LoRA.")
|
| 503 |
+
parser.add_argument("--use_gradient_checkpointing", default=False, action="store_true", help="Whether to use gradient checkpointing.")
|
| 504 |
+
parser.add_argument("--use_gradient_checkpointing_offload", default=False, action="store_true", help="Whether to offload gradient checkpointing to CPU memory.")
|
| 505 |
+
parser.add_argument("--gradient_accumulation_steps", type=int, default=1, help="Gradient accumulation steps.")
|
| 506 |
+
return parser
|
diffsynth/utils/__init__.py
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch, warnings, glob, os
|
| 2 |
+
import numpy as np
|
| 3 |
+
from PIL import Image
|
| 4 |
+
from einops import repeat, reduce
|
| 5 |
+
from typing import Optional, Union
|
| 6 |
+
from dataclasses import dataclass
|
| 7 |
+
from modelscope import snapshot_download
|
| 8 |
+
import numpy as np
|
| 9 |
+
from PIL import Image
|
| 10 |
+
from typing import Optional
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class BasePipeline(torch.nn.Module):
|
| 14 |
+
|
| 15 |
+
def __init__(
|
| 16 |
+
self,
|
| 17 |
+
device="cuda", torch_dtype=torch.float16,
|
| 18 |
+
height_division_factor=64, width_division_factor=64,
|
| 19 |
+
time_division_factor=None, time_division_remainder=None,
|
| 20 |
+
):
|
| 21 |
+
super().__init__()
|
| 22 |
+
# The device and torch_dtype is used for the storage of intermediate variables, not models.
|
| 23 |
+
self.device = device
|
| 24 |
+
self.torch_dtype = torch_dtype
|
| 25 |
+
# The following parameters are used for shape check.
|
| 26 |
+
self.height_division_factor = height_division_factor
|
| 27 |
+
self.width_division_factor = width_division_factor
|
| 28 |
+
self.time_division_factor = time_division_factor
|
| 29 |
+
self.time_division_remainder = time_division_remainder
|
| 30 |
+
self.vram_management_enabled = False
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def to(self, *args, **kwargs):
|
| 34 |
+
device, dtype, non_blocking, convert_to_format = torch._C._nn._parse_to(*args, **kwargs)
|
| 35 |
+
if device is not None:
|
| 36 |
+
self.device = device
|
| 37 |
+
if dtype is not None:
|
| 38 |
+
self.torch_dtype = dtype
|
| 39 |
+
super().to(*args, **kwargs)
|
| 40 |
+
return self
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def check_resize_height_width(self, height, width, num_frames=None):
|
| 44 |
+
# Shape check
|
| 45 |
+
if height % self.height_division_factor != 0:
|
| 46 |
+
height = (height + self.height_division_factor - 1) // self.height_division_factor * self.height_division_factor
|
| 47 |
+
print(f"height % {self.height_division_factor} != 0. We round it up to {height}.")
|
| 48 |
+
if width % self.width_division_factor != 0:
|
| 49 |
+
width = (width + self.width_division_factor - 1) // self.width_division_factor * self.width_division_factor
|
| 50 |
+
print(f"width % {self.width_division_factor} != 0. We round it up to {width}.")
|
| 51 |
+
if num_frames is None:
|
| 52 |
+
return height, width
|
| 53 |
+
else:
|
| 54 |
+
if num_frames % self.time_division_factor != self.time_division_remainder:
|
| 55 |
+
num_frames = (num_frames + self.time_division_factor - 1) // self.time_division_factor * self.time_division_factor + self.time_division_remainder
|
| 56 |
+
print(f"num_frames % {self.time_division_factor} != {self.time_division_remainder}. We round it up to {num_frames}.")
|
| 57 |
+
return height, width, num_frames
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def preprocess_image(self, image, torch_dtype=None, device=None, pattern="B C H W", min_value=-1, max_value=1):
|
| 61 |
+
# Transform a PIL.Image to torch.Tensor
|
| 62 |
+
image = torch.Tensor(np.array(image, dtype=np.float32))
|
| 63 |
+
image = image.to(dtype=torch_dtype or self.torch_dtype, device=device or self.device)
|
| 64 |
+
image = image * ((max_value - min_value) / 255) + min_value
|
| 65 |
+
image = repeat(image, f"H W C -> {pattern}", **({"B": 1} if "B" in pattern else {}))
|
| 66 |
+
return image
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def preprocess_video(self, video, torch_dtype=None, device=None, pattern="B C T H W", min_value=-1, max_value=1):
|
| 70 |
+
# Transform a list of PIL.Image to torch.Tensor
|
| 71 |
+
video = [self.preprocess_image(image, torch_dtype=torch_dtype, device=device, min_value=min_value, max_value=max_value) for image in video]
|
| 72 |
+
video = torch.stack(video, dim=pattern.index("T") // 2)
|
| 73 |
+
return video
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def vae_output_to_image(self, vae_output, pattern="B C H W", min_value=-1, max_value=1):
|
| 77 |
+
# Transform a torch.Tensor to PIL.Image
|
| 78 |
+
if pattern != "H W C":
|
| 79 |
+
vae_output = reduce(vae_output, f"{pattern} -> H W C", reduction="mean")
|
| 80 |
+
image = ((vae_output - min_value) * (255 / (max_value - min_value))).clip(0, 255)
|
| 81 |
+
image = image.to(device="cpu", dtype=torch.uint8)
|
| 82 |
+
image = Image.fromarray(image.numpy())
|
| 83 |
+
return image
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def vae_output_to_video(self, vae_output, pattern="B C T H W", min_value=-1, max_value=1):
|
| 87 |
+
# Transform a torch.Tensor to list of PIL.Image
|
| 88 |
+
if pattern != "T H W C":
|
| 89 |
+
vae_output = reduce(vae_output, f"{pattern} -> T H W C", reduction="mean")
|
| 90 |
+
video = [self.vae_output_to_image(image, pattern="H W C", min_value=min_value, max_value=max_value) for image in vae_output]
|
| 91 |
+
return video
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def load_models_to_device(self, model_names=[]):
|
| 95 |
+
if self.vram_management_enabled:
|
| 96 |
+
# offload models
|
| 97 |
+
for name, model in self.named_children():
|
| 98 |
+
if name not in model_names:
|
| 99 |
+
if hasattr(model, "vram_management_enabled") and model.vram_management_enabled:
|
| 100 |
+
for module in model.modules():
|
| 101 |
+
if hasattr(module, "offload"):
|
| 102 |
+
module.offload()
|
| 103 |
+
else:
|
| 104 |
+
model.cpu()
|
| 105 |
+
torch.cuda.empty_cache()
|
| 106 |
+
# onload models
|
| 107 |
+
for name, model in self.named_children():
|
| 108 |
+
if name in model_names:
|
| 109 |
+
if hasattr(model, "vram_management_enabled") and model.vram_management_enabled:
|
| 110 |
+
for module in model.modules():
|
| 111 |
+
if hasattr(module, "onload"):
|
| 112 |
+
module.onload()
|
| 113 |
+
else:
|
| 114 |
+
model.to(self.device)
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
def generate_noise(self, shape, seed=None, rand_device="cpu", rand_torch_dtype=torch.float32, device=None, torch_dtype=None):
|
| 118 |
+
# Initialize Gaussian noise
|
| 119 |
+
generator = None if seed is None else torch.Generator(rand_device).manual_seed(seed)
|
| 120 |
+
noise = torch.randn(shape, generator=generator, device=rand_device, dtype=rand_torch_dtype)
|
| 121 |
+
noise = noise.to(dtype=torch_dtype or self.torch_dtype, device=device or self.device)
|
| 122 |
+
return noise
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def enable_cpu_offload(self):
|
| 126 |
+
warnings.warn("`enable_cpu_offload` will be deprecated. Please use `enable_vram_management`.")
|
| 127 |
+
self.vram_management_enabled = True
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
def get_vram(self):
|
| 131 |
+
return torch.cuda.mem_get_info(self.device)[1] / (1024 ** 3)
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def freeze_except(self, model_names):
|
| 135 |
+
for name, model in self.named_children():
|
| 136 |
+
if name in model_names:
|
| 137 |
+
model.train()
|
| 138 |
+
model.requires_grad_(True)
|
| 139 |
+
else:
|
| 140 |
+
model.eval()
|
| 141 |
+
model.requires_grad_(False)
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
@dataclass
|
| 145 |
+
class ModelConfig:
|
| 146 |
+
path: Union[str, list[str]] = None
|
| 147 |
+
model_id: str = None
|
| 148 |
+
origin_file_pattern: Union[str, list[str]] = None
|
| 149 |
+
download_resource: str = "ModelScope"
|
| 150 |
+
offload_device: Optional[Union[str, torch.device]] = None
|
| 151 |
+
offload_dtype: Optional[torch.dtype] = None
|
| 152 |
+
local_model_path: str = None
|
| 153 |
+
skip_download: bool = False
|
| 154 |
+
|
| 155 |
+
def download_if_necessary(self, use_usp=False):
|
| 156 |
+
if self.path is None:
|
| 157 |
+
# Check model_id and origin_file_pattern
|
| 158 |
+
if self.model_id is None:
|
| 159 |
+
raise ValueError(f"""No valid model files. Please use `ModelConfig(path="xxx")` or `ModelConfig(model_id="xxx/yyy", origin_file_pattern="zzz")`.""")
|
| 160 |
+
|
| 161 |
+
# Skip if not in rank 0
|
| 162 |
+
if use_usp:
|
| 163 |
+
import torch.distributed as dist
|
| 164 |
+
skip_download = self.skip_download or dist.get_rank() != 0
|
| 165 |
+
else:
|
| 166 |
+
skip_download = self.skip_download
|
| 167 |
+
|
| 168 |
+
# Check whether the origin path is a folder
|
| 169 |
+
if self.origin_file_pattern is None or self.origin_file_pattern == "":
|
| 170 |
+
self.origin_file_pattern = ""
|
| 171 |
+
allow_file_pattern = None
|
| 172 |
+
is_folder = True
|
| 173 |
+
elif isinstance(self.origin_file_pattern, str) and self.origin_file_pattern.endswith("/"):
|
| 174 |
+
allow_file_pattern = self.origin_file_pattern + "*"
|
| 175 |
+
is_folder = True
|
| 176 |
+
else:
|
| 177 |
+
allow_file_pattern = self.origin_file_pattern
|
| 178 |
+
is_folder = False
|
| 179 |
+
|
| 180 |
+
# Download
|
| 181 |
+
if self.local_model_path is None:
|
| 182 |
+
self.local_model_path = "./models"
|
| 183 |
+
if not skip_download:
|
| 184 |
+
downloaded_files = glob.glob(self.origin_file_pattern, root_dir=os.path.join(self.local_model_path, self.model_id))
|
| 185 |
+
snapshot_download(
|
| 186 |
+
self.model_id,
|
| 187 |
+
local_dir=os.path.join(self.local_model_path, self.model_id),
|
| 188 |
+
allow_file_pattern=allow_file_pattern,
|
| 189 |
+
ignore_file_pattern=downloaded_files,
|
| 190 |
+
local_files_only=False
|
| 191 |
+
)
|
| 192 |
+
|
| 193 |
+
# Let rank 1, 2, ... wait for rank 0
|
| 194 |
+
if use_usp:
|
| 195 |
+
import torch.distributed as dist
|
| 196 |
+
dist.barrier(device_ids=[dist.get_rank()])
|
| 197 |
+
|
| 198 |
+
# Return downloaded files
|
| 199 |
+
if is_folder:
|
| 200 |
+
self.path = os.path.join(self.local_model_path, self.model_id, self.origin_file_pattern)
|
| 201 |
+
else:
|
| 202 |
+
self.path = glob.glob(os.path.join(self.local_model_path, self.model_id, self.origin_file_pattern))
|
| 203 |
+
if isinstance(self.path, list) and len(self.path) == 1:
|
| 204 |
+
self.path = self.path[0]
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
class PipelineUnit:
|
| 209 |
+
def __init__(
|
| 210 |
+
self,
|
| 211 |
+
seperate_cfg: bool = False,
|
| 212 |
+
take_over: bool = False,
|
| 213 |
+
input_params: tuple[str] = None,
|
| 214 |
+
input_params_posi: dict[str, str] = None,
|
| 215 |
+
input_params_nega: dict[str, str] = None,
|
| 216 |
+
onload_model_names: tuple[str] = None
|
| 217 |
+
):
|
| 218 |
+
self.seperate_cfg = seperate_cfg
|
| 219 |
+
self.take_over = take_over
|
| 220 |
+
self.input_params = input_params
|
| 221 |
+
self.input_params_posi = input_params_posi
|
| 222 |
+
self.input_params_nega = input_params_nega
|
| 223 |
+
self.onload_model_names = onload_model_names
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
def process(self, pipe: BasePipeline, inputs: dict, positive=True, **kwargs) -> dict:
|
| 227 |
+
raise NotImplementedError("`process` is not implemented.")
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
class PipelineUnitRunner:
|
| 232 |
+
def __init__(self):
|
| 233 |
+
pass
|
| 234 |
+
|
| 235 |
+
def __call__(self, unit: PipelineUnit, pipe: BasePipeline, inputs_shared: dict, inputs_posi: dict, inputs_nega: dict) -> tuple[dict, dict]:
|
| 236 |
+
if unit.take_over:
|
| 237 |
+
# Let the pipeline unit take over this function.
|
| 238 |
+
inputs_shared, inputs_posi, inputs_nega = unit.process(pipe, inputs_shared=inputs_shared, inputs_posi=inputs_posi, inputs_nega=inputs_nega)
|
| 239 |
+
elif unit.seperate_cfg:
|
| 240 |
+
# Positive side
|
| 241 |
+
processor_inputs = {name: inputs_posi.get(name_) for name, name_ in unit.input_params_posi.items()}
|
| 242 |
+
if unit.input_params is not None:
|
| 243 |
+
for name in unit.input_params:
|
| 244 |
+
processor_inputs[name] = inputs_shared.get(name)
|
| 245 |
+
processor_outputs = unit.process(pipe, **processor_inputs)
|
| 246 |
+
inputs_posi.update(processor_outputs)
|
| 247 |
+
# Negative side
|
| 248 |
+
if inputs_shared["cfg_scale"] != 1:
|
| 249 |
+
processor_inputs = {name: inputs_nega.get(name_) for name, name_ in unit.input_params_nega.items()}
|
| 250 |
+
if unit.input_params is not None:
|
| 251 |
+
for name in unit.input_params:
|
| 252 |
+
processor_inputs[name] = inputs_shared.get(name)
|
| 253 |
+
processor_outputs = unit.process(pipe, **processor_inputs)
|
| 254 |
+
inputs_nega.update(processor_outputs)
|
| 255 |
+
else:
|
| 256 |
+
inputs_nega.update(processor_outputs)
|
| 257 |
+
else:
|
| 258 |
+
processor_inputs = {name: inputs_shared.get(name) for name in unit.input_params}
|
| 259 |
+
processor_outputs = unit.process(pipe, **processor_inputs)
|
| 260 |
+
inputs_shared.update(processor_outputs)
|
| 261 |
+
return inputs_shared, inputs_posi, inputs_nega
|
diffsynth/vram_management/__init__.py
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .layers import *
|
| 2 |
+
from .gradient_checkpointing import *
|
diffsynth/vram_management/gradient_checkpointing.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def create_custom_forward(module):
|
| 5 |
+
def custom_forward(*inputs, **kwargs):
|
| 6 |
+
return module(*inputs, **kwargs)
|
| 7 |
+
return custom_forward
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def gradient_checkpoint_forward(
|
| 11 |
+
model,
|
| 12 |
+
use_gradient_checkpointing,
|
| 13 |
+
use_gradient_checkpointing_offload,
|
| 14 |
+
*args,
|
| 15 |
+
**kwargs,
|
| 16 |
+
):
|
| 17 |
+
if use_gradient_checkpointing_offload:
|
| 18 |
+
with torch.autograd.graph.save_on_cpu():
|
| 19 |
+
model_output = torch.utils.checkpoint.checkpoint(
|
| 20 |
+
create_custom_forward(model),
|
| 21 |
+
*args,
|
| 22 |
+
**kwargs,
|
| 23 |
+
use_reentrant=False,
|
| 24 |
+
)
|
| 25 |
+
elif use_gradient_checkpointing:
|
| 26 |
+
model_output = torch.utils.checkpoint.checkpoint(
|
| 27 |
+
create_custom_forward(model),
|
| 28 |
+
*args,
|
| 29 |
+
**kwargs,
|
| 30 |
+
use_reentrant=False,
|
| 31 |
+
)
|
| 32 |
+
else:
|
| 33 |
+
model_output = model(*args, **kwargs)
|
| 34 |
+
return model_output
|
diffsynth/vram_management/layers.py
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch, copy
|
| 2 |
+
from ..models.utils import init_weights_on_device
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def cast_to(weight, dtype, device):
|
| 6 |
+
r = torch.empty_like(weight, dtype=dtype, device=device)
|
| 7 |
+
r.copy_(weight)
|
| 8 |
+
return r
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class AutoTorchModule(torch.nn.Module):
|
| 12 |
+
def __init__(self):
|
| 13 |
+
super().__init__()
|
| 14 |
+
|
| 15 |
+
def check_free_vram(self):
|
| 16 |
+
gpu_mem_state = torch.cuda.mem_get_info(self.computation_device)
|
| 17 |
+
used_memory = (gpu_mem_state[1] - gpu_mem_state[0]) / (1024 ** 3)
|
| 18 |
+
return used_memory < self.vram_limit
|
| 19 |
+
|
| 20 |
+
def offload(self):
|
| 21 |
+
if self.state != 0:
|
| 22 |
+
self.to(dtype=self.offload_dtype, device=self.offload_device)
|
| 23 |
+
self.state = 0
|
| 24 |
+
|
| 25 |
+
def onload(self):
|
| 26 |
+
if self.state != 1:
|
| 27 |
+
self.to(dtype=self.onload_dtype, device=self.onload_device)
|
| 28 |
+
self.state = 1
|
| 29 |
+
|
| 30 |
+
def keep(self):
|
| 31 |
+
if self.state != 2:
|
| 32 |
+
self.to(dtype=self.computation_dtype, device=self.computation_device)
|
| 33 |
+
self.state = 2
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
class AutoWrappedModule(AutoTorchModule):
|
| 37 |
+
def __init__(self, module: torch.nn.Module, offload_dtype, offload_device, onload_dtype, onload_device, computation_dtype, computation_device, vram_limit, **kwargs):
|
| 38 |
+
super().__init__()
|
| 39 |
+
self.module = module.to(dtype=offload_dtype, device=offload_device)
|
| 40 |
+
self.offload_dtype = offload_dtype
|
| 41 |
+
self.offload_device = offload_device
|
| 42 |
+
self.onload_dtype = onload_dtype
|
| 43 |
+
self.onload_device = onload_device
|
| 44 |
+
self.computation_dtype = computation_dtype
|
| 45 |
+
self.computation_device = computation_device
|
| 46 |
+
self.vram_limit = vram_limit
|
| 47 |
+
self.state = 0
|
| 48 |
+
|
| 49 |
+
def forward(self, *args, **kwargs):
|
| 50 |
+
if self.state == 2:
|
| 51 |
+
module = self.module
|
| 52 |
+
else:
|
| 53 |
+
if self.onload_dtype == self.computation_dtype and self.onload_device == self.computation_device:
|
| 54 |
+
module = self.module
|
| 55 |
+
elif self.vram_limit is not None and self.check_free_vram():
|
| 56 |
+
self.keep()
|
| 57 |
+
module = self.module
|
| 58 |
+
else:
|
| 59 |
+
module = copy.deepcopy(self.module).to(dtype=self.computation_dtype, device=self.computation_device)
|
| 60 |
+
return module(*args, **kwargs)
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
class WanAutoCastLayerNorm(torch.nn.LayerNorm, AutoTorchModule):
|
| 64 |
+
def __init__(self, module: torch.nn.LayerNorm, offload_dtype, offload_device, onload_dtype, onload_device, computation_dtype, computation_device, vram_limit, **kwargs):
|
| 65 |
+
with init_weights_on_device(device=torch.device("meta")):
|
| 66 |
+
super().__init__(module.normalized_shape, eps=module.eps, elementwise_affine=module.elementwise_affine, bias=module.bias is not None, dtype=offload_dtype, device=offload_device)
|
| 67 |
+
self.weight = module.weight
|
| 68 |
+
self.bias = module.bias
|
| 69 |
+
self.offload_dtype = offload_dtype
|
| 70 |
+
self.offload_device = offload_device
|
| 71 |
+
self.onload_dtype = onload_dtype
|
| 72 |
+
self.onload_device = onload_device
|
| 73 |
+
self.computation_dtype = computation_dtype
|
| 74 |
+
self.computation_device = computation_device
|
| 75 |
+
self.vram_limit = vram_limit
|
| 76 |
+
self.state = 0
|
| 77 |
+
|
| 78 |
+
def forward(self, x, *args, **kwargs):
|
| 79 |
+
if self.state == 2:
|
| 80 |
+
weight, bias = self.weight, self.bias
|
| 81 |
+
else:
|
| 82 |
+
if self.onload_dtype == self.computation_dtype and self.onload_device == self.computation_device:
|
| 83 |
+
weight, bias = self.weight, self.bias
|
| 84 |
+
elif self.vram_limit is not None and self.check_free_vram():
|
| 85 |
+
self.keep()
|
| 86 |
+
weight, bias = self.weight, self.bias
|
| 87 |
+
else:
|
| 88 |
+
weight = None if self.weight is None else cast_to(self.weight, self.computation_dtype, self.computation_device)
|
| 89 |
+
bias = None if self.bias is None else cast_to(self.bias, self.computation_dtype, self.computation_device)
|
| 90 |
+
with torch.amp.autocast(device_type=x.device.type):
|
| 91 |
+
x = torch.nn.functional.layer_norm(x.float(), self.normalized_shape, weight, bias, self.eps).type_as(x)
|
| 92 |
+
return x
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
class AutoWrappedLinear(torch.nn.Linear, AutoTorchModule):
|
| 96 |
+
def __init__(self, module: torch.nn.Linear, offload_dtype, offload_device, onload_dtype, onload_device, computation_dtype, computation_device, vram_limit, name="", **kwargs):
|
| 97 |
+
with init_weights_on_device(device=torch.device("meta")):
|
| 98 |
+
super().__init__(in_features=module.in_features, out_features=module.out_features, bias=module.bias is not None, dtype=offload_dtype, device=offload_device)
|
| 99 |
+
self.weight = module.weight
|
| 100 |
+
self.bias = module.bias
|
| 101 |
+
self.offload_dtype = offload_dtype
|
| 102 |
+
self.offload_device = offload_device
|
| 103 |
+
self.onload_dtype = onload_dtype
|
| 104 |
+
self.onload_device = onload_device
|
| 105 |
+
self.computation_dtype = computation_dtype
|
| 106 |
+
self.computation_device = computation_device
|
| 107 |
+
self.vram_limit = vram_limit
|
| 108 |
+
self.state = 0
|
| 109 |
+
self.name = name
|
| 110 |
+
self.lora_A_weights = []
|
| 111 |
+
self.lora_B_weights = []
|
| 112 |
+
self.lora_merger = None
|
| 113 |
+
|
| 114 |
+
def forward(self, x, *args, **kwargs):
|
| 115 |
+
if self.state == 2:
|
| 116 |
+
weight, bias = self.weight, self.bias
|
| 117 |
+
else:
|
| 118 |
+
if self.onload_dtype == self.computation_dtype and self.onload_device == self.computation_device:
|
| 119 |
+
weight, bias = self.weight, self.bias
|
| 120 |
+
elif self.vram_limit is not None and self.check_free_vram():
|
| 121 |
+
self.keep()
|
| 122 |
+
weight, bias = self.weight, self.bias
|
| 123 |
+
else:
|
| 124 |
+
weight = cast_to(self.weight, self.computation_dtype, self.computation_device)
|
| 125 |
+
bias = None if self.bias is None else cast_to(self.bias, self.computation_dtype, self.computation_device)
|
| 126 |
+
out = torch.nn.functional.linear(x, weight, bias)
|
| 127 |
+
|
| 128 |
+
if len(self.lora_A_weights) == 0:
|
| 129 |
+
# No LoRA
|
| 130 |
+
return out
|
| 131 |
+
elif self.lora_merger is None:
|
| 132 |
+
# Native LoRA inference
|
| 133 |
+
for lora_A, lora_B in zip(self.lora_A_weights, self.lora_B_weights):
|
| 134 |
+
out = out + x @ lora_A.T @ lora_B.T
|
| 135 |
+
else:
|
| 136 |
+
# LoRA fusion
|
| 137 |
+
lora_output = []
|
| 138 |
+
for lora_A, lora_B in zip(self.lora_A_weights, self.lora_B_weights):
|
| 139 |
+
lora_output.append(x @ lora_A.T @ lora_B.T)
|
| 140 |
+
lora_output = torch.stack(lora_output)
|
| 141 |
+
out = self.lora_merger(out, lora_output)
|
| 142 |
+
return out
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
def enable_vram_management_recursively(model: torch.nn.Module, module_map: dict, module_config: dict, max_num_param=None, overflow_module_config: dict = None, total_num_param=0, vram_limit=None, name_prefix=""):
|
| 146 |
+
for name, module in model.named_children():
|
| 147 |
+
layer_name = name if name_prefix == "" else name_prefix + "." + name
|
| 148 |
+
for source_module, target_module in module_map.items():
|
| 149 |
+
if isinstance(module, source_module):
|
| 150 |
+
num_param = sum(p.numel() for p in module.parameters())
|
| 151 |
+
if max_num_param is not None and total_num_param + num_param > max_num_param:
|
| 152 |
+
module_config_ = overflow_module_config
|
| 153 |
+
else:
|
| 154 |
+
module_config_ = module_config
|
| 155 |
+
module_ = target_module(module, **module_config_, vram_limit=vram_limit, name=layer_name)
|
| 156 |
+
setattr(model, name, module_)
|
| 157 |
+
total_num_param += num_param
|
| 158 |
+
break
|
| 159 |
+
else:
|
| 160 |
+
total_num_param = enable_vram_management_recursively(module, module_map, module_config, max_num_param, overflow_module_config, total_num_param, vram_limit=vram_limit, name_prefix=layer_name)
|
| 161 |
+
return total_num_param
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
def enable_vram_management(model: torch.nn.Module, module_map: dict, module_config: dict, max_num_param=None, overflow_module_config: dict = None, vram_limit=None):
|
| 165 |
+
enable_vram_management_recursively(model, module_map, module_config, max_num_param, overflow_module_config, total_num_param=0, vram_limit=vram_limit)
|
| 166 |
+
model.vram_management_enabled = True
|
| 167 |
+
|
third_party/Optional.md
ADDED
|
File without changes
|
tools/full_inference_modules_gradio.sh
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
which python
|
| 3 |
+
export CUDA_VISIBLE_DEVICES=${CUDA_VISIBLE_DEVICES:-0}
|
| 4 |
+
|
| 5 |
+
export CUDA_HOME=/usr/local/cuda-12.4
|
| 6 |
+
export PATH=$CUDA_HOME/bin:$PATH
|
| 7 |
+
export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH
|
| 8 |
+
|
| 9 |
+
# export HF_HUB_DOWNLOAD_TIMEOUT=30
|
| 10 |
+
# export HF_HOME=${HOME}/.cache/huggingface/
|
| 11 |
+
|
| 12 |
+
export CONDA_PATH=${HOME}/miniconda3 # ! Replace with your CONDA path
|
| 13 |
+
export CONDA_PREFIX_1=${CONDA_PATH}/envs/diffsynth # ! Replace with your diffsynth environment path
|
| 14 |
+
export CONDA_PREFIX_2=${CONDA_PATH}/envs/cosmos-predict1 # ! Replace with your cosmos-predict1 environment path
|
| 15 |
+
export DR_REPO_PATH=${REPO_PATH}/third_party/cosmos-transfer1-diffusion-renderer
|
| 16 |
+
|
| 17 |
+
# if input image, set FRAME=1
|
| 18 |
+
if [ "$TEST_TYPE" -eq 1 ]; then
|
| 19 |
+
export FRAME=1
|
| 20 |
+
fi
|
| 21 |
+
|
| 22 |
+
# -------------------------------------- module 1 -----------------------------------------
|
| 23 |
+
if [ "$INFER_1" -eq 1 ]; then
|
| 24 |
+
source ${CONDA_PATH}/bin/activate ${CONDA_PREFIX_2}
|
| 25 |
+
cd ${DR_REPO_PATH}
|
| 26 |
+
mkdir -p ${REPO_PATH}/datasets/gradio_data/results/$TEST_ID
|
| 27 |
+
rm -rf ${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/frames
|
| 28 |
+
if [ "$TEST_TYPE" -eq 0 ]; then
|
| 29 |
+
# If the input is a video, split it into multiple frames and save them in the output_folder/frames/$TEST_ID folder
|
| 30 |
+
CUDA_HOME=$CONDA_PREFIX_2 PYTHONPATH=$(pwd) python scripts/dataproc_extract_frames_from_video.py \
|
| 31 |
+
--input_folder ${REPO_PATH}/datasets/gradio_data/upload_data/$TEST_ID \
|
| 32 |
+
--output_folder ${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/frames/ --frame_rate=$FRAME_RATE --max_frames=$FRAME
|
| 33 |
+
elif [ "$TEST_TYPE" -eq 1 ]; then
|
| 34 |
+
# If the input is an image, directly copy it to the output_folder/frames/$TEST_ID folder
|
| 35 |
+
mkdir -p ${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/frames/$TEST_ID
|
| 36 |
+
cp ${REPO_PATH}/datasets/gradio_data/upload_data/$TEST_ID/$TEST_ID.jpg ${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/frames/$TEST_ID/frame_00000.jpg
|
| 37 |
+
fi
|
| 38 |
+
|
| 39 |
+
if [ "$FRAME" -eq 1 ]; then
|
| 40 |
+
export COSMOS_FRAME=$FRAME
|
| 41 |
+
else
|
| 42 |
+
export COSMOS_FRAME=57
|
| 43 |
+
fi
|
| 44 |
+
rm -rf ${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/frames_delighting
|
| 45 |
+
CUDA_HOME=$CONDA_PREFIX_2 PYTHONPATH=$(pwd) python cosmos_predict1/diffusion/inference/inference_inverse_renderer.py \
|
| 46 |
+
--checkpoint_dir checkpoints --diffusion_transformer_dir Diffusion_Renderer_Inverse_Cosmos_7B \
|
| 47 |
+
--dataset_path="${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/frames/" --num_video_frames $COSMOS_FRAME --group_mode folder \
|
| 48 |
+
--video_save_folder="${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/frames_delighting/" --chunk_mode 'first' --overlap_n_frames 0 --save_video 'False'
|
| 49 |
+
|
| 50 |
+
cd ${REPO_PATH}
|
| 51 |
+
CUDA_HOME=$CONDA_PREFIX_2 PYTHONPATH=$(pwd) python tools/reorg_gbuffer_from_dr_delighting.py \
|
| 52 |
+
--frame_dir "${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/frames/" \
|
| 53 |
+
--gbuffer_dir "${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/frames_delighting/gbuffer_frames/" \
|
| 54 |
+
--tgt_dir "${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/rego/"
|
| 55 |
+
fi
|
| 56 |
+
|
| 57 |
+
# -------------------------------------- module 2 -----------------------------------------
|
| 58 |
+
if [ "$INFER_2" -eq 1 ]; then
|
| 59 |
+
source ${CONDA_PATH}/bin/activate ${CONDA_PREFIX_2}
|
| 60 |
+
cd ${REPO_PATH}
|
| 61 |
+
mkdir -p ${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/envs
|
| 62 |
+
if [ "$USE_OFFICE_ENV" -eq 0 ]; then
|
| 63 |
+
CUDA_HOME=$CONDA_PREFIX_2 PYTHONPATH=$(pwd) python tools/process_env_maps.py \
|
| 64 |
+
--env_dir ${REPO_PATH}/datasets/gradio_data/upload_data/$TEST_ID/$TEST_ENV \
|
| 65 |
+
--save_path ${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/envs/$TEST_ENV \
|
| 66 |
+
--env_strength $ENV_STRENGTH
|
| 67 |
+
else
|
| 68 |
+
CUDA_HOME=$CONDA_PREFIX_2 PYTHONPATH=$(pwd) python tools/process_env_maps.py \
|
| 69 |
+
--env_dir ${REPO_PATH}/datasets/gradio_data/assets/envs_demo/$TEST_ENV \
|
| 70 |
+
--save_path ${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/envs/$TEST_ENV \
|
| 71 |
+
--env_strength $ENV_STRENGTH
|
| 72 |
+
fi
|
| 73 |
+
fi
|
| 74 |
+
|
| 75 |
+
# -------------------------------------- module 3 -----------------------------------------
|
| 76 |
+
if [ "$INFER_3" -eq 1 ]; then
|
| 77 |
+
source ${CONDA_PATH}/bin/activate ${CONDA_PREFIX_1}
|
| 78 |
+
cd ${REPO_PATH}
|
| 79 |
+
|
| 80 |
+
# LIGHT_TYPE non-zero forces FRAME ≠ 1
|
| 81 |
+
if [ "$LIGHT_TYPE" -ne 0 ] && [ "$FRAME" -eq 1 ]; then
|
| 82 |
+
export INFER_FRAME=25
|
| 83 |
+
else
|
| 84 |
+
export INFER_FRAME=$FRAME
|
| 85 |
+
fi
|
| 86 |
+
|
| 87 |
+
if [ "$INFER_FRAME" -eq 1 ]; then
|
| 88 |
+
SAVE_EXT='png'
|
| 89 |
+
else
|
| 90 |
+
SAVE_EXT='mp4'
|
| 91 |
+
fi
|
| 92 |
+
|
| 93 |
+
if [ "$INFER_FRAME" -eq 1 ]; then
|
| 94 |
+
export HEIGHT=1024
|
| 95 |
+
export WIDTH=1472
|
| 96 |
+
export CKT="${REPO_PATH}/checkpoints/model_frame1_1024_1472.ckpt"
|
| 97 |
+
elif [ "$INFER_FRAME" -eq 25 ]; then
|
| 98 |
+
export HEIGHT=480
|
| 99 |
+
export WIDTH=832
|
| 100 |
+
export CKT="${REPO_PATH}/checkpoints/model_frame25_480_832.ckpt"
|
| 101 |
+
else
|
| 102 |
+
export HEIGHT=480
|
| 103 |
+
export WIDTH=832
|
| 104 |
+
export CKT="${REPO_PATH}/checkpoints/model_frame57_480_832.ckpt"
|
| 105 |
+
fi
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
if [ "$LIGHT_TYPE" -eq 0 ]; then
|
| 109 |
+
CUDA_HOME=$CONDA_PREFIX_1 PYTHONPATH=$(pwd) python relit_inference.py \
|
| 110 |
+
--dataset_path "${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/rego" \
|
| 111 |
+
--ckpt_path=$CKT \
|
| 112 |
+
--output_dir "${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/relighting.$TEST_ENV" \
|
| 113 |
+
--output_path "${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/$TEST_ID.$TEST_ENV.$SAVE_EXT" \
|
| 114 |
+
--cfg_scale 1.0 \
|
| 115 |
+
--height $HEIGHT \
|
| 116 |
+
--width $WIDTH \
|
| 117 |
+
--num_frames $INFER_FRAME \
|
| 118 |
+
--padding_resolution \
|
| 119 |
+
--use_ref_image \
|
| 120 |
+
--env_map_path ${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/envs/$TEST_ENV \
|
| 121 |
+
--frame_interval 1 \
|
| 122 |
+
--num_inference_steps $NUM_INFER_STEPS \
|
| 123 |
+
--wo_ref_weight $WORW \
|
| 124 |
+
--quality 10
|
| 125 |
+
elif [ "$LIGHT_TYPE" -eq 1 ]; then
|
| 126 |
+
CUDA_HOME=$CONDA_PREFIX_1 PYTHONPATH=$(pwd) python relit_inference.py \
|
| 127 |
+
--dataset_path "${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/rego" \
|
| 128 |
+
--ckpt_path=$CKT \
|
| 129 |
+
--output_dir "${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/relighting.$TEST_ENV" \
|
| 130 |
+
--output_path "${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/$TEST_ID.$TEST_ENV.$SAVE_EXT" \
|
| 131 |
+
--cfg_scale 1.0 \
|
| 132 |
+
--height $HEIGHT \
|
| 133 |
+
--width $WIDTH \
|
| 134 |
+
--num_frames $INFER_FRAME \
|
| 135 |
+
--padding_resolution \
|
| 136 |
+
--use_ref_image \
|
| 137 |
+
--env_map_path ${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/envs/$TEST_ENV \
|
| 138 |
+
--frame_interval 1 \
|
| 139 |
+
--num_inference_steps $NUM_INFER_STEPS \
|
| 140 |
+
--wo_ref_weight $WORW \
|
| 141 |
+
--use_rotate_light \
|
| 142 |
+
--quality 10
|
| 143 |
+
elif [ "$LIGHT_TYPE" -eq 2 ]; then
|
| 144 |
+
CUDA_HOME=$CONDA_PREFIX_1 PYTHONPATH=$(pwd) python relit_inference.py \
|
| 145 |
+
--dataset_path "${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/rego" \
|
| 146 |
+
--ckpt_path=$CKT \
|
| 147 |
+
--output_dir "${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/relighting.$TEST_ENV" \
|
| 148 |
+
--output_path "${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/$TEST_ID.$TEST_ENV.$SAVE_EXT" \
|
| 149 |
+
--cfg_scale 1.0 \
|
| 150 |
+
--height $HEIGHT \
|
| 151 |
+
--width $WIDTH \
|
| 152 |
+
--num_frames $INFER_FRAME \
|
| 153 |
+
--padding_resolution \
|
| 154 |
+
--use_ref_image \
|
| 155 |
+
--env_map_path ${REPO_PATH}/datasets/gradio_data/results/$TEST_ID/envs/$TEST_ENV \
|
| 156 |
+
--frame_interval 1 \
|
| 157 |
+
--num_inference_steps $NUM_INFER_STEPS \
|
| 158 |
+
--wo_ref_weight $WORW \
|
| 159 |
+
--use_fixed_frame_and_w_rotate_light \
|
| 160 |
+
--quality 10
|
| 161 |
+
fi
|
| 162 |
+
fi
|
tools/process_env_maps.py
ADDED
|
@@ -0,0 +1,599 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import glob
|
| 3 |
+
import json
|
| 4 |
+
import cv2
|
| 5 |
+
import numpy as np
|
| 6 |
+
import argparse
|
| 7 |
+
import torch
|
| 8 |
+
import imageio.v2 as imageio
|
| 9 |
+
import imageio.v3 as imageio_v3
|
| 10 |
+
|
| 11 |
+
import nvdiffrast.torch as dr
|
| 12 |
+
|
| 13 |
+
# Enable OpenEXR support in OpenCV
|
| 14 |
+
os.environ['OPENCV_IO_ENABLE_OPENEXR'] = '1'
|
| 15 |
+
|
| 16 |
+
def swap_yz_in_extrinsic_matrix(matrix):
|
| 17 |
+
assert matrix.shape == (4, 4), "Input must be a 4x4 matrix"
|
| 18 |
+
|
| 19 |
+
new_matrix = matrix.copy()
|
| 20 |
+
new_matrix[1, :], new_matrix[2, :] = new_matrix[2, :].copy(), new_matrix[1, :].copy()
|
| 21 |
+
new_matrix[:, 1], new_matrix[:, 2] = new_matrix[:, 2].copy(), new_matrix[:, 1].copy()
|
| 22 |
+
|
| 23 |
+
return new_matrix
|
| 24 |
+
|
| 25 |
+
def swap_yz_output_in_extrinsic_matrix(matrix):
|
| 26 |
+
assert matrix.shape == (4, 4), "Input must be a 4x4 matrix"
|
| 27 |
+
|
| 28 |
+
new_matrix = matrix.copy()
|
| 29 |
+
new_matrix[1, :], new_matrix[2, :] = new_matrix[2, :].copy(), new_matrix[1, :].copy()
|
| 30 |
+
|
| 31 |
+
return new_matrix
|
| 32 |
+
|
| 33 |
+
def euler_to_rotation_matrix(euler_angles, inverse_y=True, y_bias=0):
|
| 34 |
+
alpha, gamma, beta = euler_angles
|
| 35 |
+
beta += y_bias
|
| 36 |
+
if inverse_y:
|
| 37 |
+
beta = -beta
|
| 38 |
+
|
| 39 |
+
R_x = np.array([[1, 0, 0],
|
| 40 |
+
[0, np.cos(alpha), -np.sin(alpha)],
|
| 41 |
+
[0, np.sin(alpha), np.cos(alpha)]])
|
| 42 |
+
|
| 43 |
+
R_y = np.array([[np.cos(beta), 0, np.sin(beta)],
|
| 44 |
+
[0, 1, 0],
|
| 45 |
+
[-np.sin(beta), 0, np.cos(beta)]])
|
| 46 |
+
|
| 47 |
+
R_z = np.array([[np.cos(gamma), -np.sin(gamma), 0],
|
| 48 |
+
[np.sin(gamma), np.cos(gamma), 0],
|
| 49 |
+
[0, 0, 1]])
|
| 50 |
+
|
| 51 |
+
R = np.dot(R_z, np.dot(R_y, R_x))
|
| 52 |
+
return R
|
| 53 |
+
|
| 54 |
+
def remove_yaw_rotation(c2w_list):
|
| 55 |
+
c2w_0 = c2w_list[0]
|
| 56 |
+
rotation_0 = c2w_0[:3, :3]
|
| 57 |
+
|
| 58 |
+
yaw_0 = np.arctan2(rotation_0[2, 0], rotation_0[0, 0])
|
| 59 |
+
|
| 60 |
+
yaw_rotation_matrix = np.array([
|
| 61 |
+
[np.cos(-yaw_0), 0, np.sin(-yaw_0), 0],
|
| 62 |
+
[0, 1, 0, 0],
|
| 63 |
+
[-np.sin(-yaw_0), 0, np.cos(-yaw_0), 0],
|
| 64 |
+
[0, 0, 0, 1]
|
| 65 |
+
])
|
| 66 |
+
|
| 67 |
+
c2w_list_adjusted = [yaw_rotation_matrix @ c2w_i for c2w_i in c2w_list]
|
| 68 |
+
|
| 69 |
+
return c2w_list_adjusted
|
| 70 |
+
|
| 71 |
+
def adjust_yaw_rotation(c2w_list, yaw_0):
|
| 72 |
+
|
| 73 |
+
yaw_rotation_matrix = np.array([
|
| 74 |
+
[np.cos(-yaw_0), 0, np.sin(-yaw_0), 0],
|
| 75 |
+
[0, 1, 0, 0],
|
| 76 |
+
[-np.sin(-yaw_0), 0, np.cos(-yaw_0), 0],
|
| 77 |
+
[0, 0, 0, 1]
|
| 78 |
+
])
|
| 79 |
+
|
| 80 |
+
c2w_list_adjusted = [yaw_rotation_matrix @ c2w_i for c2w_i in c2w_list]
|
| 81 |
+
|
| 82 |
+
return c2w_list_adjusted
|
| 83 |
+
|
| 84 |
+
def reverse_yaw_rotation(c2w_list):
|
| 85 |
+
c2w_list_reversed = []
|
| 86 |
+
|
| 87 |
+
for c2w in c2w_list:
|
| 88 |
+
rotation = c2w[:3, :3]
|
| 89 |
+
|
| 90 |
+
yaw = np.arctan2(rotation[2, 0], rotation[0, 0])
|
| 91 |
+
|
| 92 |
+
reversed_yaw = 2 * yaw
|
| 93 |
+
|
| 94 |
+
reverse_yaw_rotation_matrix = np.array([
|
| 95 |
+
[np.cos(reversed_yaw), 0, np.sin(reversed_yaw), 0],
|
| 96 |
+
[0, 1, 0, 0],
|
| 97 |
+
[-np.sin(reversed_yaw), 0, np.cos(reversed_yaw), 0],
|
| 98 |
+
[0, 0, 0, 1]
|
| 99 |
+
])
|
| 100 |
+
|
| 101 |
+
c2w_reversed = reverse_yaw_rotation_matrix @ c2w
|
| 102 |
+
c2w_list_reversed.append(c2w_reversed)
|
| 103 |
+
|
| 104 |
+
return c2w_list_reversed
|
| 105 |
+
|
| 106 |
+
def prepare_camera_poses(num_frames, fixed_pose, pose_file, pose_offset, pose_reset, device, ign_camera_pose=True, swap_type=0, load_w2c=False, remove_y_rotation=False, reverse_y_rotation=False, yaw_0=0, pose_list=None, rotation_euler=None):
|
| 107 |
+
"""Prepare camera poses based on the provided arguments."""
|
| 108 |
+
if pose_list is not None:
|
| 109 |
+
c2w_list = pose_list
|
| 110 |
+
for frame_idx, transform_matrix in enumerate(c2w_list):
|
| 111 |
+
if swap_type == 0:
|
| 112 |
+
new_transform_matrix = transform_matrix
|
| 113 |
+
elif swap_type == 1:
|
| 114 |
+
new_transform_matrix = swap_yz_in_extrinsic_matrix(transform_matrix)
|
| 115 |
+
elif swap_type == 2:
|
| 116 |
+
new_transform_matrix = swap_yz_output_in_extrinsic_matrix(transform_matrix)
|
| 117 |
+
if load_w2c:
|
| 118 |
+
new_transform_matrix = np.linalg.inv(new_transform_matrix)
|
| 119 |
+
c2w_list[frame_idx] = new_transform_matrix
|
| 120 |
+
|
| 121 |
+
if pose_reset:
|
| 122 |
+
w2c_0 = np.linalg.inv(c2w_list[0])
|
| 123 |
+
c2w_list = [w2c_0 @ c2w_i for c2w_i in c2w_list]
|
| 124 |
+
|
| 125 |
+
if remove_y_rotation:
|
| 126 |
+
c2w_list = remove_yaw_rotation(c2w_list)
|
| 127 |
+
|
| 128 |
+
if reverse_y_rotation:
|
| 129 |
+
c2w_list = reverse_yaw_rotation(c2w_list)
|
| 130 |
+
|
| 131 |
+
if rotation_euler is not None:
|
| 132 |
+
for frame_idx, transform_matrix in enumerate(c2w_list):
|
| 133 |
+
rotation_matrix = euler_to_rotation_matrix(rotation_euler, inverse_y=True, y_bias=np.pi/2)
|
| 134 |
+
|
| 135 |
+
if ign_camera_pose:
|
| 136 |
+
transform_matrix = c2w_list[0]
|
| 137 |
+
else:
|
| 138 |
+
transform_matrix = c2w
|
| 139 |
+
|
| 140 |
+
rotation_matrix_4x4 = np.eye(4)
|
| 141 |
+
rotation_matrix_4x4[:3, :3] = rotation_matrix
|
| 142 |
+
|
| 143 |
+
new_transform_matrix = np.dot(rotation_matrix_4x4, transform_matrix)
|
| 144 |
+
c2w_list[frame_idx] = new_transform_matrix
|
| 145 |
+
|
| 146 |
+
return c2w_list
|
| 147 |
+
|
| 148 |
+
elif fixed_pose or pose_file is None:
|
| 149 |
+
return [np.eye(4) for _ in range(num_frames)]
|
| 150 |
+
|
| 151 |
+
with open(pose_file, 'r') as f:
|
| 152 |
+
meta = json.load(f)
|
| 153 |
+
frames = meta['frames'][pose_offset:pose_offset + num_frames]
|
| 154 |
+
|
| 155 |
+
for frame_idx, data in enumerate(frames):
|
| 156 |
+
transform_matrix = np.array(data["transform_matrix"])
|
| 157 |
+
if swap_type == 0:
|
| 158 |
+
new_transform_matrix = transform_matrix
|
| 159 |
+
elif swap_type == 1:
|
| 160 |
+
new_transform_matrix = swap_yz_in_extrinsic_matrix(transform_matrix)
|
| 161 |
+
if load_w2c:
|
| 162 |
+
new_transform_matrix = np.linalg.inv(new_transform_matrix)
|
| 163 |
+
data["transform_matrix"] = new_transform_matrix.tolist()
|
| 164 |
+
frames[frame_idx] = data
|
| 165 |
+
|
| 166 |
+
if ign_camera_pose:
|
| 167 |
+
c2w_list = [np.array(frames[0]["transform_matrix"]) for frame in frames]
|
| 168 |
+
else:
|
| 169 |
+
c2w_list = [np.array(frame['transform_matrix']) for frame in frames]
|
| 170 |
+
|
| 171 |
+
if pose_reset:
|
| 172 |
+
w2c_0 = np.linalg.inv(c2w_list[0])
|
| 173 |
+
c2w_list = [w2c_0 @ c2w_i for c2w_i in c2w_list] # compute c2c0
|
| 174 |
+
|
| 175 |
+
if remove_y_rotation:
|
| 176 |
+
c2w_list = remove_yaw_rotation(c2w_list)
|
| 177 |
+
|
| 178 |
+
if reverse_y_rotation:
|
| 179 |
+
c2w_list = reverse_yaw_rotation(c2w_list)
|
| 180 |
+
|
| 181 |
+
if yaw_0 != 0:
|
| 182 |
+
c2w_list = adjust_yaw_rotation(c2w_list, yaw_0)
|
| 183 |
+
|
| 184 |
+
for frame_idx, (data, c2w) in enumerate(zip(frames, c2w_list)):
|
| 185 |
+
if "hdri_euler" in data.keys():
|
| 186 |
+
rotation_matrix = euler_to_rotation_matrix(data["hdri_euler"], inverse_y=False)
|
| 187 |
+
|
| 188 |
+
if ign_camera_pose:
|
| 189 |
+
transform_matrix = c2w_list[0]
|
| 190 |
+
else:
|
| 191 |
+
transform_matrix = c2w
|
| 192 |
+
|
| 193 |
+
rotation_matrix_4x4 = np.eye(4)
|
| 194 |
+
rotation_matrix_4x4[:3, :3] = rotation_matrix
|
| 195 |
+
new_transform_matrix = np.dot(rotation_matrix_4x4, transform_matrix)
|
| 196 |
+
c2w_list[frame_idx] = new_transform_matrix
|
| 197 |
+
else:
|
| 198 |
+
print(f"Warning: 'hdri_euler' not found in frame {frame_idx} of {pose_file}. Using original transform matrix.")
|
| 199 |
+
break
|
| 200 |
+
|
| 201 |
+
return c2w_list
|
| 202 |
+
|
| 203 |
+
def latlong_vec(res, device=None):
|
| 204 |
+
gy, gx = torch.meshgrid(torch.linspace( 0.0 + 1.0 / res[0], 1.0 - 1.0 / res[0], res[0], device=device),
|
| 205 |
+
torch.linspace(-1.0 + 1.0 / res[1], 1.0 - 1.0 / res[1], res[1], device=device),
|
| 206 |
+
indexing='ij')
|
| 207 |
+
|
| 208 |
+
sintheta, costheta = torch.sin(gy*np.pi), torch.cos(gy*np.pi)
|
| 209 |
+
sinphi, cosphi = torch.sin(gx*np.pi), torch.cos(gx*np.pi)
|
| 210 |
+
|
| 211 |
+
dir_vec = torch.stack((
|
| 212 |
+
sintheta*sinphi,
|
| 213 |
+
costheta,
|
| 214 |
+
-sintheta*cosphi
|
| 215 |
+
), dim=-1)
|
| 216 |
+
# return dr.texture(cubemap[None, ...], dir_vec[None, ...].contiguous(), filter_mode='linear', boundary_mode='cube')[0]
|
| 217 |
+
return dir_vec #[H, W, 3]
|
| 218 |
+
|
| 219 |
+
def envmap_vec(res, device=None):
|
| 220 |
+
return -latlong_vec(res, device).flip(0).flip(1) #[H, W, 3]
|
| 221 |
+
|
| 222 |
+
def dot(x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
|
| 223 |
+
return torch.sum(x*y, -1, keepdim=True)
|
| 224 |
+
|
| 225 |
+
def length(x: torch.Tensor, eps: float =1e-20) -> torch.Tensor:
|
| 226 |
+
return torch.sqrt(torch.clamp(dot(x,x), min=eps)) # Clamp to avoid nan gradients because grad(sqrt(0)) = NaN
|
| 227 |
+
|
| 228 |
+
def safe_normalize(x: torch.Tensor, eps: float =1e-20) -> torch.Tensor:
|
| 229 |
+
return x / length(x, eps)
|
| 230 |
+
|
| 231 |
+
def cube_to_dir(s, x, y):
|
| 232 |
+
if s == 0: rx, ry, rz = torch.ones_like(x), -y, -x
|
| 233 |
+
elif s == 1: rx, ry, rz = -torch.ones_like(x), -y, x
|
| 234 |
+
elif s == 2: rx, ry, rz = x, torch.ones_like(x), y
|
| 235 |
+
elif s == 3: rx, ry, rz = x, -torch.ones_like(x), -y
|
| 236 |
+
elif s == 4: rx, ry, rz = x, -y, torch.ones_like(x)
|
| 237 |
+
elif s == 5: rx, ry, rz = -x, -y, -torch.ones_like(x)
|
| 238 |
+
return torch.stack((rx, ry, rz), dim=-1)
|
| 239 |
+
|
| 240 |
+
def latlong_to_cubemap(latlong_map, res):
|
| 241 |
+
cubemap = torch.zeros(6, res[0], res[1], latlong_map.shape[-1], dtype=torch.float32, device='cuda')
|
| 242 |
+
for s in range(6):
|
| 243 |
+
gy, gx = torch.meshgrid(torch.linspace(-1.0 + 1.0 / res[0], 1.0 - 1.0 / res[0], res[0], device='cuda'),
|
| 244 |
+
torch.linspace(-1.0 + 1.0 / res[1], 1.0 - 1.0 / res[1], res[1], device='cuda'),
|
| 245 |
+
indexing='ij')
|
| 246 |
+
v = safe_normalize(cube_to_dir(s, gx, gy))
|
| 247 |
+
|
| 248 |
+
tu = torch.atan2(v[..., 0:1], -v[..., 2:3]) / (2 * np.pi) + 0.5
|
| 249 |
+
tv = torch.acos(torch.clamp(v[..., 1:2], min=-1, max=1)) / np.pi
|
| 250 |
+
texcoord = torch.cat((tu, tv), dim=-1)
|
| 251 |
+
|
| 252 |
+
cubemap[s, ...] = dr.texture(latlong_map[None, ...], texcoord[None, ...], filter_mode='linear')[0]
|
| 253 |
+
return cubemap
|
| 254 |
+
|
| 255 |
+
def load_and_preprocess_hdr(hdr_dir, env_strength, env_flip, env_rot, device, rotation180=False, inverse_env=False, flip_env=False):
|
| 256 |
+
"""Load and preprocess the HDR environment map."""
|
| 257 |
+
if hdr_dir.endswith('.hdr') or hdr_dir.endswith('.exr'):
|
| 258 |
+
latlong_img = imageio_v3.imread(hdr_dir, flags=cv2.IMREAD_UNCHANGED, plugin='opencv')
|
| 259 |
+
elif hdr_dir.endswith('.jpg') or hdr_dir.endswith('.png'):
|
| 260 |
+
import skimage
|
| 261 |
+
latlong_img = skimage.io.imread(hdr_dir)[..., :3]
|
| 262 |
+
latlong_img = skimage.img_as_float(latlong_img)
|
| 263 |
+
latlong_img = np.power(latlong_img, 2.4).astype(np.float32)
|
| 264 |
+
latlong_img *= 2 # for mit dataset
|
| 265 |
+
|
| 266 |
+
if rotation180:
|
| 267 |
+
height, width, channels = latlong_img.shape
|
| 268 |
+
shift_amount = width // 2
|
| 269 |
+
shifted_hdr = np.zeros_like(latlong_img)
|
| 270 |
+
shifted_hdr[:, -shift_amount:, :] = latlong_img[:, :shift_amount, :]
|
| 271 |
+
shifted_hdr[:, :-shift_amount, :] = latlong_img[:, shift_amount:, :]
|
| 272 |
+
latlong_img = shifted_hdr
|
| 273 |
+
|
| 274 |
+
if inverse_env:
|
| 275 |
+
latlong_img = latlong_img[:, ::-1, :]
|
| 276 |
+
height, width, channels = latlong_img.shape
|
| 277 |
+
shift_amount = width // 2
|
| 278 |
+
shifted_hdr = np.zeros_like(latlong_img)
|
| 279 |
+
shifted_hdr[:, -shift_amount:, :] = latlong_img[:, :shift_amount, :]
|
| 280 |
+
shifted_hdr[:, :-shift_amount, :] = latlong_img[:, shift_amount:, :]
|
| 281 |
+
latlong_img = shifted_hdr
|
| 282 |
+
|
| 283 |
+
if flip_env:
|
| 284 |
+
latlong_img = latlong_img[:, ::-1, :].copy()
|
| 285 |
+
|
| 286 |
+
latlong_img = torch.tensor(latlong_img, dtype=torch.float32, device=device)
|
| 287 |
+
latlong_img *= env_strength
|
| 288 |
+
|
| 289 |
+
# Cleanup NaNs and Infs
|
| 290 |
+
latlong_img = torch.nan_to_num(latlong_img, nan=0.0, posinf=65504.0, neginf=0.0)
|
| 291 |
+
latlong_img = latlong_img.clamp(0.0, 65504.0)
|
| 292 |
+
|
| 293 |
+
if env_flip:
|
| 294 |
+
latlong_img = torch.flip(latlong_img, dims=[1])
|
| 295 |
+
|
| 296 |
+
if env_rot != 0:
|
| 297 |
+
lat_h, lat_w = latlong_img.shape[:2]
|
| 298 |
+
pixel_rot = int(lat_w * env_rot / 360)
|
| 299 |
+
latlong_img = torch.roll(latlong_img, shifts=pixel_rot, dims=1)
|
| 300 |
+
|
| 301 |
+
# Convert to cubemap
|
| 302 |
+
cubemap = latlong_to_cubemap(latlong_img, [512, 512])
|
| 303 |
+
return cubemap
|
| 304 |
+
|
| 305 |
+
def prepare_metadata(hdr_dir, env_rot, env_flip, env_strength, fixed_pose, rotate_envlight, save_dir, prefix):
|
| 306 |
+
"""Prepare metadata about the environment map processing."""
|
| 307 |
+
env_meta = {
|
| 308 |
+
'envmap': os.path.basename(hdr_dir),
|
| 309 |
+
'envmap_rot': env_rot,
|
| 310 |
+
'envmap_flip': env_flip,
|
| 311 |
+
'envmap_strength': env_strength,
|
| 312 |
+
'fixed_pose': fixed_pose,
|
| 313 |
+
'rotate_envlight': rotate_envlight,
|
| 314 |
+
}
|
| 315 |
+
|
| 316 |
+
if save_dir:
|
| 317 |
+
os.makedirs(save_dir, exist_ok=True)
|
| 318 |
+
meta_path = os.path.join(save_dir, f'{prefix}.meta.json')
|
| 319 |
+
with open(meta_path, 'w') as f:
|
| 320 |
+
json.dump(env_meta, f, indent=4)
|
| 321 |
+
|
| 322 |
+
return env_meta
|
| 323 |
+
|
| 324 |
+
def rotate_y(a, device=None):
|
| 325 |
+
s, c = np.sin(a), np.cos(a)
|
| 326 |
+
return torch.tensor([[ c, 0, s, 0],
|
| 327 |
+
[ 0, 1, 0, 0],
|
| 328 |
+
[-s, 0, c, 0],
|
| 329 |
+
[ 0, 0, 0, 1]], dtype=torch.float32, device=device)
|
| 330 |
+
|
| 331 |
+
def process_projected_envmap(cubemap, vec, c2w, y_rot, H, W):
|
| 332 |
+
"""Process the camera-oriented projected environment map."""
|
| 333 |
+
vec_cam = vec.view(-1, 3) @ c2w[:3, :3].T
|
| 334 |
+
vec_query = (vec_cam @ y_rot[:3, :3].T).view(1, H, W, 3)
|
| 335 |
+
env_proj = dr.texture(cubemap.unsqueeze(0), -vec_query.contiguous(),
|
| 336 |
+
filter_mode='linear', boundary_mode='cube')[0]
|
| 337 |
+
env_proj = torch.flip(env_proj, dims=[0, 1])
|
| 338 |
+
return env_proj
|
| 339 |
+
|
| 340 |
+
def rgb2srgb(rgb):
|
| 341 |
+
return torch.where(rgb <= 0.0031308, 12.92 * rgb, 1.055 * rgb**(1/2.4) - 0.055)
|
| 342 |
+
|
| 343 |
+
def reinhard(x, max_point=16):
|
| 344 |
+
y_rein = x * (1 + x / (max_point ** 2)) / (1 + x)
|
| 345 |
+
return y_rein
|
| 346 |
+
|
| 347 |
+
def hdr_mapping(env_hdr, log_scale):
|
| 348 |
+
"""Map HDR environment maps to LDR and logarithmic representations."""
|
| 349 |
+
env_ev0 = rgb2srgb(reinhard(env_hdr, max_point=16).clamp(0, 1))
|
| 350 |
+
env_log = rgb2srgb(torch.log1p(env_hdr) / np.log1p(log_scale)).clamp(0, 1)
|
| 351 |
+
return {
|
| 352 |
+
'env_hdr': env_hdr, # Original HDR image
|
| 353 |
+
'env_ev0': env_ev0, # LDR image after tone mapping
|
| 354 |
+
'env_log': env_log, # Logarithmic scaling
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
+
def process_environment_map(
|
| 358 |
+
hdr_dir,
|
| 359 |
+
resolution=(512, 512),
|
| 360 |
+
num_frames=1,
|
| 361 |
+
fixed_pose=True,
|
| 362 |
+
pose_file=None,
|
| 363 |
+
pose_list=None,
|
| 364 |
+
rotation_euler=None,
|
| 365 |
+
pose_offset=0,
|
| 366 |
+
pose_reset=False,
|
| 367 |
+
rotate_envlight=False,
|
| 368 |
+
env_format=['proj'],
|
| 369 |
+
log_scale=10000,
|
| 370 |
+
env_strength=1.0,
|
| 371 |
+
env_flip=True,
|
| 372 |
+
env_rot=180.0,
|
| 373 |
+
save_dir=None,
|
| 374 |
+
prefix='0000',
|
| 375 |
+
device=None,
|
| 376 |
+
rotation180=False,
|
| 377 |
+
ign_camera_pose=True,
|
| 378 |
+
inverse_env=False,
|
| 379 |
+
swap_type=0,
|
| 380 |
+
load_w2c=False,
|
| 381 |
+
flip_env=False,
|
| 382 |
+
remove_y_rotation=False,
|
| 383 |
+
reverse_y_rotation=False,
|
| 384 |
+
yaw_0=0,
|
| 385 |
+
):
|
| 386 |
+
"""
|
| 387 |
+
Preprocess HDR environment maps for rendering.
|
| 388 |
+
FIXME: Note that this function bakes in a flip and rotate operation for the environment light. Set to env_flip=True and env_rot=180 is considered as loading the original environment map.
|
| 389 |
+
|
| 390 |
+
Args:
|
| 391 |
+
hdr_dir (str): Path to the HDR environment map file.
|
| 392 |
+
resolution (tuple of int): Resolution of the output images (H, W).
|
| 393 |
+
num_frames (int): Number of frames to process.
|
| 394 |
+
fixed_pose (bool): Use a fixed camera pose (identity matrix) if True.
|
| 395 |
+
pose_file (str): Path to the camera pose file (JSON).
|
| 396 |
+
pose_offset (int): Offset for the pose frames in the pose file.
|
| 397 |
+
pose_reset (bool): Reset camera poses to be relative to the first frame.
|
| 398 |
+
rotate_envlight (bool): Rotate the environment light over frames if True.
|
| 399 |
+
env_format (list of str): Formats of the environment maps to generate ('proj', 'fixed', 'ball').
|
| 400 |
+
log_scale (int): Log scale factor for HDR mapping.
|
| 401 |
+
env_strength (float): Strength multiplier for the environment map.
|
| 402 |
+
env_flip (bool): Flip the environment map horizontally if True.
|
| 403 |
+
env_rot (float): Rotation angle for the environment map in degrees.
|
| 404 |
+
save_dir (str): Directory to save the processed images (optional).
|
| 405 |
+
prefix (str): Prefix for the output files (used if saving images).
|
| 406 |
+
|
| 407 |
+
Returns:
|
| 408 |
+
dict: A dictionary containing the processed environment maps and metadata.
|
| 409 |
+
{
|
| 410 |
+
'metadata': env_meta,
|
| 411 |
+
'fixed': mapping_results_for_fixed_envmap, # Only if 'fixed' in env_format
|
| 412 |
+
'env_ldr': stacked_tensor_of_proj_env_ldr, # Only if 'proj' in env_format
|
| 413 |
+
'env_log': stacked_tensor_of_proj_env_log, # Only if 'proj' in env_format
|
| 414 |
+
'ball_env_ldr': stacked_tensor_of_ball_env_ldr, # Only if 'ball' in env_format
|
| 415 |
+
'ball_env_log': stacked_tensor_of_ball_env_log, # Only if 'ball' in env_format
|
| 416 |
+
}
|
| 417 |
+
Tensors are with shape (T, H, W, 3) in [0, 1]
|
| 418 |
+
"""
|
| 419 |
+
H, W = resolution # (704, 1280)
|
| 420 |
+
if device is None:
|
| 421 |
+
device = 'cuda' if torch.cuda.is_available() else 'cpu'
|
| 422 |
+
vec = latlong_vec((H, W), device=device)
|
| 423 |
+
|
| 424 |
+
# Prepare camera poses
|
| 425 |
+
poses = prepare_camera_poses(
|
| 426 |
+
num_frames=num_frames,
|
| 427 |
+
fixed_pose=fixed_pose,
|
| 428 |
+
pose_file=pose_file,
|
| 429 |
+
pose_offset=pose_offset,
|
| 430 |
+
pose_reset=pose_reset,
|
| 431 |
+
device=device,
|
| 432 |
+
ign_camera_pose=ign_camera_pose,
|
| 433 |
+
swap_type=swap_type,
|
| 434 |
+
load_w2c=load_w2c,
|
| 435 |
+
remove_y_rotation=remove_y_rotation,
|
| 436 |
+
reverse_y_rotation=reverse_y_rotation,
|
| 437 |
+
yaw_0=yaw_0,
|
| 438 |
+
pose_list=pose_list,
|
| 439 |
+
rotation_euler=rotation_euler,
|
| 440 |
+
)
|
| 441 |
+
|
| 442 |
+
# Prepare rotations for the environment light # 57 * rot
|
| 443 |
+
rots = np.linspace(0, 2 * np.pi, num_frames) if rotate_envlight else [0] * num_frames
|
| 444 |
+
|
| 445 |
+
# Load and preprocess the HDR environment map
|
| 446 |
+
cubemap = load_and_preprocess_hdr(
|
| 447 |
+
hdr_dir=hdr_dir,
|
| 448 |
+
env_strength=env_strength,
|
| 449 |
+
env_flip=env_flip,
|
| 450 |
+
env_rot=env_rot,
|
| 451 |
+
device=device,
|
| 452 |
+
rotation180=rotation180,
|
| 453 |
+
inverse_env=inverse_env,
|
| 454 |
+
flip_env=flip_env,
|
| 455 |
+
)
|
| 456 |
+
|
| 457 |
+
# Prepare metadata
|
| 458 |
+
env_meta = prepare_metadata(
|
| 459 |
+
hdr_dir=hdr_dir,
|
| 460 |
+
env_rot=env_rot,
|
| 461 |
+
env_flip=env_flip,
|
| 462 |
+
env_strength=env_strength,
|
| 463 |
+
fixed_pose=fixed_pose,
|
| 464 |
+
rotate_envlight=rotate_envlight,
|
| 465 |
+
save_dir=save_dir,
|
| 466 |
+
prefix=prefix
|
| 467 |
+
)
|
| 468 |
+
|
| 469 |
+
# Initialize result dictionary
|
| 470 |
+
results = {
|
| 471 |
+
'metadata': env_meta,
|
| 472 |
+
}
|
| 473 |
+
|
| 474 |
+
# Prepare lists to collect per-frame tensors
|
| 475 |
+
if 'proj' in env_format:
|
| 476 |
+
proj_env_ldr_list = []
|
| 477 |
+
proj_env_log_list = []
|
| 478 |
+
|
| 479 |
+
# Process per-frame environment maps
|
| 480 |
+
for i in range(num_frames):
|
| 481 |
+
c2w = torch.from_numpy(poses[i]).float().to(device)
|
| 482 |
+
y_rot = rotate_y(rots[i], device=device)
|
| 483 |
+
|
| 484 |
+
if 'proj' in env_format:
|
| 485 |
+
env_proj = process_projected_envmap(cubemap, vec, c2w, y_rot, H, W)
|
| 486 |
+
mapping_results = hdr_mapping(env_proj, log_scale=log_scale)
|
| 487 |
+
proj_env_ldr_list.append(mapping_results['env_ev0'])
|
| 488 |
+
proj_env_log_list.append(mapping_results['env_log'])
|
| 489 |
+
|
| 490 |
+
if 'proj' in env_format:
|
| 491 |
+
results['env_ldr'] = torch.stack(proj_env_ldr_list, dim=0)
|
| 492 |
+
results['env_log'] = torch.stack(proj_env_log_list, dim=0)
|
| 493 |
+
|
| 494 |
+
return results
|
| 495 |
+
|
| 496 |
+
def save_array_as_video(video_array, output_path: str, fps: int = 24):
|
| 497 |
+
"""
|
| 498 |
+
video_array: t h w c, np.array or tensors
|
| 499 |
+
"""
|
| 500 |
+
if isinstance(video_array, torch.Tensor):
|
| 501 |
+
video_array = video_array.cpu().numpy()
|
| 502 |
+
if video_array.dtype != np.uint8:
|
| 503 |
+
print("float 2 uint8")
|
| 504 |
+
# If the data range is [-1, 1]
|
| 505 |
+
if video_array.min() < 0:
|
| 506 |
+
video_array = ((video_array + 1) * 127.5).clip(0, 255).astype(np.uint8)
|
| 507 |
+
# If the data range is [0, 1]
|
| 508 |
+
else:
|
| 509 |
+
video_array = (video_array * 255).clip(0, 255).astype(np.uint8)
|
| 510 |
+
|
| 511 |
+
try:
|
| 512 |
+
if not os.path.isfile(output_path):
|
| 513 |
+
imageio.mimsave(
|
| 514 |
+
output_path,
|
| 515 |
+
[frame for frame in video_array],
|
| 516 |
+
fps=fps,
|
| 517 |
+
codec='libx264'
|
| 518 |
+
)
|
| 519 |
+
print("succeed to save vide")
|
| 520 |
+
print(f"video already exists in {output_path}")
|
| 521 |
+
except Exception as e:
|
| 522 |
+
print(f"fail to save video: {e}")
|
| 523 |
+
|
| 524 |
+
def process_hdr(hdr_path, save_path, env_strength=1.0, inverse_env=False):
|
| 525 |
+
hdr_path = glob.glob(f'{hdr_path}*')[0]
|
| 526 |
+
|
| 527 |
+
if '.hdr' in hdr_path:
|
| 528 |
+
env_strength = env_strength / 3.0
|
| 529 |
+
|
| 530 |
+
num_of_frames = 57
|
| 531 |
+
ldr_list = []
|
| 532 |
+
hdr_log_list = []
|
| 533 |
+
env_dir_list = []
|
| 534 |
+
|
| 535 |
+
envlight_dict = process_environment_map(
|
| 536 |
+
hdr_dir=hdr_path,
|
| 537 |
+
resolution=(320, 576),
|
| 538 |
+
num_frames=num_of_frames, # 1 for mit dataset
|
| 539 |
+
fixed_pose=True,
|
| 540 |
+
rotate_envlight=False,
|
| 541 |
+
env_format=['proj', ],
|
| 542 |
+
device='cuda',
|
| 543 |
+
rotation180=False,
|
| 544 |
+
inverse_env=inverse_env, # True for mit dataset, False for others
|
| 545 |
+
log_scale=60000,
|
| 546 |
+
env_strength=env_strength, # 1.0 for mit dataset
|
| 547 |
+
) # Tensors are with shape (T, H, W, 3) in [0, 1]
|
| 548 |
+
ldr_list = (envlight_dict['env_ldr'].cpu().numpy() * 255).astype(np.uint8)
|
| 549 |
+
hdr_log_list = (envlight_dict['env_log'].cpu().numpy() * 255).astype(np.uint8)
|
| 550 |
+
env_nrm = ((envmap_vec([320, 576], device='cpu').cpu().numpy()*0.5 + 0.5) * 255).astype(np.uint8)
|
| 551 |
+
for _ in range(num_of_frames):
|
| 552 |
+
env_dir_list.append(env_nrm)
|
| 553 |
+
|
| 554 |
+
os.makedirs(save_path, exist_ok=True)
|
| 555 |
+
ldr_video_path = os.path.join(save_path, "ldr_video_fix_first_frame.mp4")
|
| 556 |
+
hdr_log_video_path = os.path.join(save_path, "hdr_log_video_fix_first_frame.mp4")
|
| 557 |
+
env_dir_video_path = os.path.join(save_path, "env_dir_video_fix_first_frame.mp4")
|
| 558 |
+
|
| 559 |
+
if os.path.exists(ldr_video_path):
|
| 560 |
+
os.remove(ldr_video_path)
|
| 561 |
+
if os.path.exists(hdr_log_video_path):
|
| 562 |
+
os.remove(hdr_log_video_path)
|
| 563 |
+
if os.path.exists(env_dir_video_path):
|
| 564 |
+
os.remove(env_dir_video_path)
|
| 565 |
+
|
| 566 |
+
save_array_as_video(np.array(ldr_list),ldr_video_path)
|
| 567 |
+
save_array_as_video(np.array(hdr_log_list),hdr_log_video_path)
|
| 568 |
+
save_array_as_video(np.array(env_dir_list),env_dir_video_path)
|
| 569 |
+
|
| 570 |
+
def parse_arguments() -> argparse.Namespace:
|
| 571 |
+
parser = argparse.ArgumentParser(description="Env maps processing script")
|
| 572 |
+
# Specific arguments
|
| 573 |
+
parser.add_argument(
|
| 574 |
+
"--env_dir",
|
| 575 |
+
type=str,
|
| 576 |
+
default=None,
|
| 577 |
+
help="Path to the directory containing the environment map."
|
| 578 |
+
)
|
| 579 |
+
parser.add_argument(
|
| 580 |
+
"--save_path",
|
| 581 |
+
type=str,
|
| 582 |
+
default=None,
|
| 583 |
+
help="Path to the directory where the processed environment maps will be saved."
|
| 584 |
+
)
|
| 585 |
+
parser.add_argument(
|
| 586 |
+
"--env_strength",
|
| 587 |
+
type=float,
|
| 588 |
+
default=1.0,
|
| 589 |
+
help="Strength of the environment map."
|
| 590 |
+
)
|
| 591 |
+
return parser.parse_args()
|
| 592 |
+
|
| 593 |
+
if __name__ == "__main__":
|
| 594 |
+
args = parse_arguments()
|
| 595 |
+
process_hdr(args.env_dir, save_path=args.save_path, env_strength=args.env_strength)
|
| 596 |
+
|
| 597 |
+
|
| 598 |
+
|
| 599 |
+
|
tools/reorg_gbuffer_from_dr_delighting.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import pdb
|
| 3 |
+
import json
|
| 4 |
+
from tqdm import tqdm
|
| 5 |
+
import shutil, glob
|
| 6 |
+
import argparse
|
| 7 |
+
|
| 8 |
+
def parse_arguments() -> argparse.Namespace:
|
| 9 |
+
parser = argparse.ArgumentParser(description="Text to world generation demo script")
|
| 10 |
+
|
| 11 |
+
parser.add_argument(
|
| 12 |
+
"--frame_dir",
|
| 13 |
+
type=str,
|
| 14 |
+
default=None,
|
| 15 |
+
help="."
|
| 16 |
+
)
|
| 17 |
+
parser.add_argument(
|
| 18 |
+
"--gbuffer_dir",
|
| 19 |
+
type=str,
|
| 20 |
+
default=None,
|
| 21 |
+
help="."
|
| 22 |
+
)
|
| 23 |
+
parser.add_argument(
|
| 24 |
+
"--tgt_dir",
|
| 25 |
+
type=str,
|
| 26 |
+
default=None,
|
| 27 |
+
help="."
|
| 28 |
+
)
|
| 29 |
+
|
| 30 |
+
return parser.parse_args()
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def collect_available_chunk_ids(gbuffer_seq_dir):
|
| 34 |
+
chunk_ids = set()
|
| 35 |
+
for path in glob.glob(os.path.join(gbuffer_seq_dir, "*.jpg")):
|
| 36 |
+
name = os.path.basename(path)
|
| 37 |
+
parts = name.split(".")
|
| 38 |
+
if len(parts) < 4:
|
| 39 |
+
continue
|
| 40 |
+
if parts[0].isdigit():
|
| 41 |
+
chunk_ids.add(int(parts[0]))
|
| 42 |
+
return sorted(chunk_ids)
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
args = parse_arguments()
|
| 46 |
+
frame_dir = args.frame_dir
|
| 47 |
+
gbuffer_dir = args.gbuffer_dir
|
| 48 |
+
tgt_dir = args.tgt_dir
|
| 49 |
+
os.makedirs(tgt_dir, exist_ok=True)
|
| 50 |
+
|
| 51 |
+
seq_list = sorted(os.listdir(frame_dir))
|
| 52 |
+
for seq_name in tqdm(seq_list):
|
| 53 |
+
chunk_size = 57
|
| 54 |
+
overlap_n_frames = 0
|
| 55 |
+
step = chunk_size - overlap_n_frames
|
| 56 |
+
|
| 57 |
+
rgb_path_list = sorted(
|
| 58 |
+
glob.glob(os.path.join(frame_dir, f"{seq_name}/*.jpg")) +
|
| 59 |
+
glob.glob(os.path.join(frame_dir, f"{seq_name}/*.png"))
|
| 60 |
+
)
|
| 61 |
+
images_num = len(rgb_path_list)
|
| 62 |
+
|
| 63 |
+
gbuffer_file_path = f"{gbuffer_dir}/{seq_name}"
|
| 64 |
+
available_chunk_ids = collect_available_chunk_ids(gbuffer_file_path)
|
| 65 |
+
|
| 66 |
+
if len(available_chunk_ids) == 0:
|
| 67 |
+
print(f"Skip {seq_name}: no gbuffer files found in {gbuffer_file_path}")
|
| 68 |
+
continue
|
| 69 |
+
|
| 70 |
+
max_valid_chunk_idx = max(available_chunk_ids)
|
| 71 |
+
|
| 72 |
+
print("Processing", seq_name)
|
| 73 |
+
for t_gbuffer in ["Base Color", "normal", "depth", "Roughness", "Metallic", "env", "images_4"]:
|
| 74 |
+
os.system(f"rm -rf {tgt_dir}/{seq_name}*/{t_gbuffer}")
|
| 75 |
+
|
| 76 |
+
for image_idx in range(images_num):
|
| 77 |
+
raw_chunk_idx = image_idx // step
|
| 78 |
+
frame_in_chunk = image_idx % step
|
| 79 |
+
|
| 80 |
+
if raw_chunk_idx > max_valid_chunk_idx:
|
| 81 |
+
print(
|
| 82 |
+
f"Stop {seq_name} at image_idx={image_idx}: "
|
| 83 |
+
f"raw_chunk_idx={raw_chunk_idx} exceeds max_valid_chunk_idx={max_valid_chunk_idx}"
|
| 84 |
+
)
|
| 85 |
+
break
|
| 86 |
+
|
| 87 |
+
chunk_idx = raw_chunk_idx
|
| 88 |
+
frame_idx = frame_in_chunk
|
| 89 |
+
seq_name_now = seq_name + f".{chunk_idx}"
|
| 90 |
+
|
| 91 |
+
gbuffer_src_map = {}
|
| 92 |
+
missing_file = False
|
| 93 |
+
for gbuffer, t_gbuffer in [
|
| 94 |
+
("basecolor", "Base Color"),
|
| 95 |
+
("normal", "normal"),
|
| 96 |
+
("depth", "depth"),
|
| 97 |
+
("roughness", "Roughness"),
|
| 98 |
+
("metallic", "Metallic"),
|
| 99 |
+
]:
|
| 100 |
+
img_name = f"{chunk_idx:04d}.{frame_in_chunk:04d}.{gbuffer}.jpg"
|
| 101 |
+
src_path = os.path.join(gbuffer_file_path, img_name)
|
| 102 |
+
if not os.path.exists(src_path):
|
| 103 |
+
print(f"Stop {seq_name_now}: missing gbuffer file {src_path}")
|
| 104 |
+
missing_file = True
|
| 105 |
+
break
|
| 106 |
+
gbuffer_src_map[t_gbuffer] = src_path
|
| 107 |
+
|
| 108 |
+
if missing_file:
|
| 109 |
+
break
|
| 110 |
+
|
| 111 |
+
for t_gbuffer in ["Base Color", "normal", "depth", "Roughness", "Metallic", "env", "images_4"]:
|
| 112 |
+
if os.path.exists(f"{tgt_dir}/{seq_name_now}/{t_gbuffer}") and frame_idx == 0:
|
| 113 |
+
shutil.rmtree(f"{tgt_dir}/{seq_name_now}/{t_gbuffer}")
|
| 114 |
+
os.makedirs(f"{tgt_dir}/{seq_name_now}/{t_gbuffer}", exist_ok=True)
|
| 115 |
+
|
| 116 |
+
for t_gbuffer, src_path in gbuffer_src_map.items():
|
| 117 |
+
shutil.copy(
|
| 118 |
+
src_path,
|
| 119 |
+
f"{tgt_dir}/{seq_name_now}/{t_gbuffer}/frame_{frame_idx:04d}.jpg"
|
| 120 |
+
)
|
| 121 |
+
|
| 122 |
+
rgb_ext = os.path.basename(rgb_path_list[image_idx]).split(".")[-1]
|
| 123 |
+
shutil.copy(
|
| 124 |
+
rgb_path_list[image_idx],
|
| 125 |
+
f"{tgt_dir}/{seq_name_now}/images_4/frame_{frame_idx:04d}.{rgb_ext}"
|
| 126 |
+
)
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
|