tamarher commited on
Commit
a1cc385
·
verified ·
1 Parent(s): b15077d

Add files using upload-large-folder tool

Browse files
LICENSES.md ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Licenses for the TRELLIS.2 MLX 8-bit Bundle
2
+
3
+ This repository combines derivatives of three separately licensed models. No
4
+ single license replaces the component licenses below.
5
+
6
+ | Component | Files | Governing terms |
7
+ | --- | --- | --- |
8
+ | Microsoft TRELLIS.2-4B | `ckpts/`, `pipeline.json`, `texturing_pipeline.json` | [MIT License](LICENSE_TRELLIS2) |
9
+ | Meta DINOv3 ViT-L/16 | `dinov3/` | [DINOv3 License](LICENSE_DINOV3.md) |
10
+ | BRIA RMBG-2.0 | `rmbg/` | [CC BY-NC 4.0 attribution and change notice](LICENSE_RMBG2.md) |
11
+
12
+ The quantization metadata, packaging, and model card describe changes made for
13
+ `mlx-spatial`; they do not relax or replace any upstream term. You must comply
14
+ with every license that applies to the files you use or redistribute.
15
+
16
+ Because the bundle includes RMBG-2.0, use of the complete bundle is limited to
17
+ non-commercial purposes unless you obtain separate commercial rights from
18
+ BRIA. The DINOv3 agreement also includes redistribution, trade-control, and
19
+ other conditions that must be read in full.
20
+
21
+ This repository is an unofficial derivative and is not affiliated with or
22
+ endorsed by Microsoft, Meta, BRIA, or the original authors.
23
+
24
+ ## Upstream References
25
+
26
+ - TRELLIS.2-4B: <https://huggingface.co/microsoft/TRELLIS.2-4B>
27
+ - TRELLIS.2 source: <https://github.com/microsoft/TRELLIS.2>
28
+ - DINOv3 ViT-L/16: <https://huggingface.co/facebook/dinov3-vitl16-pretrain-lvd1689m>
29
+ - DINOv3 source: <https://github.com/facebookresearch/dinov3>
30
+ - RMBG-2.0: <https://huggingface.co/briaai/RMBG-2.0>
31
+ - RMBG-2.0 source: <https://github.com/Bria-AI/RMBG-2.0>
LICENSE_DINOV3.md ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DINOv3 License
2
+
3
+ *Last Updated: August 19, 2025*
4
+
5
+ **“Agreement”** means the terms and conditions for use, reproduction, distribution and modification of the DINO Materials set forth herein.
6
+
7
+ **“DINO Materials”** means, collectively, Documentation and the models, software and algorithms, including machine-learning model code, trained model weights, inference-enabling code, training-enabling code, fine-tuning enabling code, and other elements of the foregoing distributed by Meta and made available under this Agreement.
8
+
9
+ **“Documentation”** means the specifications, manuals and documentation accompanying
10
+ DINO Materials distributed by Meta.
11
+
12
+ **“Licensee”** or **“you”** means you, or your employer or any other person or entity (if you are entering into this Agreement on such person or entity’s behalf), of the age required under applicable laws, rules or regulations to provide legal consent and that has legal authority to bind your employer or such other person or entity if you are entering in this Agreement on their behalf.
13
+
14
+ **“Meta”** or **“we”** means Meta Platforms Ireland Limited (if you are located in or, if you are an entity, your principal place of business is in the EEA or Switzerland) or Meta Platforms, Inc. (if you are located outside of the EEA or Switzerland).
15
+
16
+ **“Sanctions”** means any economic or trade sanctions or restrictions administered or enforced by the United States (including the Office of Foreign Assets Control of the U.S. Department of the Treasury (“OFAC”), the U.S. Department of State and the U.S. Department of Commerce), the United Nations, the European Union, or the United Kingdom.
17
+
18
+ **“Trade Controls”** means any of the following: Sanctions and applicable export and import controls.
19
+
20
+ By clicking “I Accept” below or by using or distributing any portion or element of the DINO Materials, you agree to be bound by this Agreement.
21
+
22
+ ## 1. License Rights and Redistribution.
23
+
24
+ a. <ins>Grant of Rights</ins>. You are granted a non-exclusive, worldwide, non-transferable and royalty-free limited license under Meta’s intellectual property or other rights owned by Meta embodied in the DINO Materials to use, reproduce, distribute, copy, create derivative works of, and make modifications to the DINO Materials.
25
+
26
+ b. <ins>Redistribution and Use</ins>.
27
+
28
+ i. Distribution of DINO Materials, and any derivative works thereof, are subject to the terms of this Agreement. If you distribute or make the DINO Materials, or any derivative works thereof, available to a third party, you may only do so under the terms of this Agreement and you shall provide a copy of this Agreement with any such DINO Materials.
29
+
30
+ ii. If you submit for publication the results of research you perform on, using, or otherwise in connection with DINO Materials, you must acknowledge the use of DINO Materials in your publication.
31
+
32
+ iii. Your use of the DINO Materials must comply with applicable laws and regulations, including Trade Control Laws and applicable privacy and data protection laws.
33
+
34
+ iv. Your use of the DINO Materials will not involve or encourage others to reverse engineer, decompile or discover the underlying components of the DINO Materials.
35
+
36
+ v. You are not the target of Trade Controls and your use of DINO Materials must comply with Trade Controls. You agree not to use, or permit others to use, DINO Materials for any activities subject to the International Traffic in Arms Regulations (ITAR) or end uses prohibited by Trade Controls, including those related to military or warfare purposes, nuclear industries or applications, espionage, or the development or use of guns or illegal weapons.
37
+
38
+ ## 2. User Support.
39
+
40
+ Your use of the DINO Materials is done at your own discretion; Meta does not process any information nor provide any service in relation to such use. Meta is under no obligation to provide any support services for the DINO Materials. Any support provided is “as is”, “with all faults”, and without warranty of any kind.
41
+
42
+ ## 3. Disclaimer of Warranty.
43
+
44
+ UNLESS REQUIRED BY APPLICABLE LAW, THE DINO MATERIALS AND ANY OUTPUT AND RESULTS THEREFROM ARE PROVIDED ON AN “AS IS” BASIS, WITHOUT WARRANTIES OF ANY KIND, AND META DISCLAIMS ALL WARRANTIES OF ANY KIND, BOTH EXPRESS AND IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE FOR DETERMINING THE APPROPRIATENESS OF USING OR REDISTRIBUTING THE DINO MATERIALS AND ASSUME ANY RISKS ASSOCIATED WITH YOUR USE OF THE DINO MATERIALS AND ANY OUTPUT AND RESULTS.
45
+
46
+ ## 4. Limitation of Liability.
47
+
48
+ IN NO EVENT WILL META OR ITS AFFILIATES BE LIABLE UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, TORT, NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, ARISING OUT OF THIS AGREEMENT, FOR ANY LOST PROFITS OR ANY DIRECT OR INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL, EXEMPLARY OR PUNITIVE DAMAGES, EVEN IF META OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF ANY OF THE FOREGOING.
49
+
50
+ ## 5. Intellectual Property.
51
+
52
+ a. Subject to Meta’s ownership of DINO Materials and derivatives made by or for Meta, with respect to any derivative works and modifications of the DINO Materials that are made by you, as between you and Meta, you are and will be the owner of such derivative works and modifications.
53
+
54
+ b. If you institute litigation or other proceedings against Meta or any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the DINO Materials, outputs or results, or any portion of any of the foregoing, constitutes infringement of intellectual property or other rights owned or licensable by you, then any licenses granted to you under this Agreement shall terminate as of the date such litigation or claim is filed or instituted. You will indemnify and hold harmless Meta from and against any claim by any third party arising out of or related to your use or distribution of the DINO Materials.
55
+
56
+ ## 6. Term and Termination.
57
+
58
+ The term of this Agreement will commence upon your acceptance of this Agreement or access to the DINO Materials and will continue in full force and effect until terminated in accordance with the terms and conditions herein. Meta may terminate this Agreement if you are in breach of any term or condition of this Agreement. Upon termination of this Agreement, you shall delete and cease use of the DINO Materials. Sections 3, 4 and 7 shall survive the termination of this Agreement.
59
+
60
+ ## 7. Governing Law and Jurisdiction.
61
+
62
+ This Agreement will be governed and construed under the laws of the State of California without regard to choice of law principles, and the UN Convention on Contracts for the International Sale of Goods does not apply to this Agreement. The courts of California shall have exclusive jurisdiction of any dispute arising out of this Agreement.
63
+
64
+ ## 8. Modifications and Amendments.
65
+
66
+ Meta may modify this Agreement from time to time; provided that they are similar in spirit to the current version of the Agreement, but may differ in detail to address new problems or concerns. All such changes will be effective immediately. Your continued use of the DINO Materials after any modification to this Agreement constitutes your agreement to such modification. Except as provided in this Agreement, no modification or addition to any provision of this Agreement will be binding unless it is in writing and signed by an authorized representative of both you and Meta.
LICENSE_RMBG2.md ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # BRIA RMBG-2.0 License and Attribution
2
+
3
+ This distribution includes a selectively quantized derivative of BRIA
4
+ RMBG-2.0.
5
+
6
+ - Original work: **BRIA RMBG-2.0**
7
+ - Creator: **BRIA AI**
8
+ - Model: <https://huggingface.co/briaai/RMBG-2.0>
9
+ - Source: <https://github.com/Bria-AI/RMBG-2.0>
10
+ - License: [Creative Commons Attribution-NonCommercial 4.0
11
+ International](https://creativecommons.org/licenses/by-nc/4.0/)
12
+
13
+ The original model is available for non-commercial use under CC BY-NC 4.0.
14
+ Commercial use requires a separate agreement with BRIA. Refer to the original
15
+ model page for BRIA's current commercial licensing information.
16
+
17
+ ## Changes in This Distribution
18
+
19
+ Eligible attention and MLP matrix weights were repacked for direct MLX affine
20
+ 8-bit execution with group size 64. Other weights remain in their source
21
+ precision. The derivative preserves the original logical tensor names through
22
+ checkpoint metadata and is distributed as part of the TRELLIS.2 MLX 8-bit
23
+ runtime bundle.
24
+
25
+ No endorsement by BRIA AI is implied. This notice summarizes the source,
26
+ attribution, and changes; the linked CC BY-NC 4.0 terms remain controlling.
LICENSE_TRELLIS2 ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) Microsoft Corporation.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md ADDED
@@ -0,0 +1,275 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: other
3
+ license_name: trellis2-dinov3-rmbg-multiple-licenses
4
+ license_link: https://huggingface.co/appautomaton/trellis2-mlx-8bit/blob/main/LICENSES.md
5
+ library_name: mlx
6
+ pipeline_tag: image-to-3d
7
+ base_model:
8
+ - microsoft/TRELLIS.2-4B
9
+ - facebook/dinov3-vitl16-pretrain-lvd1689m
10
+ - briaai/RMBG-2.0
11
+ base_model_relation: quantized
12
+ language:
13
+ - en
14
+ tags:
15
+ - mlx
16
+ - apple-silicon
17
+ - safetensors
18
+ - trellis2
19
+ - o-voxel
20
+ - image-to-3d
21
+ - mesh-generation
22
+ - pbr
23
+ - glb
24
+ - 8-bit
25
+ - affine-quantization
26
+ - mixed-precision
27
+ - non-commercial
28
+ ---
29
+
30
+ # TRELLIS.2 MLX 8-bit Affine for `mlx-spatial`
31
+
32
+ <p align="center">
33
+ <a href="https://appautomaton.github.io"><img alt="App Automaton project" src="https://img.shields.io/badge/App_Automaton-Project-5B5BD6?style=for-the-badge"></a>
34
+ <a href="https://github.com/appautomaton/mlx-spatial"><img alt="GitHub — appautomaton/mlx-spatial" src="https://img.shields.io/badge/GitHub-mlx--spatial-181717?style=for-the-badge&amp;logo=github&amp;logoColor=white"></a>
35
+ <a href="https://appautomaton.renocrypt.com/mlx-spatial/"><img alt="mlx-spatial documentation" src="https://img.shields.io/badge/Documentation-mlx--spatial-0A7BBB?style=for-the-badge&amp;logo=readthedocs&amp;logoColor=white"></a>
36
+ <a href="https://pypi.org/project/mlx-spatial/"><img alt="mlx-spatial on PyPI" src="https://img.shields.io/pypi/v/mlx-spatial?style=for-the-badge&amp;logo=pypi&amp;logoColor=white&amp;label=PyPI"></a>
37
+ </p>
38
+
39
+ <p align="center">
40
+ <a href="https://huggingface.co/appautomaton/trellis2-mlx-8bit"><img alt="TRELLIS.2 MLX 8-bit" src="https://img.shields.io/badge/Hugging_Face-MLX_8--bit-FF9D00?style=for-the-badge&amp;logo=huggingface&amp;logoColor=000"></a>
41
+ </p>
42
+
43
+ A self-contained TRELLIS.2 image-to-3D bundle with selective 8-bit affine
44
+ weights for direct execution by
45
+ [`mlx-spatial`](https://github.com/appautomaton/mlx-spatial) on Apple Silicon.
46
+ The bundle includes the TRELLIS.2 checkpoints, DINOv3 image conditioner, and
47
+ RMBG-2.0 foreground extractor required by the local inference pipeline.
48
+
49
+ Large transformer and block-internal MLP matrices execute through MLX's packed
50
+ quantized matrix multiplication. Convolutions and accuracy-sensitive boundary
51
+ tensors remain in their source precision.
52
+
53
+ > This is an unofficial quantized derivative. It is not a Microsoft, Meta, or
54
+ > BRIA release. Because the bundle contains RMBG-2.0, it is restricted to
55
+ > non-commercial use unless the user obtains separate commercial rights from
56
+ > BRIA.
57
+
58
+ ## Variants
59
+
60
+ | Variant | Precision | Complete bundle size | Model |
61
+ | --- | --- | ---: | --- |
62
+ | Source dependency set | BF16, FP16, and FP32 | 18.483 GB | TRELLIS.2-4B + DINOv3 ViT-L/16 + RMBG-2.0 |
63
+ | MLX 8-bit bundle | Selective affine INT8 with retained BF16, FP16, and FP32 | 11.248 GB | **This model** |
64
+
65
+ The complete 8-bit bundle is 39.1% smaller and does not require duplicate
66
+ full-precision checkpoints. Both forms expose the same 5,587 logical tensors
67
+ with identical names, shapes, and declared source dtypes.
68
+
69
+ ## Compatibility
70
+
71
+ This format requires an `mlx-spatial` build that includes TRELLIS.2 affine
72
+ checkpoint support. Until that support is available in a tagged PyPI release,
73
+ install the current project revision:
74
+
75
+ ```bash
76
+ pip install \
77
+ "mlx-spatial @ git+https://github.com/appautomaton/mlx-spatial.git@main"
78
+ ```
79
+
80
+ The runtime targets Apple Silicon, Python 3.13, and MLX `0.32.x`. It does not
81
+ use Torch, CUDA, or a dequantized full-precision checkpoint.
82
+
83
+ ## Use
84
+
85
+ Download the complete bundle:
86
+
87
+ ```bash
88
+ hf download appautomaton/trellis2-mlx-8bit \
89
+ --local-dir weights/trellis2-mlx-8bit
90
+ ```
91
+
92
+ Validate its three runtime roots:
93
+
94
+ ```bash
95
+ mlx-spatial-trellis2 validate \
96
+ --root weights/trellis2-mlx-8bit
97
+
98
+ mlx-spatial-trellis2 dinov3-validate \
99
+ --root weights/trellis2-mlx-8bit/dinov3
100
+
101
+ mlx-spatial-trellis2 rmbg-validate \
102
+ --root weights/trellis2-mlx-8bit/rmbg
103
+ ```
104
+
105
+ Generate a textured GLB:
106
+
107
+ ```bash
108
+ mlx-spatial-trellis2 generate-textured \
109
+ weights/trellis2-mlx-8bit \
110
+ inputs/trellis2/object.png \
111
+ --dino-root weights/trellis2-mlx-8bit/dinov3 \
112
+ --rmbg-root weights/trellis2-mlx-8bit/rmbg \
113
+ --output outputs/trellis2/object-8bit/model.glb \
114
+ --pipeline-type 1024_cascade \
115
+ --seed 42
116
+ ```
117
+
118
+ `1024_cascade` is the recommended quality tier; use `512` when lower memory
119
+ use or faster iteration matters more.
120
+
121
+ Do not pass `--slat-steps` for a quality run; the model configuration uses 12
122
+ steps. `--slat-steps 1` is intended only for a quick runtime smoke test.
123
+
124
+ RGBA inputs use their alpha channel directly. RGB inputs are passed through
125
+ the bundled RMBG-2.0 model. A clean single-object foreground and an uncropped
126
+ silhouette generally produce the most useful reconstruction.
127
+
128
+ ## Bundle
129
+
130
+ | Component | Logical tensors | INT8 matrices | Safetensors bytes |
131
+ | --- | ---: | ---: | ---: |
132
+ | TRELLIS.2 flow, VAE, and decoder checkpoints | 4,418 | 1,306 | 10,560,255,296 |
133
+ | `dinov3/model.safetensors` | 415 | 144 | 344,386,453 |
134
+ | `rmbg/model.safetensors` | 754 | 96 | 343,122,500 |
135
+ | **Total** | **5,587** | **1,546** | **11,247,764,249** |
136
+
137
+ Configuration, model card, license, and RMBG support files account for the
138
+ small difference between checkpoint bytes and the complete directory size.
139
+
140
+ The repository preserves the TRELLIS.2 checkpoint names and layout used by the
141
+ source model. DINOv3 and RMBG-2.0 are bundled under `dinov3/` and `rmbg/` so a
142
+ single download contains every runtime weight.
143
+
144
+ ## Quantization
145
+
146
+ The quantization scheme is affine 8-bit with group size 64. Packed weights are
147
+ stored as `uint32` with FP32 scales and biases, then executed directly through
148
+ `mx.quantized_matmul`.
149
+
150
+ The following block-internal two-dimensional weights are quantized:
151
+
152
+ - self-attention QKV and output projections in all five TRELLIS.2 flow DiTs;
153
+ - cross-attention query, key/value, and output projections in those DiTs;
154
+ - DiT MLP input and output matrices;
155
+ - internal ConvNeXt MLP matrices in the shape and texture encoders and
156
+ decoders;
157
+ - DINOv3 attention Q/K/V/output and MLP up/down projections;
158
+ - RMBG-2.0 Swin attention QKV/output and MLP FC matrices.
159
+
160
+ The following tensors remain in their source precision:
161
+
162
+ - all dense and sparse convolutions, including the sparse-structure decoder;
163
+ - input, output, patch, latent, subdivision, and final prediction boundaries;
164
+ - timestep and condition projections, embeddings, learned tokens, and
165
+ positional tensors;
166
+ - normalization parameters, RMSNorm parameters, modulation tensors, and
167
+ biases;
168
+ - RMBG stage-transition reductions;
169
+ - matrices whose input dimension is incompatible with group size 64.
170
+
171
+ Physical packed arrays use internal qweight, scale, and bias suffixes. The
172
+ runtime reconstructs the original logical names from safetensors metadata, so
173
+ the existing TRELLIS.2 pipeline and configuration continue to use the same
174
+ checkpoint contract. Format details are embedded under
175
+ `mlx_spatial.trellis2.quantization`.
176
+
177
+ ## Reproducing the Bundle
178
+
179
+ Starting from the three source weight roots:
180
+
181
+ ```bash
182
+ mlx-spatial-trellis2-quantize \
183
+ weights/trellis2 \
184
+ weights/trellis2-mlx-8bit \
185
+ --dinov3-root weights/dinov3-vitl16-pretrain-lvd1689m \
186
+ --rmbg-root weights/rmbg2 \
187
+ --bits 8 \
188
+ --group-size 64
189
+ ```
190
+
191
+ The command creates a complete runtime root. Do not add full-precision copies
192
+ of the quantized checkpoints to the 8-bit repository.
193
+
194
+ ## Verification
195
+
196
+ - Logical checkpoint inspection matched all 5,587 source tensor names,
197
+ shapes, and dtypes exactly.
198
+ - The quantization inventory contains 1,546 packed matrices: 1,050 DiT
199
+ matrices, 256 encoder/decoder MLP matrices, 144 DINOv3 matrices, and 96
200
+ RMBG-2.0 matrices.
201
+ - The complete `mlx-spatial` repository suite passed 1,175 tests; 10 tests
202
+ were skipped, 50 were deselected, and 3 expected failures remained.
203
+ - A 512-resolution, 12-step run completed background handling, DINOv3
204
+ conditioning, sparse-structure sampling, shape and texture SLat sampling,
205
+ both decoders, and textured GLB export with no blocker.
206
+ - That run produced 4,022 shape tokens, 1,041,541 decoded shape/texture points,
207
+ and a 12,083,344-byte GLB. The rendered asset retained coherent geometry and
208
+ recognizable appearance.
209
+ - The same run completed in 152.23 seconds, observed 3.516 GB peak MLX
210
+ allocator use, and recorded zero swap growth.
211
+ - A separate `1024_cascade`, 12-step run completed the same end-to-end path
212
+ and produced a Blender-readable 12,670,448-byte GLB with 199,884 faces and
213
+ embedded 1024 x 1024 PBR textures.
214
+
215
+ The 512 runtime and memory figures are one local Apple Silicon observation,
216
+ not a general benchmark. The `1024_cascade` run overlapped another MLX workload,
217
+ so it establishes compatibility and artifact health rather than performance.
218
+ Neither run is a formal claim of visual equivalence to the source weights.
219
+
220
+ ## Limitations
221
+
222
+ - Quantization changes the sampling trajectory. Geometry, pose, topology,
223
+ texture placement, material values, and unseen surfaces can differ from the
224
+ source-precision model even with the same seed.
225
+ - End-to-end validation covers `512` and `1024_cascade`. The standalone `1024`
226
+ and `1536_cascade` routes have not received an equivalent quality evaluation.
227
+ - Single-view reconstruction cannot determine unseen geometry with certainty.
228
+ - Fine detail depends on foreground extraction, cropping, occlusion,
229
+ reflections, transparency, and thin structures.
230
+ - Generated meshes can contain small holes, non-manifold regions, or other
231
+ topology requiring downstream cleanup.
232
+ - The packed checkpoint format requires `mlx-spatial`; generic safetensors
233
+ readers expose the physical packed arrays rather than the logical matrices.
234
+ - This bundle supports inference, not training or fine-tuning.
235
+ - Commercial use of the bundled RMBG-2.0 weights requires separate rights
236
+ from BRIA.
237
+
238
+ ## License and Attribution
239
+
240
+ This is a combined derivative; no single permissive license covers every
241
+ included component. Read [`LICENSES.md`](LICENSES.md) and all referenced terms
242
+ before downloading, using, or redistributing the bundle.
243
+
244
+ - Microsoft TRELLIS.2 files are provided under the MIT License. A copy is
245
+ included as [`LICENSE_TRELLIS2`](LICENSE_TRELLIS2).
246
+ - Meta DINOv3 files and derivatives are governed by the DINOv3 License. The
247
+ complete agreement is included as
248
+ [`LICENSE_DINOV3.md`](LICENSE_DINOV3.md), as required for redistribution.
249
+ - BRIA RMBG-2.0 is provided for non-commercial use under CC BY-NC 4.0. Its
250
+ attribution and change notice are included in
251
+ [`LICENSE_RMBG2.md`](LICENSE_RMBG2.md). Commercial use requires separate
252
+ authorization from BRIA.
253
+
254
+ The combined bundle must therefore be treated as non-commercial unless the
255
+ user has obtained all additional rights that their use requires. This
256
+ repository is not affiliated with or endorsed by Microsoft, Meta, BRIA, or the
257
+ original authors.
258
+
259
+ ## Links
260
+
261
+ - [App Automaton](https://appautomaton.github.io)
262
+ - [AppAutomaton models on Hugging Face](https://huggingface.co/appautomaton)
263
+ - [`appautomaton/mlx-spatial`](https://github.com/appautomaton/mlx-spatial) — MLX-native 3D and spatial inference for Apple Silicon.
264
+ - [`mlx-spatial` documentation](https://appautomaton.renocrypt.com/mlx-spatial/)
265
+ - [`mlx-spatial` on PyPI](https://pypi.org/project/mlx-spatial/)
266
+ - [TRELLIS.2 guide](https://github.com/appautomaton/mlx-spatial/blob/main/docs/trellis2.md)
267
+ - [TRELLIS.2 MLX 8-bit model](https://huggingface.co/appautomaton/trellis2-mlx-8bit)
268
+ - [Microsoft TRELLIS.2-4B model](https://huggingface.co/microsoft/TRELLIS.2-4B)
269
+ - [Microsoft TRELLIS.2 source](https://github.com/microsoft/TRELLIS.2)
270
+ - [TRELLIS.2 project page](https://microsoft.github.io/TRELLIS.2/)
271
+ - [Meta DINOv3 ViT-L/16 model](https://huggingface.co/facebook/dinov3-vitl16-pretrain-lvd1689m)
272
+ - [Meta DINOv3 source](https://github.com/facebookresearch/dinov3)
273
+ - [BRIA RMBG-2.0 model](https://huggingface.co/briaai/RMBG-2.0)
274
+ - [BRIA RMBG-2.0 source](https://github.com/Bria-AI/RMBG-2.0)
275
+ - [MLX](https://github.com/ml-explore/mlx)
ckpts/shape_dec_next_dc_f16c32_fp16.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "FlexiDualGridVaeDecoder",
3
+ "args": {
4
+ "resolution": 256,
5
+ "model_channels": [1024, 512, 256, 128, 64],
6
+ "latent_channels": 32,
7
+ "num_blocks": [4, 16, 8, 4, 0],
8
+ "block_type": [
9
+ "SparseConvNeXtBlock3d",
10
+ "SparseConvNeXtBlock3d",
11
+ "SparseConvNeXtBlock3d",
12
+ "SparseConvNeXtBlock3d",
13
+ "SparseConvNeXtBlock3d"
14
+ ],
15
+ "up_block_type": [
16
+ "SparseResBlockC2S3d",
17
+ "SparseResBlockC2S3d",
18
+ "SparseResBlockC2S3d",
19
+ "SparseResBlockC2S3d"
20
+ ],
21
+ "block_args": [{}, {}, {}, {}, {}],
22
+ "use_fp16": true
23
+ }
24
+ }
ckpts/shape_dec_next_dc_f16c32_fp16.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1819be8e9c3a10fe47dcddfc69b59e452dea8fd14a1eb4965f916765f58baf7d
3
+ size 885660861
ckpts/shape_enc_next_dc_f16c32_fp16.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "FlexiDualGridVaeEncoder",
3
+ "args": {
4
+ "model_channels": [64, 128, 256, 512, 1024],
5
+ "latent_channels": 32,
6
+ "num_blocks": [0, 4, 8, 16, 4],
7
+ "block_type": [
8
+ "SparseConvNeXtBlock3d",
9
+ "SparseConvNeXtBlock3d",
10
+ "SparseConvNeXtBlock3d",
11
+ "SparseConvNeXtBlock3d",
12
+ "SparseConvNeXtBlock3d"
13
+ ],
14
+ "down_block_type": [
15
+ "SparseResBlockS2C3d",
16
+ "SparseResBlockS2C3d",
17
+ "SparseResBlockS2C3d",
18
+ "SparseResBlockS2C3d"
19
+ ],
20
+ "block_args": [{}, {}, {}, {}, {}],
21
+ "use_fp16": true
22
+ }
23
+ }
ckpts/shape_enc_next_dc_f16c32_fp16.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0d2f0fea6943ba40784b5c98707acdd302ac517b39b07e2188569a15621c9f49
3
+ size 645968221
ckpts/slat_flow_img2shape_dit_1_3B_1024_bf16.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "SLatFlowModel",
3
+ "args": {
4
+ "resolution": 64,
5
+ "in_channels": 32,
6
+ "out_channels": 32,
7
+ "model_channels": 1536,
8
+ "cond_channels": 1024,
9
+ "num_blocks": 30,
10
+ "num_heads": 12,
11
+ "mlp_ratio": 5.3334,
12
+ "pe_mode": "rope",
13
+ "share_mod": true,
14
+ "initialization": "scaled",
15
+ "qk_rms_norm": true,
16
+ "qk_rms_norm_cross": true,
17
+ "dtype": "bfloat16"
18
+ }
19
+ }
ckpts/slat_flow_img2shape_dit_1_3B_1024_bf16.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5a526ba4647590900d63098069f49051ebf9f959edacfd249da27a46e79afdc1
3
+ size 1469877546
ckpts/slat_flow_img2shape_dit_1_3B_512_bf16.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "SLatFlowModel",
3
+ "args": {
4
+ "resolution": 32,
5
+ "in_channels": 32,
6
+ "out_channels": 32,
7
+ "model_channels": 1536,
8
+ "cond_channels": 1024,
9
+ "num_blocks": 30,
10
+ "num_heads": 12,
11
+ "mlp_ratio": 5.3334,
12
+ "pe_mode": "rope",
13
+ "share_mod": true,
14
+ "initialization": "scaled",
15
+ "qk_rms_norm": true,
16
+ "qk_rms_norm_cross": true,
17
+ "dtype": "bfloat16"
18
+ }
19
+ }
ckpts/slat_flow_img2shape_dit_1_3B_512_bf16.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3408d77de33125a65e8ee5bfdc30c3970abcd4125afb627d70750d27c90b5a3b
3
+ size 1469877545
ckpts/slat_flow_imgshape2tex_dit_1_3B_1024_bf16.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "SLatFlowModel",
3
+ "args": {
4
+ "resolution": 64,
5
+ "in_channels": 64,
6
+ "out_channels": 32,
7
+ "model_channels": 1536,
8
+ "cond_channels": 1024,
9
+ "num_blocks": 30,
10
+ "num_heads": 12,
11
+ "mlp_ratio": 5.3334,
12
+ "pe_mode": "rope",
13
+ "share_mod": true,
14
+ "initialization": "scaled",
15
+ "qk_rms_norm": true,
16
+ "qk_rms_norm_cross": true,
17
+ "dtype": "bfloat16"
18
+ }
19
+ }
ckpts/slat_flow_imgshape2tex_dit_1_3B_1024_bf16.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8f248f026d586ebd122457451b683ea05df9793419bd283601a7ee28ed536bb6
3
+ size 1469975853
ckpts/slat_flow_imgshape2tex_dit_1_3B_512_bf16.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "SLatFlowModel",
3
+ "args": {
4
+ "resolution": 32,
5
+ "in_channels": 64,
6
+ "out_channels": 32,
7
+ "model_channels": 1536,
8
+ "cond_channels": 1024,
9
+ "num_blocks": 30,
10
+ "num_heads": 12,
11
+ "mlp_ratio": 5.3334,
12
+ "pe_mode": "rope",
13
+ "share_mod": true,
14
+ "initialization": "scaled",
15
+ "qk_rms_norm": true,
16
+ "qk_rms_norm_cross": true,
17
+ "dtype": "bfloat16"
18
+ }
19
+ }
ckpts/slat_flow_imgshape2tex_dit_1_3B_512_bf16.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e606bca060e1b9921e87612ac4e0d9d8b91ae143bba8ada910abba06d9ec0590
3
+ size 1469975852
ckpts/ss_flow_img_dit_1_3B_64_bf16.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "SparseStructureFlowModel",
3
+ "args": {
4
+ "resolution": 16,
5
+ "in_channels": 8,
6
+ "out_channels": 8,
7
+ "model_channels": 1536,
8
+ "cond_channels": 1024,
9
+ "num_blocks": 30,
10
+ "num_heads": 12,
11
+ "mlp_ratio": 5.3334,
12
+ "pe_mode": "rope",
13
+ "share_mod": true,
14
+ "initialization": "scaled",
15
+ "qk_rms_norm": true,
16
+ "qk_rms_norm_cross": true,
17
+ "dtype": "bfloat16"
18
+ }
19
+ }
ckpts/ss_flow_img_dit_1_3B_64_bf16.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9c6f6875470b50f1ff954c837640120ab9ea889ebd6a1d559cf5601ef0d141ee
3
+ size 1469730029
ckpts/tex_dec_next_dc_f16c32_fp16.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "SparseUnetVaeDecoder",
3
+ "args": {
4
+ "out_channels": 6,
5
+ "model_channels": [1024, 512, 256, 128, 64],
6
+ "latent_channels": 32,
7
+ "num_blocks": [4, 16, 8, 4, 0],
8
+ "block_type": [
9
+ "SparseConvNeXtBlock3d",
10
+ "SparseConvNeXtBlock3d",
11
+ "SparseConvNeXtBlock3d",
12
+ "SparseConvNeXtBlock3d",
13
+ "SparseConvNeXtBlock3d"
14
+ ],
15
+ "up_block_type": [
16
+ "SparseResBlockC2S3d",
17
+ "SparseResBlockC2S3d",
18
+ "SparseResBlockC2S3d",
19
+ "SparseResBlockC2S3d"
20
+ ],
21
+ "block_args": [{}, {}, {}, {}, {}],
22
+ "pred_subdiv": false,
23
+ "use_fp16": true
24
+ }
25
+ }
ckpts/tex_dec_next_dc_f16c32_fp16.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f176da4cf6724e47f723a8b5abca455db9e9caba815b163f47676228a1ae5970
3
+ size 885629198
ckpts/tex_enc_next_dc_f16c32_fp16.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "SparseUnetVaeEncoder",
3
+ "args": {
4
+ "in_channels": 6,
5
+ "model_channels": [64, 128, 256, 512, 1024],
6
+ "latent_channels": 32,
7
+ "num_blocks": [0, 4, 8, 16, 4],
8
+ "block_type": [
9
+ "SparseConvNeXtBlock3d",
10
+ "SparseConvNeXtBlock3d",
11
+ "SparseConvNeXtBlock3d",
12
+ "SparseConvNeXtBlock3d",
13
+ "SparseConvNeXtBlock3d"
14
+ ],
15
+ "down_block_type": [
16
+ "SparseResBlockS2C3d",
17
+ "SparseResBlockS2C3d",
18
+ "SparseResBlockS2C3d",
19
+ "SparseResBlockS2C3d"
20
+ ],
21
+ "block_args": [{}, {}, {}, {}, {}],
22
+ "use_fp16": true
23
+ }
24
+ }
ckpts/tex_enc_next_dc_f16c32_fp16.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:dc3fdb644825c6a3fde2154e1dcb43503e71d83c36a79a6b2998ce388e3f5df7
3
+ size 645968219
dinov3/config.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "DINOv3ViTModel"
4
+ ],
5
+ "attention_dropout": 0.0,
6
+ "drop_path_rate": 0.0,
7
+ "hidden_act": "gelu",
8
+ "hidden_size": 1024,
9
+ "image_size": 224,
10
+ "initializer_range": 0.02,
11
+ "intermediate_size": 4096,
12
+ "key_bias": false,
13
+ "layer_norm_eps": 1e-05,
14
+ "layerscale_value": 1.0,
15
+ "mlp_bias": true,
16
+ "model_type": "dinov3_vit",
17
+ "num_attention_heads": 16,
18
+ "num_channels": 3,
19
+ "num_hidden_layers": 24,
20
+ "num_register_tokens": 4,
21
+ "patch_size": 16,
22
+ "pos_embed_jitter": null,
23
+ "pos_embed_rescale": 2.0,
24
+ "pos_embed_shift": null,
25
+ "proj_bias": true,
26
+ "query_bias": true,
27
+ "rope_theta": 100.0,
28
+ "torch_dtype": "float32",
29
+ "transformers_version": "4.56.0.dev0",
30
+ "use_gated_mlp": false,
31
+ "value_bias": true
32
+ }
dinov3/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3237601868b352884c651200bf85c93a761618739b8738c177ec68886744120a
3
+ size 344386453
microsoft/TRELLIS-image-large/ckpts/ss_dec_conv3d_16l8_fp16.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ {
3
+ "name": "SparseStructureDecoder",
4
+ "args": {
5
+ "out_channels": 1,
6
+ "latent_channels": 8,
7
+ "num_res_blocks": 2,
8
+ "num_res_blocks_middle": 2,
9
+ "channels": [512, 128, 32],
10
+ "use_fp16": true
11
+ }
12
+ }
microsoft/TRELLIS-image-large/ckpts/ss_dec_conv3d_16l8_fp16.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1c76d4a40519aa2d711cc263a8404105231ac26db31d946bed48b84fee79009a
3
+ size 147591972
pipeline.json ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "Trellis2ImageTo3DPipeline",
3
+ "args": {
4
+ "models": {
5
+ "sparse_structure_decoder": "microsoft/TRELLIS-image-large/ckpts/ss_dec_conv3d_16l8_fp16",
6
+ "sparse_structure_flow_model": "ckpts/ss_flow_img_dit_1_3B_64_bf16",
7
+ "shape_slat_decoder": "ckpts/shape_dec_next_dc_f16c32_fp16",
8
+ "shape_slat_flow_model_512": "ckpts/slat_flow_img2shape_dit_1_3B_512_bf16",
9
+ "shape_slat_flow_model_1024": "ckpts/slat_flow_img2shape_dit_1_3B_1024_bf16",
10
+ "tex_slat_decoder": "ckpts/tex_dec_next_dc_f16c32_fp16",
11
+ "tex_slat_flow_model_512": "ckpts/slat_flow_imgshape2tex_dit_1_3B_512_bf16",
12
+ "tex_slat_flow_model_1024": "ckpts/slat_flow_imgshape2tex_dit_1_3B_1024_bf16"
13
+ },
14
+ "sparse_structure_sampler": {
15
+ "name": "FlowEulerGuidanceIntervalSampler",
16
+ "args": {
17
+ "sigma_min": 1e-5
18
+ },
19
+ "params": {
20
+ "steps": 12,
21
+ "guidance_strength": 7.5,
22
+ "guidance_rescale": 0.7,
23
+ "guidance_interval": [0.6, 1.0],
24
+ "rescale_t": 5.0
25
+ }
26
+ },
27
+ "shape_slat_sampler": {
28
+ "name": "FlowEulerGuidanceIntervalSampler",
29
+ "args": {
30
+ "sigma_min": 1e-5
31
+ },
32
+ "params": {
33
+ "steps": 12,
34
+ "guidance_strength": 7.5,
35
+ "guidance_rescale": 0.5,
36
+ "guidance_interval": [0.6, 1.0],
37
+ "rescale_t": 3.0
38
+ }
39
+ },
40
+ "shape_slat_normalization": {
41
+ "mean": [
42
+ 0.781296, 0.018091, -0.495192, -0.558457, 1.060530, 0.093252, 1.518149, -0.933218,
43
+ -0.732996, 2.604095, -0.118341, -2.143904, 0.495076, -2.179512, -2.130751, -0.996944,
44
+ 0.261421, -2.217463, 1.260067, -0.150213, 3.790713, 1.481266, -1.046058, -1.523667,
45
+ -0.059621, 2.220780, 1.621212, 0.877230, 0.567247, -3.175944, -3.186688, 1.578665
46
+ ],
47
+ "std": [
48
+ 5.972266, 4.706852, 5.445010, 5.209927, 5.320220, 4.547237, 5.020802, 5.444004,
49
+ 5.226681, 5.683095, 4.831436, 5.286469, 5.652043, 5.367606, 5.525084, 4.730578,
50
+ 4.805265, 5.124013, 5.530808, 5.619001, 5.103930, 5.417670, 5.269677, 5.547194,
51
+ 5.634698, 5.235274, 6.110351, 5.511298, 6.237273, 4.879207, 5.347008, 5.405691
52
+ ]
53
+ },
54
+ "tex_slat_sampler": {
55
+ "name": "FlowEulerGuidanceIntervalSampler",
56
+ "args": {
57
+ "sigma_min": 1e-5
58
+ },
59
+ "params": {
60
+ "steps": 12,
61
+ "guidance_strength": 1.0,
62
+ "guidance_rescale": 0.0,
63
+ "guidance_interval": [0.6, 0.9],
64
+ "rescale_t": 3.0
65
+ }
66
+ },
67
+ "tex_slat_normalization": {
68
+ "mean": [
69
+ 3.501659, 2.212398, 2.226094, 0.251093, -0.026248, -0.687364, 0.439898, -0.928075,
70
+ 0.029398, -0.339596, -0.869527, 1.038479, -0.972385, 0.126042, -1.129303, 0.455149,
71
+ -1.209521, 2.069067, 0.544735, 2.569128, -0.323407, 2.293000, -1.925608, -1.217717,
72
+ 1.213905, 0.971588, -0.023631, 0.106750, 2.021786, 0.250524, -0.662387, -0.768862
73
+ ],
74
+ "std": [
75
+ 2.665652, 2.743913, 2.765121, 2.595319, 3.037293, 2.291316, 2.144656, 2.911822,
76
+ 2.969419, 2.501689, 2.154811, 3.163343, 2.621215, 2.381943, 3.186697, 3.021588,
77
+ 2.295916, 3.234985, 3.233086, 2.260140, 2.874801, 2.810596, 3.292720, 2.674999,
78
+ 2.680878, 2.372054, 2.451546, 2.353556, 2.995195, 2.379849, 2.786195, 2.775190
79
+ ]
80
+ },
81
+ "image_cond_model": {
82
+ "name": "DinoV3FeatureExtractor",
83
+ "args": {
84
+ "model_name": "facebook/dinov3-vitl16-pretrain-lvd1689m"
85
+ }
86
+ },
87
+ "rembg_model": {
88
+ "name": "BiRefNet",
89
+ "args": {
90
+ "model_name": "briaai/RMBG-2.0"
91
+ }
92
+ },
93
+ "default_pipeline_type": "1024_cascade"
94
+ }
95
+ }
rmbg/BiRefNet_config.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import PretrainedConfig
2
+
3
+ class BiRefNetConfig(PretrainedConfig):
4
+ model_type = "SegformerForSemanticSegmentation"
5
+ def __init__(
6
+ self,
7
+ bb_pretrained=False,
8
+ **kwargs
9
+ ):
10
+ self.bb_pretrained = bb_pretrained
11
+ super().__init__(**kwargs)
rmbg/birefnet.py ADDED
@@ -0,0 +1,2248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### config.py
2
+
3
+ import os
4
+ import math
5
+ from transformers import PretrainedConfig
6
+
7
+ class Config(PretrainedConfig):
8
+ def __init__(self) -> None:
9
+ super().__init__()
10
+ # PATH settings
11
+ self.sys_home_dir = os.path.expanduser('~') # Make up your file system as: SYS_HOME_DIR/codes/dis/BiRefNet, SYS_HOME_DIR/datasets/dis/xx, SYS_HOME_DIR/weights/xx
12
+
13
+ # TASK settings
14
+ self.task = ['DIS5K', 'COD', 'HRSOD', 'DIS5K+HRSOD+HRS10K', 'P3M-10k'][0]
15
+ self.training_set = {
16
+ 'DIS5K': ['DIS-TR', 'DIS-TR+DIS-TE1+DIS-TE2+DIS-TE3+DIS-TE4'][0],
17
+ 'COD': 'TR-COD10K+TR-CAMO',
18
+ 'HRSOD': ['TR-DUTS', 'TR-HRSOD', 'TR-UHRSD', 'TR-DUTS+TR-HRSOD', 'TR-DUTS+TR-UHRSD', 'TR-HRSOD+TR-UHRSD', 'TR-DUTS+TR-HRSOD+TR-UHRSD'][5],
19
+ 'DIS5K+HRSOD+HRS10K': 'DIS-TE1+DIS-TE2+DIS-TE3+DIS-TE4+DIS-TR+TE-HRS10K+TE-HRSOD+TE-UHRSD+TR-HRS10K+TR-HRSOD+TR-UHRSD', # leave DIS-VD for evaluation.
20
+ 'P3M-10k': 'TR-P3M-10k',
21
+ }[self.task]
22
+ self.prompt4loc = ['dense', 'sparse'][0]
23
+
24
+ # Faster-Training settings
25
+ self.load_all = True
26
+ self.compile = True # 1. Trigger CPU memory leak in some extend, which is an inherent problem of PyTorch.
27
+ # Machines with > 70GB CPU memory can run the whole training on DIS5K with default setting.
28
+ # 2. Higher PyTorch version may fix it: https://github.com/pytorch/pytorch/issues/119607.
29
+ # 3. But compile in Pytorch > 2.0.1 seems to bring no acceleration for training.
30
+ self.precisionHigh = True
31
+
32
+ # MODEL settings
33
+ self.ms_supervision = True
34
+ self.out_ref = self.ms_supervision and True
35
+ self.dec_ipt = True
36
+ self.dec_ipt_split = True
37
+ self.cxt_num = [0, 3][1] # multi-scale skip connections from encoder
38
+ self.mul_scl_ipt = ['', 'add', 'cat'][2]
39
+ self.dec_att = ['', 'ASPP', 'ASPPDeformable'][2]
40
+ self.squeeze_block = ['', 'BasicDecBlk_x1', 'ResBlk_x4', 'ASPP_x3', 'ASPPDeformable_x3'][1]
41
+ self.dec_blk = ['BasicDecBlk', 'ResBlk', 'HierarAttDecBlk'][0]
42
+
43
+ # TRAINING settings
44
+ self.batch_size = 4
45
+ self.IoU_finetune_last_epochs = [
46
+ 0,
47
+ {
48
+ 'DIS5K': -50,
49
+ 'COD': -20,
50
+ 'HRSOD': -20,
51
+ 'DIS5K+HRSOD+HRS10K': -20,
52
+ 'P3M-10k': -20,
53
+ }[self.task]
54
+ ][1] # choose 0 to skip
55
+ self.lr = (1e-4 if 'DIS5K' in self.task else 1e-5) * math.sqrt(self.batch_size / 4) # DIS needs high lr to converge faster. Adapt the lr linearly
56
+ self.size = 1024
57
+ self.num_workers = max(4, self.batch_size) # will be decrease to min(it, batch_size) at the initialization of the data_loader
58
+
59
+ # Backbone settings
60
+ self.bb = [
61
+ 'vgg16', 'vgg16bn', 'resnet50', # 0, 1, 2
62
+ 'swin_v1_t', 'swin_v1_s', # 3, 4
63
+ 'swin_v1_b', 'swin_v1_l', # 5-bs9, 6-bs4
64
+ 'pvt_v2_b0', 'pvt_v2_b1', # 7, 8
65
+ 'pvt_v2_b2', 'pvt_v2_b5', # 9-bs10, 10-bs5
66
+ ][6]
67
+ self.lateral_channels_in_collection = {
68
+ 'vgg16': [512, 256, 128, 64], 'vgg16bn': [512, 256, 128, 64], 'resnet50': [1024, 512, 256, 64],
69
+ 'pvt_v2_b2': [512, 320, 128, 64], 'pvt_v2_b5': [512, 320, 128, 64],
70
+ 'swin_v1_b': [1024, 512, 256, 128], 'swin_v1_l': [1536, 768, 384, 192],
71
+ 'swin_v1_t': [768, 384, 192, 96], 'swin_v1_s': [768, 384, 192, 96],
72
+ 'pvt_v2_b0': [256, 160, 64, 32], 'pvt_v2_b1': [512, 320, 128, 64],
73
+ }[self.bb]
74
+ if self.mul_scl_ipt == 'cat':
75
+ self.lateral_channels_in_collection = [channel * 2 for channel in self.lateral_channels_in_collection]
76
+ self.cxt = self.lateral_channels_in_collection[1:][::-1][-self.cxt_num:] if self.cxt_num else []
77
+
78
+ # MODEL settings - inactive
79
+ self.lat_blk = ['BasicLatBlk'][0]
80
+ self.dec_channels_inter = ['fixed', 'adap'][0]
81
+ self.refine = ['', 'itself', 'RefUNet', 'Refiner', 'RefinerPVTInChannels4'][0]
82
+ self.progressive_ref = self.refine and True
83
+ self.ender = self.progressive_ref and False
84
+ self.scale = self.progressive_ref and 2
85
+ self.auxiliary_classification = False # Only for DIS5K, where class labels are saved in `dataset.py`.
86
+ self.refine_iteration = 1
87
+ self.freeze_bb = False
88
+ self.model = [
89
+ 'BiRefNet',
90
+ ][0]
91
+ if self.dec_blk == 'HierarAttDecBlk':
92
+ self.batch_size = 2 ** [0, 1, 2, 3, 4][2]
93
+
94
+ # TRAINING settings - inactive
95
+ self.preproc_methods = ['flip', 'enhance', 'rotate', 'pepper', 'crop'][:4]
96
+ self.optimizer = ['Adam', 'AdamW'][1]
97
+ self.lr_decay_epochs = [1e5] # Set to negative N to decay the lr in the last N-th epoch.
98
+ self.lr_decay_rate = 0.5
99
+ # Loss
100
+ self.lambdas_pix_last = {
101
+ # not 0 means opening this loss
102
+ # original rate -- 1 : 30 : 1.5 : 0.2, bce x 30
103
+ 'bce': 30 * 1, # high performance
104
+ 'iou': 0.5 * 1, # 0 / 255
105
+ 'iou_patch': 0.5 * 0, # 0 / 255, win_size = (64, 64)
106
+ 'mse': 150 * 0, # can smooth the saliency map
107
+ 'triplet': 3 * 0,
108
+ 'reg': 100 * 0,
109
+ 'ssim': 10 * 1, # help contours,
110
+ 'cnt': 5 * 0, # help contours
111
+ 'structure': 5 * 0, # structure loss from codes of MVANet. A little improvement on DIS-TE[1,2,3], a bit more decrease on DIS-TE4.
112
+ }
113
+ self.lambdas_cls = {
114
+ 'ce': 5.0
115
+ }
116
+ # Adv
117
+ self.lambda_adv_g = 10. * 0 # turn to 0 to avoid adv training
118
+ self.lambda_adv_d = 3. * (self.lambda_adv_g > 0)
119
+
120
+ # PATH settings - inactive
121
+ self.data_root_dir = os.path.join(self.sys_home_dir, 'datasets/dis')
122
+ self.weights_root_dir = os.path.join(self.sys_home_dir, 'weights')
123
+ self.weights = {
124
+ 'pvt_v2_b2': os.path.join(self.weights_root_dir, 'pvt_v2_b2.pth'),
125
+ 'pvt_v2_b5': os.path.join(self.weights_root_dir, ['pvt_v2_b5.pth', 'pvt_v2_b5_22k.pth'][0]),
126
+ 'swin_v1_b': os.path.join(self.weights_root_dir, ['swin_base_patch4_window12_384_22kto1k.pth', 'swin_base_patch4_window12_384_22k.pth'][0]),
127
+ 'swin_v1_l': os.path.join(self.weights_root_dir, ['swin_large_patch4_window12_384_22kto1k.pth', 'swin_large_patch4_window12_384_22k.pth'][0]),
128
+ 'swin_v1_t': os.path.join(self.weights_root_dir, ['swin_tiny_patch4_window7_224_22kto1k_finetune.pth'][0]),
129
+ 'swin_v1_s': os.path.join(self.weights_root_dir, ['swin_small_patch4_window7_224_22kto1k_finetune.pth'][0]),
130
+ 'pvt_v2_b0': os.path.join(self.weights_root_dir, ['pvt_v2_b0.pth'][0]),
131
+ 'pvt_v2_b1': os.path.join(self.weights_root_dir, ['pvt_v2_b1.pth'][0]),
132
+ }
133
+
134
+ # Callbacks - inactive
135
+ self.verbose_eval = True
136
+ self.only_S_MAE = False
137
+ self.use_fp16 = False # Bugs. It may cause nan in training.
138
+ self.SDPA_enabled = False # Bugs. Slower and errors occur in multi-GPUs
139
+
140
+ # others
141
+ self.device = [0, 'cpu'][0] # .to(0) == .to('cuda:0')
142
+
143
+ self.batch_size_valid = 1
144
+ self.rand_seed = 7
145
+ # run_sh_file = [f for f in os.listdir('.') if 'train.sh' == f] + [os.path.join('..', f) for f in os.listdir('..') if 'train.sh' == f]
146
+ # with open(run_sh_file[0], 'r') as f:
147
+ # lines = f.readlines()
148
+ # self.save_last = int([l.strip() for l in lines if '"{}")'.format(self.task) in l and 'val_last=' in l][0].split('val_last=')[-1].split()[0])
149
+ # self.save_step = int([l.strip() for l in lines if '"{}")'.format(self.task) in l and 'step=' in l][0].split('step=')[-1].split()[0])
150
+ # self.val_step = [0, self.save_step][0]
151
+
152
+ def print_task(self) -> None:
153
+ # Return task for choosing settings in shell scripts.
154
+ print(self.task)
155
+
156
+
157
+
158
+ ### models/backbones/pvt_v2.py
159
+
160
+ import torch
161
+ import torch.nn as nn
162
+ from functools import partial
163
+
164
+ from timm.models.layers import DropPath, to_2tuple, trunc_normal_
165
+ from timm.models.registry import register_model
166
+
167
+ import math
168
+
169
+ # from config import Config
170
+
171
+ # config = Config()
172
+
173
+ class Mlp(nn.Module):
174
+ def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.):
175
+ super().__init__()
176
+ out_features = out_features or in_features
177
+ hidden_features = hidden_features or in_features
178
+ self.fc1 = nn.Linear(in_features, hidden_features)
179
+ self.dwconv = DWConv(hidden_features)
180
+ self.act = act_layer()
181
+ self.fc2 = nn.Linear(hidden_features, out_features)
182
+ self.drop = nn.Dropout(drop)
183
+
184
+ self.apply(self._init_weights)
185
+
186
+ def _init_weights(self, m):
187
+ if isinstance(m, nn.Linear):
188
+ trunc_normal_(m.weight, std=.02)
189
+ if isinstance(m, nn.Linear) and m.bias is not None:
190
+ nn.init.constant_(m.bias, 0)
191
+ elif isinstance(m, nn.LayerNorm):
192
+ nn.init.constant_(m.bias, 0)
193
+ nn.init.constant_(m.weight, 1.0)
194
+ elif isinstance(m, nn.Conv2d):
195
+ fan_out = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
196
+ fan_out //= m.groups
197
+ m.weight.data.normal_(0, math.sqrt(2.0 / fan_out))
198
+ if m.bias is not None:
199
+ m.bias.data.zero_()
200
+
201
+ def forward(self, x, H, W):
202
+ x = self.fc1(x)
203
+ x = self.dwconv(x, H, W)
204
+ x = self.act(x)
205
+ x = self.drop(x)
206
+ x = self.fc2(x)
207
+ x = self.drop(x)
208
+ return x
209
+
210
+
211
+ class Attention(nn.Module):
212
+ def __init__(self, dim, num_heads=8, qkv_bias=False, qk_scale=None, attn_drop=0., proj_drop=0., sr_ratio=1):
213
+ super().__init__()
214
+ assert dim % num_heads == 0, f"dim {dim} should be divided by num_heads {num_heads}."
215
+
216
+ self.dim = dim
217
+ self.num_heads = num_heads
218
+ head_dim = dim // num_heads
219
+ self.scale = qk_scale or head_dim ** -0.5
220
+
221
+ self.q = nn.Linear(dim, dim, bias=qkv_bias)
222
+ self.kv = nn.Linear(dim, dim * 2, bias=qkv_bias)
223
+ self.attn_drop_prob = attn_drop
224
+ self.attn_drop = nn.Dropout(attn_drop)
225
+ self.proj = nn.Linear(dim, dim)
226
+ self.proj_drop = nn.Dropout(proj_drop)
227
+
228
+ self.sr_ratio = sr_ratio
229
+ if sr_ratio > 1:
230
+ self.sr = nn.Conv2d(dim, dim, kernel_size=sr_ratio, stride=sr_ratio)
231
+ self.norm = nn.LayerNorm(dim)
232
+
233
+ self.apply(self._init_weights)
234
+
235
+ def _init_weights(self, m):
236
+ if isinstance(m, nn.Linear):
237
+ trunc_normal_(m.weight, std=.02)
238
+ if isinstance(m, nn.Linear) and m.bias is not None:
239
+ nn.init.constant_(m.bias, 0)
240
+ elif isinstance(m, nn.LayerNorm):
241
+ nn.init.constant_(m.bias, 0)
242
+ nn.init.constant_(m.weight, 1.0)
243
+ elif isinstance(m, nn.Conv2d):
244
+ fan_out = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
245
+ fan_out //= m.groups
246
+ m.weight.data.normal_(0, math.sqrt(2.0 / fan_out))
247
+ if m.bias is not None:
248
+ m.bias.data.zero_()
249
+
250
+ def forward(self, x, H, W):
251
+ B, N, C = x.shape
252
+ q = self.q(x).reshape(B, N, self.num_heads, C // self.num_heads).permute(0, 2, 1, 3)
253
+
254
+ if self.sr_ratio > 1:
255
+ x_ = x.permute(0, 2, 1).reshape(B, C, H, W)
256
+ x_ = self.sr(x_).reshape(B, C, -1).permute(0, 2, 1)
257
+ x_ = self.norm(x_)
258
+ kv = self.kv(x_).reshape(B, -1, 2, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
259
+ else:
260
+ kv = self.kv(x).reshape(B, -1, 2, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
261
+ k, v = kv[0], kv[1]
262
+
263
+ if config.SDPA_enabled:
264
+ x = torch.nn.functional.scaled_dot_product_attention(
265
+ q, k, v,
266
+ attn_mask=None, dropout_p=self.attn_drop_prob, is_causal=False
267
+ ).transpose(1, 2).reshape(B, N, C)
268
+ else:
269
+ attn = (q @ k.transpose(-2, -1)) * self.scale
270
+ attn = attn.softmax(dim=-1)
271
+ attn = self.attn_drop(attn)
272
+
273
+ x = (attn @ v).transpose(1, 2).reshape(B, N, C)
274
+ x = self.proj(x)
275
+ x = self.proj_drop(x)
276
+
277
+ return x
278
+
279
+
280
+ class Block(nn.Module):
281
+
282
+ def __init__(self, dim, num_heads, mlp_ratio=4., qkv_bias=False, qk_scale=None, drop=0., attn_drop=0.,
283
+ drop_path=0., act_layer=nn.GELU, norm_layer=nn.LayerNorm, sr_ratio=1):
284
+ super().__init__()
285
+ self.norm1 = norm_layer(dim)
286
+ self.attn = Attention(
287
+ dim,
288
+ num_heads=num_heads, qkv_bias=qkv_bias, qk_scale=qk_scale,
289
+ attn_drop=attn_drop, proj_drop=drop, sr_ratio=sr_ratio)
290
+ # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here
291
+ self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
292
+ self.norm2 = norm_layer(dim)
293
+ mlp_hidden_dim = int(dim * mlp_ratio)
294
+ self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)
295
+
296
+ self.apply(self._init_weights)
297
+
298
+ def _init_weights(self, m):
299
+ if isinstance(m, nn.Linear):
300
+ trunc_normal_(m.weight, std=.02)
301
+ if isinstance(m, nn.Linear) and m.bias is not None:
302
+ nn.init.constant_(m.bias, 0)
303
+ elif isinstance(m, nn.LayerNorm):
304
+ nn.init.constant_(m.bias, 0)
305
+ nn.init.constant_(m.weight, 1.0)
306
+ elif isinstance(m, nn.Conv2d):
307
+ fan_out = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
308
+ fan_out //= m.groups
309
+ m.weight.data.normal_(0, math.sqrt(2.0 / fan_out))
310
+ if m.bias is not None:
311
+ m.bias.data.zero_()
312
+
313
+ def forward(self, x, H, W):
314
+ x = x + self.drop_path(self.attn(self.norm1(x), H, W))
315
+ x = x + self.drop_path(self.mlp(self.norm2(x), H, W))
316
+
317
+ return x
318
+
319
+
320
+ class OverlapPatchEmbed(nn.Module):
321
+ """ Image to Patch Embedding
322
+ """
323
+
324
+ def __init__(self, img_size=224, patch_size=7, stride=4, in_channels=3, embed_dim=768):
325
+ super().__init__()
326
+ img_size = to_2tuple(img_size)
327
+ patch_size = to_2tuple(patch_size)
328
+
329
+ self.img_size = img_size
330
+ self.patch_size = patch_size
331
+ self.H, self.W = img_size[0] // patch_size[0], img_size[1] // patch_size[1]
332
+ self.num_patches = self.H * self.W
333
+ self.proj = nn.Conv2d(in_channels, embed_dim, kernel_size=patch_size, stride=stride,
334
+ padding=(patch_size[0] // 2, patch_size[1] // 2))
335
+ self.norm = nn.LayerNorm(embed_dim)
336
+
337
+ self.apply(self._init_weights)
338
+
339
+ def _init_weights(self, m):
340
+ if isinstance(m, nn.Linear):
341
+ trunc_normal_(m.weight, std=.02)
342
+ if isinstance(m, nn.Linear) and m.bias is not None:
343
+ nn.init.constant_(m.bias, 0)
344
+ elif isinstance(m, nn.LayerNorm):
345
+ nn.init.constant_(m.bias, 0)
346
+ nn.init.constant_(m.weight, 1.0)
347
+ elif isinstance(m, nn.Conv2d):
348
+ fan_out = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
349
+ fan_out //= m.groups
350
+ m.weight.data.normal_(0, math.sqrt(2.0 / fan_out))
351
+ if m.bias is not None:
352
+ m.bias.data.zero_()
353
+
354
+ def forward(self, x):
355
+ x = self.proj(x)
356
+ _, _, H, W = x.shape
357
+ x = x.flatten(2).transpose(1, 2)
358
+ x = self.norm(x)
359
+
360
+ return x, H, W
361
+
362
+
363
+ class PyramidVisionTransformerImpr(nn.Module):
364
+ def __init__(self, img_size=224, patch_size=16, in_channels=3, num_classes=1000, embed_dims=[64, 128, 256, 512],
365
+ num_heads=[1, 2, 4, 8], mlp_ratios=[4, 4, 4, 4], qkv_bias=False, qk_scale=None, drop_rate=0.,
366
+ attn_drop_rate=0., drop_path_rate=0., norm_layer=nn.LayerNorm,
367
+ depths=[3, 4, 6, 3], sr_ratios=[8, 4, 2, 1]):
368
+ super().__init__()
369
+ self.num_classes = num_classes
370
+ self.depths = depths
371
+
372
+ # patch_embed
373
+ self.patch_embed1 = OverlapPatchEmbed(img_size=img_size, patch_size=7, stride=4, in_channels=in_channels,
374
+ embed_dim=embed_dims[0])
375
+ self.patch_embed2 = OverlapPatchEmbed(img_size=img_size // 4, patch_size=3, stride=2, in_channels=embed_dims[0],
376
+ embed_dim=embed_dims[1])
377
+ self.patch_embed3 = OverlapPatchEmbed(img_size=img_size // 8, patch_size=3, stride=2, in_channels=embed_dims[1],
378
+ embed_dim=embed_dims[2])
379
+ self.patch_embed4 = OverlapPatchEmbed(img_size=img_size // 16, patch_size=3, stride=2, in_channels=embed_dims[2],
380
+ embed_dim=embed_dims[3])
381
+
382
+ # transformer encoder
383
+ dpr = np.linspace(0, drop_path_rate, sum(depths)).tolist() # stochastic depth decay rule
384
+ cur = 0
385
+ self.block1 = nn.ModuleList([Block(
386
+ dim=embed_dims[0], num_heads=num_heads[0], mlp_ratio=mlp_ratios[0], qkv_bias=qkv_bias, qk_scale=qk_scale,
387
+ drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[cur + i], norm_layer=norm_layer,
388
+ sr_ratio=sr_ratios[0])
389
+ for i in range(depths[0])])
390
+ self.norm1 = norm_layer(embed_dims[0])
391
+
392
+ cur += depths[0]
393
+ self.block2 = nn.ModuleList([Block(
394
+ dim=embed_dims[1], num_heads=num_heads[1], mlp_ratio=mlp_ratios[1], qkv_bias=qkv_bias, qk_scale=qk_scale,
395
+ drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[cur + i], norm_layer=norm_layer,
396
+ sr_ratio=sr_ratios[1])
397
+ for i in range(depths[1])])
398
+ self.norm2 = norm_layer(embed_dims[1])
399
+
400
+ cur += depths[1]
401
+ self.block3 = nn.ModuleList([Block(
402
+ dim=embed_dims[2], num_heads=num_heads[2], mlp_ratio=mlp_ratios[2], qkv_bias=qkv_bias, qk_scale=qk_scale,
403
+ drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[cur + i], norm_layer=norm_layer,
404
+ sr_ratio=sr_ratios[2])
405
+ for i in range(depths[2])])
406
+ self.norm3 = norm_layer(embed_dims[2])
407
+
408
+ cur += depths[2]
409
+ self.block4 = nn.ModuleList([Block(
410
+ dim=embed_dims[3], num_heads=num_heads[3], mlp_ratio=mlp_ratios[3], qkv_bias=qkv_bias, qk_scale=qk_scale,
411
+ drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[cur + i], norm_layer=norm_layer,
412
+ sr_ratio=sr_ratios[3])
413
+ for i in range(depths[3])])
414
+ self.norm4 = norm_layer(embed_dims[3])
415
+
416
+ # classification head
417
+ # self.head = nn.Linear(embed_dims[3], num_classes) if num_classes > 0 else nn.Identity()
418
+
419
+ self.apply(self._init_weights)
420
+
421
+ def _init_weights(self, m):
422
+ if isinstance(m, nn.Linear):
423
+ trunc_normal_(m.weight, std=.02)
424
+ if isinstance(m, nn.Linear) and m.bias is not None:
425
+ nn.init.constant_(m.bias, 0)
426
+ elif isinstance(m, nn.LayerNorm):
427
+ nn.init.constant_(m.bias, 0)
428
+ nn.init.constant_(m.weight, 1.0)
429
+ elif isinstance(m, nn.Conv2d):
430
+ fan_out = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
431
+ fan_out //= m.groups
432
+ m.weight.data.normal_(0, math.sqrt(2.0 / fan_out))
433
+ if m.bias is not None:
434
+ m.bias.data.zero_()
435
+
436
+ def init_weights(self, pretrained=None):
437
+ if isinstance(pretrained, str):
438
+ logger = 1
439
+ #load_checkpoint(self, pretrained, map_location='cpu', strict=False, logger=logger)
440
+
441
+ def reset_drop_path(self, drop_path_rate):
442
+ dpr = np.linspace(0, drop_path_rate, sum(self.depths)).tolist()
443
+ cur = 0
444
+ for i in range(self.depths[0]):
445
+ self.block1[i].drop_path.drop_prob = dpr[cur + i]
446
+
447
+ cur += self.depths[0]
448
+ for i in range(self.depths[1]):
449
+ self.block2[i].drop_path.drop_prob = dpr[cur + i]
450
+
451
+ cur += self.depths[1]
452
+ for i in range(self.depths[2]):
453
+ self.block3[i].drop_path.drop_prob = dpr[cur + i]
454
+
455
+ cur += self.depths[2]
456
+ for i in range(self.depths[3]):
457
+ self.block4[i].drop_path.drop_prob = dpr[cur + i]
458
+
459
+ def freeze_patch_emb(self):
460
+ self.patch_embed1.requires_grad = False
461
+
462
+ @torch.jit.ignore
463
+ def no_weight_decay(self):
464
+ return {'pos_embed1', 'pos_embed2', 'pos_embed3', 'pos_embed4', 'cls_token'} # has pos_embed may be better
465
+
466
+ def get_classifier(self):
467
+ return self.head
468
+
469
+ def reset_classifier(self, num_classes, global_pool=''):
470
+ self.num_classes = num_classes
471
+ self.head = nn.Linear(self.embed_dim, num_classes) if num_classes > 0 else nn.Identity()
472
+
473
+ def forward_features(self, x):
474
+ B = x.shape[0]
475
+ outs = []
476
+
477
+ # stage 1
478
+ x, H, W = self.patch_embed1(x)
479
+ for i, blk in enumerate(self.block1):
480
+ x = blk(x, H, W)
481
+ x = self.norm1(x)
482
+ x = x.reshape(B, H, W, -1).permute(0, 3, 1, 2).contiguous()
483
+ outs.append(x)
484
+
485
+ # stage 2
486
+ x, H, W = self.patch_embed2(x)
487
+ for i, blk in enumerate(self.block2):
488
+ x = blk(x, H, W)
489
+ x = self.norm2(x)
490
+ x = x.reshape(B, H, W, -1).permute(0, 3, 1, 2).contiguous()
491
+ outs.append(x)
492
+
493
+ # stage 3
494
+ x, H, W = self.patch_embed3(x)
495
+ for i, blk in enumerate(self.block3):
496
+ x = blk(x, H, W)
497
+ x = self.norm3(x)
498
+ x = x.reshape(B, H, W, -1).permute(0, 3, 1, 2).contiguous()
499
+ outs.append(x)
500
+
501
+ # stage 4
502
+ x, H, W = self.patch_embed4(x)
503
+ for i, blk in enumerate(self.block4):
504
+ x = blk(x, H, W)
505
+ x = self.norm4(x)
506
+ x = x.reshape(B, H, W, -1).permute(0, 3, 1, 2).contiguous()
507
+ outs.append(x)
508
+
509
+ return outs
510
+
511
+ # return x.mean(dim=1)
512
+
513
+ def forward(self, x):
514
+ x = self.forward_features(x)
515
+ # x = self.head(x)
516
+
517
+ return x
518
+
519
+
520
+ class DWConv(nn.Module):
521
+ def __init__(self, dim=768):
522
+ super(DWConv, self).__init__()
523
+ self.dwconv = nn.Conv2d(dim, dim, 3, 1, 1, bias=True, groups=dim)
524
+
525
+ def forward(self, x, H, W):
526
+ B, N, C = x.shape
527
+ x = x.transpose(1, 2).view(B, C, H, W).contiguous()
528
+ x = self.dwconv(x)
529
+ x = x.flatten(2).transpose(1, 2)
530
+
531
+ return x
532
+
533
+
534
+ def _conv_filter(state_dict, patch_size=16):
535
+ """ convert patch embedding weight from manual patchify + linear proj to conv"""
536
+ out_dict = {}
537
+ for k, v in state_dict.items():
538
+ if 'patch_embed.proj.weight' in k:
539
+ v = v.reshape((v.shape[0], 3, patch_size, patch_size))
540
+ out_dict[k] = v
541
+
542
+ return out_dict
543
+
544
+
545
+ ## @register_model
546
+ class pvt_v2_b0(PyramidVisionTransformerImpr):
547
+ def __init__(self, **kwargs):
548
+ super(pvt_v2_b0, self).__init__(
549
+ patch_size=4, embed_dims=[32, 64, 160, 256], num_heads=[1, 2, 5, 8], mlp_ratios=[8, 8, 4, 4],
550
+ qkv_bias=True, norm_layer=partial(nn.LayerNorm, eps=1e-6), depths=[2, 2, 2, 2], sr_ratios=[8, 4, 2, 1],
551
+ drop_rate=0.0, drop_path_rate=0.1)
552
+
553
+
554
+
555
+ ## @register_model
556
+ class pvt_v2_b1(PyramidVisionTransformerImpr):
557
+ def __init__(self, **kwargs):
558
+ super(pvt_v2_b1, self).__init__(
559
+ patch_size=4, embed_dims=[64, 128, 320, 512], num_heads=[1, 2, 5, 8], mlp_ratios=[8, 8, 4, 4],
560
+ qkv_bias=True, norm_layer=partial(nn.LayerNorm, eps=1e-6), depths=[2, 2, 2, 2], sr_ratios=[8, 4, 2, 1],
561
+ drop_rate=0.0, drop_path_rate=0.1)
562
+
563
+ ## @register_model
564
+ class pvt_v2_b2(PyramidVisionTransformerImpr):
565
+ def __init__(self, in_channels=3, **kwargs):
566
+ super(pvt_v2_b2, self).__init__(
567
+ patch_size=4, embed_dims=[64, 128, 320, 512], num_heads=[1, 2, 5, 8], mlp_ratios=[8, 8, 4, 4],
568
+ qkv_bias=True, norm_layer=partial(nn.LayerNorm, eps=1e-6), depths=[3, 4, 6, 3], sr_ratios=[8, 4, 2, 1],
569
+ drop_rate=0.0, drop_path_rate=0.1, in_channels=in_channels)
570
+
571
+ ## @register_model
572
+ class pvt_v2_b3(PyramidVisionTransformerImpr):
573
+ def __init__(self, **kwargs):
574
+ super(pvt_v2_b3, self).__init__(
575
+ patch_size=4, embed_dims=[64, 128, 320, 512], num_heads=[1, 2, 5, 8], mlp_ratios=[8, 8, 4, 4],
576
+ qkv_bias=True, norm_layer=partial(nn.LayerNorm, eps=1e-6), depths=[3, 4, 18, 3], sr_ratios=[8, 4, 2, 1],
577
+ drop_rate=0.0, drop_path_rate=0.1)
578
+
579
+ ## @register_model
580
+ class pvt_v2_b4(PyramidVisionTransformerImpr):
581
+ def __init__(self, **kwargs):
582
+ super(pvt_v2_b4, self).__init__(
583
+ patch_size=4, embed_dims=[64, 128, 320, 512], num_heads=[1, 2, 5, 8], mlp_ratios=[8, 8, 4, 4],
584
+ qkv_bias=True, norm_layer=partial(nn.LayerNorm, eps=1e-6), depths=[3, 8, 27, 3], sr_ratios=[8, 4, 2, 1],
585
+ drop_rate=0.0, drop_path_rate=0.1)
586
+
587
+
588
+ ## @register_model
589
+ class pvt_v2_b5(PyramidVisionTransformerImpr):
590
+ def __init__(self, **kwargs):
591
+ super(pvt_v2_b5, self).__init__(
592
+ patch_size=4, embed_dims=[64, 128, 320, 512], num_heads=[1, 2, 5, 8], mlp_ratios=[4, 4, 4, 4],
593
+ qkv_bias=True, norm_layer=partial(nn.LayerNorm, eps=1e-6), depths=[3, 6, 40, 3], sr_ratios=[8, 4, 2, 1],
594
+ drop_rate=0.0, drop_path_rate=0.1)
595
+
596
+
597
+
598
+ ### models/backbones/swin_v1.py
599
+
600
+ # --------------------------------------------------------
601
+ # Swin Transformer
602
+ # Copyright (c) 2021 Microsoft
603
+ # Licensed under The MIT License [see LICENSE for details]
604
+ # Written by Ze Liu, Yutong Lin, Yixuan Wei
605
+ # --------------------------------------------------------
606
+
607
+ import torch
608
+ import torch.nn as nn
609
+ import torch.nn.functional as F
610
+ import torch.utils.checkpoint as checkpoint
611
+ import numpy as np
612
+ from timm.models.layers import DropPath, to_2tuple, trunc_normal_
613
+
614
+ # from config import Config
615
+
616
+
617
+ # config = Config()
618
+
619
+ class Mlp(nn.Module):
620
+ """ Multilayer perceptron."""
621
+
622
+ def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.):
623
+ super().__init__()
624
+ out_features = out_features or in_features
625
+ hidden_features = hidden_features or in_features
626
+ self.fc1 = nn.Linear(in_features, hidden_features)
627
+ self.act = act_layer()
628
+ self.fc2 = nn.Linear(hidden_features, out_features)
629
+ self.drop = nn.Dropout(drop)
630
+
631
+ def forward(self, x):
632
+ x = self.fc1(x)
633
+ x = self.act(x)
634
+ x = self.drop(x)
635
+ x = self.fc2(x)
636
+ x = self.drop(x)
637
+ return x
638
+
639
+
640
+ def window_partition(x, window_size):
641
+ """
642
+ Args:
643
+ x: (B, H, W, C)
644
+ window_size (int): window size
645
+
646
+ Returns:
647
+ windows: (num_windows*B, window_size, window_size, C)
648
+ """
649
+ B, H, W, C = x.shape
650
+ x = x.view(B, H // window_size, window_size, W // window_size, window_size, C)
651
+ windows = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(-1, window_size, window_size, C)
652
+ return windows
653
+
654
+
655
+ def window_reverse(windows, window_size, H, W):
656
+ """
657
+ Args:
658
+ windows: (num_windows*B, window_size, window_size, C)
659
+ window_size (int): Window size
660
+ H (int): Height of image
661
+ W (int): Width of image
662
+
663
+ Returns:
664
+ x: (B, H, W, C)
665
+ """
666
+ B = int(windows.shape[0] / (H * W / window_size / window_size))
667
+ x = windows.view(B, H // window_size, W // window_size, window_size, window_size, -1)
668
+ x = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(B, H, W, -1)
669
+ return x
670
+
671
+
672
+ class WindowAttention(nn.Module):
673
+ """ Window based multi-head self attention (W-MSA) module with relative position bias.
674
+ It supports both of shifted and non-shifted window.
675
+
676
+ Args:
677
+ dim (int): Number of input channels.
678
+ window_size (tuple[int]): The height and width of the window.
679
+ num_heads (int): Number of attention heads.
680
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
681
+ qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set
682
+ attn_drop (float, optional): Dropout ratio of attention weight. Default: 0.0
683
+ proj_drop (float, optional): Dropout ratio of output. Default: 0.0
684
+ """
685
+
686
+ def __init__(self, dim, window_size, num_heads, qkv_bias=True, qk_scale=None, attn_drop=0., proj_drop=0.):
687
+
688
+ super().__init__()
689
+ self.dim = dim
690
+ self.window_size = window_size # Wh, Ww
691
+ self.num_heads = num_heads
692
+ head_dim = dim // num_heads
693
+ self.scale = qk_scale or head_dim ** -0.5
694
+
695
+ # define a parameter table of relative position bias
696
+ self.relative_position_bias_table = nn.Parameter(
697
+ torch.zeros((2 * window_size[0] - 1) * (2 * window_size[1] - 1), num_heads)) # 2*Wh-1 * 2*Ww-1, nH
698
+
699
+ # get pair-wise relative position index for each token inside the window
700
+ coords_h = torch.arange(self.window_size[0])
701
+ coords_w = torch.arange(self.window_size[1])
702
+ coords = torch.stack(torch.meshgrid([coords_h, coords_w], indexing='ij')) # 2, Wh, Ww
703
+ coords_flatten = torch.flatten(coords, 1) # 2, Wh*Ww
704
+ relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :] # 2, Wh*Ww, Wh*Ww
705
+ relative_coords = relative_coords.permute(1, 2, 0).contiguous() # Wh*Ww, Wh*Ww, 2
706
+ relative_coords[:, :, 0] += self.window_size[0] - 1 # shift to start from 0
707
+ relative_coords[:, :, 1] += self.window_size[1] - 1
708
+ relative_coords[:, :, 0] *= 2 * self.window_size[1] - 1
709
+ relative_position_index = relative_coords.sum(-1) # Wh*Ww, Wh*Ww
710
+ self.register_buffer("relative_position_index", relative_position_index)
711
+
712
+ self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
713
+ self.attn_drop_prob = attn_drop
714
+ self.attn_drop = nn.Dropout(attn_drop)
715
+ self.proj = nn.Linear(dim, dim)
716
+ self.proj_drop = nn.Dropout(proj_drop)
717
+
718
+ trunc_normal_(self.relative_position_bias_table, std=.02)
719
+ self.softmax = nn.Softmax(dim=-1)
720
+
721
+ def forward(self, x, mask=None):
722
+ """ Forward function.
723
+
724
+ Args:
725
+ x: input features with shape of (num_windows*B, N, C)
726
+ mask: (0/-inf) mask with shape of (num_windows, Wh*Ww, Wh*Ww) or None
727
+ """
728
+ B_, N, C = x.shape
729
+ qkv = self.qkv(x).reshape(B_, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
730
+ q, k, v = qkv[0], qkv[1], qkv[2] # make torchscript happy (cannot use tensor as tuple)
731
+
732
+ q = q * self.scale
733
+
734
+ if config.SDPA_enabled:
735
+ x = torch.nn.functional.scaled_dot_product_attention(
736
+ q, k, v,
737
+ attn_mask=None, dropout_p=self.attn_drop_prob, is_causal=False
738
+ ).transpose(1, 2).reshape(B_, N, C)
739
+ else:
740
+ attn = (q @ k.transpose(-2, -1))
741
+
742
+ relative_position_bias = self.relative_position_bias_table[self.relative_position_index.view(-1)].view(
743
+ self.window_size[0] * self.window_size[1], self.window_size[0] * self.window_size[1], -1) # Wh*Ww,Wh*Ww,nH
744
+ relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous() # nH, Wh*Ww, Wh*Ww
745
+ attn = attn + relative_position_bias.unsqueeze(0)
746
+
747
+ if mask is not None:
748
+ nW = mask.shape[0]
749
+ attn = attn.view(B_ // nW, nW, self.num_heads, N, N) + mask.unsqueeze(1).unsqueeze(0)
750
+ attn = attn.view(-1, self.num_heads, N, N)
751
+ attn = self.softmax(attn)
752
+ else:
753
+ attn = self.softmax(attn)
754
+
755
+ attn = self.attn_drop(attn)
756
+
757
+ x = (attn @ v).transpose(1, 2).reshape(B_, N, C)
758
+ x = self.proj(x)
759
+ x = self.proj_drop(x)
760
+ return x
761
+
762
+
763
+ class SwinTransformerBlock(nn.Module):
764
+ """ Swin Transformer Block.
765
+
766
+ Args:
767
+ dim (int): Number of input channels.
768
+ num_heads (int): Number of attention heads.
769
+ window_size (int): Window size.
770
+ shift_size (int): Shift size for SW-MSA.
771
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
772
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
773
+ qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.
774
+ drop (float, optional): Dropout rate. Default: 0.0
775
+ attn_drop (float, optional): Attention dropout rate. Default: 0.0
776
+ drop_path (float, optional): Stochastic depth rate. Default: 0.0
777
+ act_layer (nn.Module, optional): Activation layer. Default: nn.GELU
778
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
779
+ """
780
+
781
+ def __init__(self, dim, num_heads, window_size=7, shift_size=0,
782
+ mlp_ratio=4., qkv_bias=True, qk_scale=None, drop=0., attn_drop=0., drop_path=0.,
783
+ act_layer=nn.GELU, norm_layer=nn.LayerNorm):
784
+ super().__init__()
785
+ self.dim = dim
786
+ self.num_heads = num_heads
787
+ self.window_size = window_size
788
+ self.shift_size = shift_size
789
+ self.mlp_ratio = mlp_ratio
790
+ assert 0 <= self.shift_size < self.window_size, "shift_size must in 0-window_size"
791
+
792
+ self.norm1 = norm_layer(dim)
793
+ self.attn = WindowAttention(
794
+ dim, window_size=to_2tuple(self.window_size), num_heads=num_heads,
795
+ qkv_bias=qkv_bias, qk_scale=qk_scale, attn_drop=attn_drop, proj_drop=drop)
796
+
797
+ self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
798
+ self.norm2 = norm_layer(dim)
799
+ mlp_hidden_dim = int(dim * mlp_ratio)
800
+ self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)
801
+
802
+ self.H = None
803
+ self.W = None
804
+
805
+ def forward(self, x, mask_matrix):
806
+ """ Forward function.
807
+
808
+ Args:
809
+ x: Input feature, tensor size (B, H*W, C).
810
+ H, W: Spatial resolution of the input feature.
811
+ mask_matrix: Attention mask for cyclic shift.
812
+ """
813
+ B, L, C = x.shape
814
+ H, W = self.H, self.W
815
+ assert L == H * W, "input feature has wrong size"
816
+
817
+ shortcut = x
818
+ x = self.norm1(x)
819
+ x = x.view(B, H, W, C)
820
+
821
+ # pad feature maps to multiples of window size
822
+ pad_l = pad_t = 0
823
+ pad_r = (self.window_size - W % self.window_size) % self.window_size
824
+ pad_b = (self.window_size - H % self.window_size) % self.window_size
825
+ x = F.pad(x, (0, 0, pad_l, pad_r, pad_t, pad_b))
826
+ _, Hp, Wp, _ = x.shape
827
+
828
+ # cyclic shift
829
+ if self.shift_size > 0:
830
+ shifted_x = torch.roll(x, shifts=(-self.shift_size, -self.shift_size), dims=(1, 2))
831
+ attn_mask = mask_matrix
832
+ else:
833
+ shifted_x = x
834
+ attn_mask = None
835
+
836
+ # partition windows
837
+ x_windows = window_partition(shifted_x, self.window_size) # nW*B, window_size, window_size, C
838
+ x_windows = x_windows.view(-1, self.window_size * self.window_size, C) # nW*B, window_size*window_size, C
839
+
840
+ # W-MSA/SW-MSA
841
+ attn_windows = self.attn(x_windows, mask=attn_mask) # nW*B, window_size*window_size, C
842
+
843
+ # merge windows
844
+ attn_windows = attn_windows.view(-1, self.window_size, self.window_size, C)
845
+ shifted_x = window_reverse(attn_windows, self.window_size, Hp, Wp) # B H' W' C
846
+
847
+ # reverse cyclic shift
848
+ if self.shift_size > 0:
849
+ x = torch.roll(shifted_x, shifts=(self.shift_size, self.shift_size), dims=(1, 2))
850
+ else:
851
+ x = shifted_x
852
+
853
+ if pad_r > 0 or pad_b > 0:
854
+ x = x[:, :H, :W, :].contiguous()
855
+
856
+ x = x.view(B, H * W, C)
857
+
858
+ # FFN
859
+ x = shortcut + self.drop_path(x)
860
+ x = x + self.drop_path(self.mlp(self.norm2(x)))
861
+
862
+ return x
863
+
864
+
865
+ class PatchMerging(nn.Module):
866
+ """ Patch Merging Layer
867
+
868
+ Args:
869
+ dim (int): Number of input channels.
870
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
871
+ """
872
+ def __init__(self, dim, norm_layer=nn.LayerNorm):
873
+ super().__init__()
874
+ self.dim = dim
875
+ self.reduction = nn.Linear(4 * dim, 2 * dim, bias=False)
876
+ self.norm = norm_layer(4 * dim)
877
+
878
+ def forward(self, x, H, W):
879
+ """ Forward function.
880
+
881
+ Args:
882
+ x: Input feature, tensor size (B, H*W, C).
883
+ H, W: Spatial resolution of the input feature.
884
+ """
885
+ B, L, C = x.shape
886
+ assert L == H * W, "input feature has wrong size"
887
+
888
+ x = x.view(B, H, W, C)
889
+
890
+ # padding
891
+ pad_input = (H % 2 == 1) or (W % 2 == 1)
892
+ if pad_input:
893
+ x = F.pad(x, (0, 0, 0, W % 2, 0, H % 2))
894
+
895
+ x0 = x[:, 0::2, 0::2, :] # B H/2 W/2 C
896
+ x1 = x[:, 1::2, 0::2, :] # B H/2 W/2 C
897
+ x2 = x[:, 0::2, 1::2, :] # B H/2 W/2 C
898
+ x3 = x[:, 1::2, 1::2, :] # B H/2 W/2 C
899
+ x = torch.cat([x0, x1, x2, x3], -1) # B H/2 W/2 4*C
900
+ x = x.view(B, -1, 4 * C) # B H/2*W/2 4*C
901
+
902
+ x = self.norm(x)
903
+ x = self.reduction(x)
904
+
905
+ return x
906
+
907
+
908
+ class BasicLayer(nn.Module):
909
+ """ A basic Swin Transformer layer for one stage.
910
+
911
+ Args:
912
+ dim (int): Number of feature channels
913
+ depth (int): Depths of this stage.
914
+ num_heads (int): Number of attention head.
915
+ window_size (int): Local window size. Default: 7.
916
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. Default: 4.
917
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
918
+ qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.
919
+ drop (float, optional): Dropout rate. Default: 0.0
920
+ attn_drop (float, optional): Attention dropout rate. Default: 0.0
921
+ drop_path (float | tuple[float], optional): Stochastic depth rate. Default: 0.0
922
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
923
+ downsample (nn.Module | None, optional): Downsample layer at the end of the layer. Default: None
924
+ use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False.
925
+ """
926
+
927
+ def __init__(self,
928
+ dim,
929
+ depth,
930
+ num_heads,
931
+ window_size=7,
932
+ mlp_ratio=4.,
933
+ qkv_bias=True,
934
+ qk_scale=None,
935
+ drop=0.,
936
+ attn_drop=0.,
937
+ drop_path=0.,
938
+ norm_layer=nn.LayerNorm,
939
+ downsample=None,
940
+ use_checkpoint=False):
941
+ super().__init__()
942
+ self.window_size = window_size
943
+ self.shift_size = window_size // 2
944
+ self.depth = depth
945
+ self.use_checkpoint = use_checkpoint
946
+
947
+ # build blocks
948
+ self.blocks = nn.ModuleList([
949
+ SwinTransformerBlock(
950
+ dim=dim,
951
+ num_heads=num_heads,
952
+ window_size=window_size,
953
+ shift_size=0 if (i % 2 == 0) else window_size // 2,
954
+ mlp_ratio=mlp_ratio,
955
+ qkv_bias=qkv_bias,
956
+ qk_scale=qk_scale,
957
+ drop=drop,
958
+ attn_drop=attn_drop,
959
+ drop_path=drop_path[i] if isinstance(drop_path, list) else drop_path,
960
+ norm_layer=norm_layer)
961
+ for i in range(depth)])
962
+
963
+ # patch merging layer
964
+ if downsample is not None:
965
+ self.downsample = downsample(dim=dim, norm_layer=norm_layer)
966
+ else:
967
+ self.downsample = None
968
+
969
+ def forward(self, x, H, W):
970
+ """ Forward function.
971
+
972
+ Args:
973
+ x: Input feature, tensor size (B, H*W, C).
974
+ H, W: Spatial resolution of the input feature.
975
+ """
976
+
977
+ # calculate attention mask for SW-MSA
978
+ Hp = int(np.ceil(H / self.window_size)) * self.window_size
979
+ Wp = int(np.ceil(W / self.window_size)) * self.window_size
980
+ img_mask = torch.zeros((1, Hp, Wp, 1), device=x.device) # 1 Hp Wp 1
981
+ h_slices = (slice(0, -self.window_size),
982
+ slice(-self.window_size, -self.shift_size),
983
+ slice(-self.shift_size, None))
984
+ w_slices = (slice(0, -self.window_size),
985
+ slice(-self.window_size, -self.shift_size),
986
+ slice(-self.shift_size, None))
987
+ cnt = 0
988
+ for h in h_slices:
989
+ for w in w_slices:
990
+ img_mask[:, h, w, :] = cnt
991
+ cnt += 1
992
+
993
+ mask_windows = window_partition(img_mask, self.window_size) # nW, window_size, window_size, 1
994
+ mask_windows = mask_windows.view(-1, self.window_size * self.window_size)
995
+ attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2)
996
+ attn_mask = attn_mask.masked_fill(attn_mask != 0, float(-100.0)).masked_fill(attn_mask == 0, float(0.0)).to(x.dtype)
997
+
998
+ for blk in self.blocks:
999
+ blk.H, blk.W = H, W
1000
+ if self.use_checkpoint:
1001
+ x = checkpoint.checkpoint(blk, x, attn_mask)
1002
+ else:
1003
+ x = blk(x, attn_mask)
1004
+ if self.downsample is not None:
1005
+ x_down = self.downsample(x, H, W)
1006
+ Wh, Ww = (H + 1) // 2, (W + 1) // 2
1007
+ return x, H, W, x_down, Wh, Ww
1008
+ else:
1009
+ return x, H, W, x, H, W
1010
+
1011
+
1012
+ class PatchEmbed(nn.Module):
1013
+ """ Image to Patch Embedding
1014
+
1015
+ Args:
1016
+ patch_size (int): Patch token size. Default: 4.
1017
+ in_channels (int): Number of input image channels. Default: 3.
1018
+ embed_dim (int): Number of linear projection output channels. Default: 96.
1019
+ norm_layer (nn.Module, optional): Normalization layer. Default: None
1020
+ """
1021
+
1022
+ def __init__(self, patch_size=4, in_channels=3, embed_dim=96, norm_layer=None):
1023
+ super().__init__()
1024
+ patch_size = to_2tuple(patch_size)
1025
+ self.patch_size = patch_size
1026
+
1027
+ self.in_channels = in_channels
1028
+ self.embed_dim = embed_dim
1029
+
1030
+ self.proj = nn.Conv2d(in_channels, embed_dim, kernel_size=patch_size, stride=patch_size)
1031
+ if norm_layer is not None:
1032
+ self.norm = norm_layer(embed_dim)
1033
+ else:
1034
+ self.norm = None
1035
+
1036
+ def forward(self, x):
1037
+ """Forward function."""
1038
+ # padding
1039
+ _, _, H, W = x.size()
1040
+ if W % self.patch_size[1] != 0:
1041
+ x = F.pad(x, (0, self.patch_size[1] - W % self.patch_size[1]))
1042
+ if H % self.patch_size[0] != 0:
1043
+ x = F.pad(x, (0, 0, 0, self.patch_size[0] - H % self.patch_size[0]))
1044
+
1045
+ x = self.proj(x) # B C Wh Ww
1046
+ if self.norm is not None:
1047
+ Wh, Ww = x.size(2), x.size(3)
1048
+ x = x.flatten(2).transpose(1, 2)
1049
+ x = self.norm(x)
1050
+ x = x.transpose(1, 2).view(-1, self.embed_dim, Wh, Ww)
1051
+
1052
+ return x
1053
+
1054
+
1055
+ class SwinTransformer(nn.Module):
1056
+ """ Swin Transformer backbone.
1057
+ A PyTorch impl of : `Swin Transformer: Hierarchical Vision Transformer using Shifted Windows` -
1058
+ https://arxiv.org/pdf/2103.14030
1059
+
1060
+ Args:
1061
+ pretrain_img_size (int): Input image size for training the pretrained model,
1062
+ used in absolute postion embedding. Default 224.
1063
+ patch_size (int | tuple(int)): Patch size. Default: 4.
1064
+ in_channels (int): Number of input image channels. Default: 3.
1065
+ embed_dim (int): Number of linear projection output channels. Default: 96.
1066
+ depths (tuple[int]): Depths of each Swin Transformer stage.
1067
+ num_heads (tuple[int]): Number of attention head of each stage.
1068
+ window_size (int): Window size. Default: 7.
1069
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. Default: 4.
1070
+ qkv_bias (bool): If True, add a learnable bias to query, key, value. Default: True
1071
+ qk_scale (float): Override default qk scale of head_dim ** -0.5 if set.
1072
+ drop_rate (float): Dropout rate.
1073
+ attn_drop_rate (float): Attention dropout rate. Default: 0.
1074
+ drop_path_rate (float): Stochastic depth rate. Default: 0.2.
1075
+ norm_layer (nn.Module): Normalization layer. Default: nn.LayerNorm.
1076
+ ape (bool): If True, add absolute position embedding to the patch embedding. Default: False.
1077
+ patch_norm (bool): If True, add normalization after patch embedding. Default: True.
1078
+ out_indices (Sequence[int]): Output from which stages.
1079
+ frozen_stages (int): Stages to be frozen (stop grad and set eval mode).
1080
+ -1 means not freezing any parameters.
1081
+ use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False.
1082
+ """
1083
+
1084
+ def __init__(self,
1085
+ pretrain_img_size=224,
1086
+ patch_size=4,
1087
+ in_channels=3,
1088
+ embed_dim=96,
1089
+ depths=[2, 2, 6, 2],
1090
+ num_heads=[3, 6, 12, 24],
1091
+ window_size=7,
1092
+ mlp_ratio=4.,
1093
+ qkv_bias=True,
1094
+ qk_scale=None,
1095
+ drop_rate=0.,
1096
+ attn_drop_rate=0.,
1097
+ drop_path_rate=0.2,
1098
+ norm_layer=nn.LayerNorm,
1099
+ ape=False,
1100
+ patch_norm=True,
1101
+ out_indices=(0, 1, 2, 3),
1102
+ frozen_stages=-1,
1103
+ use_checkpoint=False):
1104
+ super().__init__()
1105
+
1106
+ self.pretrain_img_size = pretrain_img_size
1107
+ self.num_layers = len(depths)
1108
+ self.embed_dim = embed_dim
1109
+ self.ape = ape
1110
+ self.patch_norm = patch_norm
1111
+ self.out_indices = out_indices
1112
+ self.frozen_stages = frozen_stages
1113
+
1114
+ # split image into non-overlapping patches
1115
+ self.patch_embed = PatchEmbed(
1116
+ patch_size=patch_size, in_channels=in_channels, embed_dim=embed_dim,
1117
+ norm_layer=norm_layer if self.patch_norm else None)
1118
+
1119
+ # absolute position embedding
1120
+ if self.ape:
1121
+ pretrain_img_size = to_2tuple(pretrain_img_size)
1122
+ patch_size = to_2tuple(patch_size)
1123
+ patches_resolution = [pretrain_img_size[0] // patch_size[0], pretrain_img_size[1] // patch_size[1]]
1124
+
1125
+ self.absolute_pos_embed = nn.Parameter(torch.zeros(1, embed_dim, patches_resolution[0], patches_resolution[1]))
1126
+ trunc_normal_(self.absolute_pos_embed, std=.02)
1127
+
1128
+ self.pos_drop = nn.Dropout(p=drop_rate)
1129
+
1130
+ # stochastic depth
1131
+ dpr = np.linspace(0, drop_path_rate, sum(depths)).tolist() # stochastic depth decay rule
1132
+
1133
+ # build layers
1134
+ self.layers = nn.ModuleList()
1135
+ for i_layer in range(self.num_layers):
1136
+ layer = BasicLayer(
1137
+ dim=int(embed_dim * 2 ** i_layer),
1138
+ depth=depths[i_layer],
1139
+ num_heads=num_heads[i_layer],
1140
+ window_size=window_size,
1141
+ mlp_ratio=mlp_ratio,
1142
+ qkv_bias=qkv_bias,
1143
+ qk_scale=qk_scale,
1144
+ drop=drop_rate,
1145
+ attn_drop=attn_drop_rate,
1146
+ drop_path=dpr[sum(depths[:i_layer]):sum(depths[:i_layer + 1])],
1147
+ norm_layer=norm_layer,
1148
+ downsample=PatchMerging if (i_layer < self.num_layers - 1) else None,
1149
+ use_checkpoint=use_checkpoint)
1150
+ self.layers.append(layer)
1151
+
1152
+ num_features = [int(embed_dim * 2 ** i) for i in range(self.num_layers)]
1153
+ self.num_features = num_features
1154
+
1155
+ # add a norm layer for each output
1156
+ for i_layer in out_indices:
1157
+ layer = norm_layer(num_features[i_layer])
1158
+ layer_name = f'norm{i_layer}'
1159
+ self.add_module(layer_name, layer)
1160
+
1161
+ self._freeze_stages()
1162
+
1163
+ def _freeze_stages(self):
1164
+ if self.frozen_stages >= 0:
1165
+ self.patch_embed.eval()
1166
+ for param in self.patch_embed.parameters():
1167
+ param.requires_grad = False
1168
+
1169
+ if self.frozen_stages >= 1 and self.ape:
1170
+ self.absolute_pos_embed.requires_grad = False
1171
+
1172
+ if self.frozen_stages >= 2:
1173
+ self.pos_drop.eval()
1174
+ for i in range(0, self.frozen_stages - 1):
1175
+ m = self.layers[i]
1176
+ m.eval()
1177
+ for param in m.parameters():
1178
+ param.requires_grad = False
1179
+
1180
+
1181
+ def forward(self, x):
1182
+ """Forward function."""
1183
+ x = self.patch_embed(x)
1184
+
1185
+ Wh, Ww = x.size(2), x.size(3)
1186
+ if self.ape:
1187
+ # interpolate the position embedding to the corresponding size
1188
+ absolute_pos_embed = F.interpolate(self.absolute_pos_embed, size=(Wh, Ww), mode='bicubic')
1189
+ x = (x + absolute_pos_embed) # B Wh*Ww C
1190
+
1191
+ outs = []#x.contiguous()]
1192
+ x = x.flatten(2).transpose(1, 2)
1193
+ x = self.pos_drop(x)
1194
+ for i in range(self.num_layers):
1195
+ layer = self.layers[i]
1196
+ x_out, H, W, x, Wh, Ww = layer(x, Wh, Ww)
1197
+
1198
+ if i in self.out_indices:
1199
+ norm_layer = getattr(self, f'norm{i}')
1200
+ x_out = norm_layer(x_out)
1201
+
1202
+ out = x_out.view(-1, H, W, self.num_features[i]).permute(0, 3, 1, 2).contiguous()
1203
+ outs.append(out)
1204
+
1205
+ return tuple(outs)
1206
+
1207
+ def train(self, mode=True):
1208
+ """Convert the model into training mode while keep layers freezed."""
1209
+ super(SwinTransformer, self).train(mode)
1210
+ self._freeze_stages()
1211
+
1212
+ def swin_v1_t():
1213
+ model = SwinTransformer(embed_dim=96, depths=[2, 2, 6, 2], num_heads=[3, 6, 12, 24], window_size=7)
1214
+ return model
1215
+
1216
+ def swin_v1_s():
1217
+ model = SwinTransformer(embed_dim=96, depths=[2, 2, 18, 2], num_heads=[3, 6, 12, 24], window_size=7)
1218
+ return model
1219
+
1220
+ def swin_v1_b():
1221
+ model = SwinTransformer(embed_dim=128, depths=[2, 2, 18, 2], num_heads=[4, 8, 16, 32], window_size=12)
1222
+ return model
1223
+
1224
+ def swin_v1_l():
1225
+ model = SwinTransformer(embed_dim=192, depths=[2, 2, 18, 2], num_heads=[6, 12, 24, 48], window_size=12)
1226
+ return model
1227
+
1228
+
1229
+
1230
+ ### models/modules/deform_conv.py
1231
+
1232
+ import torch
1233
+ import torch.nn as nn
1234
+ from torchvision.ops import deform_conv2d
1235
+
1236
+
1237
+ class DeformableConv2d(nn.Module):
1238
+ def __init__(self,
1239
+ in_channels,
1240
+ out_channels,
1241
+ kernel_size=3,
1242
+ stride=1,
1243
+ padding=1,
1244
+ bias=False):
1245
+
1246
+ super(DeformableConv2d, self).__init__()
1247
+
1248
+ assert type(kernel_size) == tuple or type(kernel_size) == int
1249
+
1250
+ kernel_size = kernel_size if type(kernel_size) == tuple else (kernel_size, kernel_size)
1251
+ self.stride = stride if type(stride) == tuple else (stride, stride)
1252
+ self.padding = padding
1253
+
1254
+ self.offset_conv = nn.Conv2d(in_channels,
1255
+ 2 * kernel_size[0] * kernel_size[1],
1256
+ kernel_size=kernel_size,
1257
+ stride=stride,
1258
+ padding=self.padding,
1259
+ bias=True)
1260
+
1261
+ nn.init.constant_(self.offset_conv.weight, 0.)
1262
+ nn.init.constant_(self.offset_conv.bias, 0.)
1263
+
1264
+ self.modulator_conv = nn.Conv2d(in_channels,
1265
+ 1 * kernel_size[0] * kernel_size[1],
1266
+ kernel_size=kernel_size,
1267
+ stride=stride,
1268
+ padding=self.padding,
1269
+ bias=True)
1270
+
1271
+ nn.init.constant_(self.modulator_conv.weight, 0.)
1272
+ nn.init.constant_(self.modulator_conv.bias, 0.)
1273
+
1274
+ self.regular_conv = nn.Conv2d(in_channels,
1275
+ out_channels=out_channels,
1276
+ kernel_size=kernel_size,
1277
+ stride=stride,
1278
+ padding=self.padding,
1279
+ bias=bias)
1280
+
1281
+ def forward(self, x):
1282
+ #h, w = x.shape[2:]
1283
+ #max_offset = max(h, w)/4.
1284
+
1285
+ offset = self.offset_conv(x)#.clamp(-max_offset, max_offset)
1286
+ modulator = 2. * torch.sigmoid(self.modulator_conv(x))
1287
+
1288
+ x = deform_conv2d(
1289
+ input=x,
1290
+ offset=offset,
1291
+ weight=self.regular_conv.weight,
1292
+ bias=self.regular_conv.bias,
1293
+ padding=self.padding,
1294
+ mask=modulator,
1295
+ stride=self.stride,
1296
+ )
1297
+ return x
1298
+
1299
+
1300
+
1301
+
1302
+ ### utils.py
1303
+
1304
+ import torch.nn as nn
1305
+
1306
+
1307
+ def build_act_layer(act_layer):
1308
+ if act_layer == 'ReLU':
1309
+ return nn.ReLU(inplace=True)
1310
+ elif act_layer == 'SiLU':
1311
+ return nn.SiLU(inplace=True)
1312
+ elif act_layer == 'GELU':
1313
+ return nn.GELU()
1314
+
1315
+ raise NotImplementedError(f'build_act_layer does not support {act_layer}')
1316
+
1317
+
1318
+ def build_norm_layer(dim,
1319
+ norm_layer,
1320
+ in_format='channels_last',
1321
+ out_format='channels_last',
1322
+ eps=1e-6):
1323
+ layers = []
1324
+ if norm_layer == 'BN':
1325
+ if in_format == 'channels_last':
1326
+ layers.append(to_channels_first())
1327
+ layers.append(nn.BatchNorm2d(dim))
1328
+ if out_format == 'channels_last':
1329
+ layers.append(to_channels_last())
1330
+ elif norm_layer == 'LN':
1331
+ if in_format == 'channels_first':
1332
+ layers.append(to_channels_last())
1333
+ layers.append(nn.LayerNorm(dim, eps=eps))
1334
+ if out_format == 'channels_first':
1335
+ layers.append(to_channels_first())
1336
+ else:
1337
+ raise NotImplementedError(
1338
+ f'build_norm_layer does not support {norm_layer}')
1339
+ return nn.Sequential(*layers)
1340
+
1341
+
1342
+ class to_channels_first(nn.Module):
1343
+
1344
+ def __init__(self):
1345
+ super().__init__()
1346
+
1347
+ def forward(self, x):
1348
+ return x.permute(0, 3, 1, 2)
1349
+
1350
+
1351
+ class to_channels_last(nn.Module):
1352
+
1353
+ def __init__(self):
1354
+ super().__init__()
1355
+
1356
+ def forward(self, x):
1357
+ return x.permute(0, 2, 3, 1)
1358
+
1359
+
1360
+
1361
+ ### dataset.py
1362
+
1363
+ _class_labels_TR_sorted = (
1364
+ 'Airplane, Ant, Antenna, Archery, Axe, BabyCarriage, Bag, BalanceBeam, Balcony, Balloon, Basket, BasketballHoop, Beatle, Bed, Bee, Bench, Bicycle, '
1365
+ 'BicycleFrame, BicycleStand, Boat, Bonsai, BoomLift, Bridge, BunkBed, Butterfly, Button, Cable, CableLift, Cage, Camcorder, Cannon, Canoe, Car, '
1366
+ 'CarParkDropArm, Carriage, Cart, Caterpillar, CeilingLamp, Centipede, Chair, Clip, Clock, Clothes, CoatHanger, Comb, ConcretePumpTruck, Crack, Crane, '
1367
+ 'Cup, DentalChair, Desk, DeskChair, Diagram, DishRack, DoorHandle, Dragonfish, Dragonfly, Drum, Earphone, Easel, ElectricIron, Excavator, Eyeglasses, '
1368
+ 'Fan, Fence, Fencing, FerrisWheel, FireExtinguisher, Fishing, Flag, FloorLamp, Forklift, GasStation, Gate, Gear, Goal, Golf, GymEquipment, Hammock, '
1369
+ 'Handcart, Handcraft, Handrail, HangGlider, Harp, Harvester, Headset, Helicopter, Helmet, Hook, HorizontalBar, Hydrovalve, IroningTable, Jewelry, Key, '
1370
+ 'KidsPlayground, Kitchenware, Kite, Knife, Ladder, LaundryRack, Lightning, Lobster, Locust, Machine, MachineGun, MagazineRack, Mantis, Medal, MemorialArchway, '
1371
+ 'Microphone, Missile, MobileHolder, Monitor, Mosquito, Motorcycle, MovingTrolley, Mower, MusicPlayer, MusicStand, ObservationTower, Octopus, OilWell, '
1372
+ 'OlympicLogo, OperatingTable, OutdoorFitnessEquipment, Parachute, Pavilion, Piano, Pipe, PlowHarrow, PoleVault, Punchbag, Rack, Racket, Rifle, Ring, Robot, '
1373
+ 'RockClimbing, Rope, Sailboat, Satellite, Scaffold, Scale, Scissor, Scooter, Sculpture, Seadragon, Seahorse, Seal, SewingMachine, Ship, Shoe, ShoppingCart, '
1374
+ 'ShoppingTrolley, Shower, Shrimp, Signboard, Skateboarding, Skeleton, Skiing, Spade, SpeedBoat, Spider, Spoon, Stair, Stand, Stationary, SteeringWheel, '
1375
+ 'Stethoscope, Stool, Stove, StreetLamp, SweetStand, Swing, Sword, TV, Table, TableChair, TableLamp, TableTennis, Tank, Tapeline, Teapot, Telescope, Tent, '
1376
+ 'TobaccoPipe, Toy, Tractor, TrafficLight, TrafficSign, Trampoline, TransmissionTower, Tree, Tricycle, TrimmerCover, Tripod, Trombone, Truck, Trumpet, Tuba, '
1377
+ 'UAV, Umbrella, UnevenBars, UtilityPole, VacuumCleaner, Violin, Wakesurfing, Watch, WaterTower, WateringPot, Well, WellLid, Wheel, Wheelchair, WindTurbine, Windmill, WineGlass, WireWhisk, Yacht'
1378
+ )
1379
+ class_labels_TR_sorted = _class_labels_TR_sorted.split(', ')
1380
+
1381
+
1382
+ ### models/backbones/build_backbones.py
1383
+
1384
+ import torch
1385
+ import torch.nn as nn
1386
+ from collections import OrderedDict
1387
+ from torchvision.models import vgg16, vgg16_bn, VGG16_Weights, VGG16_BN_Weights, resnet50, ResNet50_Weights
1388
+ # from models.pvt_v2 import pvt_v2_b0, pvt_v2_b1, pvt_v2_b2, pvt_v2_b5
1389
+ # from models.swin_v1 import swin_v1_t, swin_v1_s, swin_v1_b, swin_v1_l
1390
+ # from config import Config
1391
+
1392
+
1393
+ config = Config()
1394
+
1395
+ def build_backbone(bb_name, pretrained=True, params_settings=''):
1396
+ if bb_name == 'vgg16':
1397
+ bb_net = list(vgg16(pretrained=VGG16_Weights.DEFAULT if pretrained else None).children())[0]
1398
+ bb = nn.Sequential(OrderedDict({'conv1': bb_net[:4], 'conv2': bb_net[4:9], 'conv3': bb_net[9:16], 'conv4': bb_net[16:23]}))
1399
+ elif bb_name == 'vgg16bn':
1400
+ bb_net = list(vgg16_bn(pretrained=VGG16_BN_Weights.DEFAULT if pretrained else None).children())[0]
1401
+ bb = nn.Sequential(OrderedDict({'conv1': bb_net[:6], 'conv2': bb_net[6:13], 'conv3': bb_net[13:23], 'conv4': bb_net[23:33]}))
1402
+ elif bb_name == 'resnet50':
1403
+ bb_net = list(resnet50(pretrained=ResNet50_Weights.DEFAULT if pretrained else None).children())
1404
+ bb = nn.Sequential(OrderedDict({'conv1': nn.Sequential(*bb_net[0:3]), 'conv2': bb_net[4], 'conv3': bb_net[5], 'conv4': bb_net[6]}))
1405
+ else:
1406
+ bb = eval('{}({})'.format(bb_name, params_settings))
1407
+ if pretrained:
1408
+ bb = load_weights(bb, bb_name)
1409
+ return bb
1410
+
1411
+ def load_weights(model, model_name):
1412
+ save_model = torch.load(config.weights[model_name], map_location='cpu')
1413
+ model_dict = model.state_dict()
1414
+ state_dict = {k: v if v.size() == model_dict[k].size() else model_dict[k] for k, v in save_model.items() if k in model_dict.keys()}
1415
+ # to ignore the weights with mismatched size when I modify the backbone itself.
1416
+ if not state_dict:
1417
+ save_model_keys = list(save_model.keys())
1418
+ sub_item = save_model_keys[0] if len(save_model_keys) == 1 else None
1419
+ state_dict = {k: v if v.size() == model_dict[k].size() else model_dict[k] for k, v in save_model[sub_item].items() if k in model_dict.keys()}
1420
+ if not state_dict or not sub_item:
1421
+ print('Weights are not successully loaded. Check the state dict of weights file.')
1422
+ return None
1423
+ else:
1424
+ print('Found correct weights in the "{}" item of loaded state_dict.'.format(sub_item))
1425
+ model_dict.update(state_dict)
1426
+ model.load_state_dict(model_dict)
1427
+ return model
1428
+
1429
+
1430
+
1431
+ ### models/modules/decoder_blocks.py
1432
+
1433
+ import torch
1434
+ import torch.nn as nn
1435
+ # from models.aspp import ASPP, ASPPDeformable
1436
+ # from config import Config
1437
+
1438
+
1439
+ # config = Config()
1440
+
1441
+
1442
+ class BasicDecBlk(nn.Module):
1443
+ def __init__(self, in_channels=64, out_channels=64, inter_channels=64):
1444
+ super(BasicDecBlk, self).__init__()
1445
+ inter_channels = in_channels // 4 if config.dec_channels_inter == 'adap' else 64
1446
+ self.conv_in = nn.Conv2d(in_channels, inter_channels, 3, 1, padding=1)
1447
+ self.relu_in = nn.ReLU(inplace=True)
1448
+ if config.dec_att == 'ASPP':
1449
+ self.dec_att = ASPP(in_channels=inter_channels)
1450
+ elif config.dec_att == 'ASPPDeformable':
1451
+ self.dec_att = ASPPDeformable(in_channels=inter_channels)
1452
+ self.conv_out = nn.Conv2d(inter_channels, out_channels, 3, 1, padding=1)
1453
+ self.bn_in = nn.BatchNorm2d(inter_channels) if config.batch_size > 1 else nn.Identity()
1454
+ self.bn_out = nn.BatchNorm2d(out_channels) if config.batch_size > 1 else nn.Identity()
1455
+
1456
+ def forward(self, x):
1457
+ x = self.conv_in(x)
1458
+ x = self.bn_in(x)
1459
+ x = self.relu_in(x)
1460
+ if hasattr(self, 'dec_att'):
1461
+ x = self.dec_att(x)
1462
+ x = self.conv_out(x)
1463
+ x = self.bn_out(x)
1464
+ return x
1465
+
1466
+
1467
+ class ResBlk(nn.Module):
1468
+ def __init__(self, in_channels=64, out_channels=None, inter_channels=64):
1469
+ super(ResBlk, self).__init__()
1470
+ if out_channels is None:
1471
+ out_channels = in_channels
1472
+ inter_channels = in_channels // 4 if config.dec_channels_inter == 'adap' else 64
1473
+
1474
+ self.conv_in = nn.Conv2d(in_channels, inter_channels, 3, 1, padding=1)
1475
+ self.bn_in = nn.BatchNorm2d(inter_channels) if config.batch_size > 1 else nn.Identity()
1476
+ self.relu_in = nn.ReLU(inplace=True)
1477
+
1478
+ if config.dec_att == 'ASPP':
1479
+ self.dec_att = ASPP(in_channels=inter_channels)
1480
+ elif config.dec_att == 'ASPPDeformable':
1481
+ self.dec_att = ASPPDeformable(in_channels=inter_channels)
1482
+
1483
+ self.conv_out = nn.Conv2d(inter_channels, out_channels, 3, 1, padding=1)
1484
+ self.bn_out = nn.BatchNorm2d(out_channels) if config.batch_size > 1 else nn.Identity()
1485
+
1486
+ self.conv_resi = nn.Conv2d(in_channels, out_channels, 1, 1, 0)
1487
+
1488
+ def forward(self, x):
1489
+ _x = self.conv_resi(x)
1490
+ x = self.conv_in(x)
1491
+ x = self.bn_in(x)
1492
+ x = self.relu_in(x)
1493
+ if hasattr(self, 'dec_att'):
1494
+ x = self.dec_att(x)
1495
+ x = self.conv_out(x)
1496
+ x = self.bn_out(x)
1497
+ return x + _x
1498
+
1499
+
1500
+
1501
+ ### models/modules/lateral_blocks.py
1502
+
1503
+ import numpy as np
1504
+ import torch
1505
+ import torch.nn as nn
1506
+ import torch.nn.functional as F
1507
+ from functools import partial
1508
+
1509
+ # from config import Config
1510
+
1511
+
1512
+ # config = Config()
1513
+
1514
+
1515
+ class BasicLatBlk(nn.Module):
1516
+ def __init__(self, in_channels=64, out_channels=64, inter_channels=64):
1517
+ super(BasicLatBlk, self).__init__()
1518
+ inter_channels = in_channels // 4 if config.dec_channels_inter == 'adap' else 64
1519
+ self.conv = nn.Conv2d(in_channels, out_channels, 1, 1, 0)
1520
+
1521
+ def forward(self, x):
1522
+ x = self.conv(x)
1523
+ return x
1524
+
1525
+
1526
+
1527
+ ### models/modules/aspp.py
1528
+
1529
+ import torch
1530
+ import torch.nn as nn
1531
+ import torch.nn.functional as F
1532
+ # from models.deform_conv import DeformableConv2d
1533
+ # from config import Config
1534
+
1535
+
1536
+ # config = Config()
1537
+
1538
+
1539
+ class _ASPPModule(nn.Module):
1540
+ def __init__(self, in_channels, planes, kernel_size, padding, dilation):
1541
+ super(_ASPPModule, self).__init__()
1542
+ self.atrous_conv = nn.Conv2d(in_channels, planes, kernel_size=kernel_size,
1543
+ stride=1, padding=padding, dilation=dilation, bias=False)
1544
+ self.bn = nn.BatchNorm2d(planes) if config.batch_size > 1 else nn.Identity()
1545
+ self.relu = nn.ReLU(inplace=True)
1546
+
1547
+ def forward(self, x):
1548
+ x = self.atrous_conv(x)
1549
+ x = self.bn(x)
1550
+
1551
+ return self.relu(x)
1552
+
1553
+
1554
+ class ASPP(nn.Module):
1555
+ def __init__(self, in_channels=64, out_channels=None, output_stride=16):
1556
+ super(ASPP, self).__init__()
1557
+ self.down_scale = 1
1558
+ if out_channels is None:
1559
+ out_channels = in_channels
1560
+ self.in_channelster = 256 // self.down_scale
1561
+ if output_stride == 16:
1562
+ dilations = [1, 6, 12, 18]
1563
+ elif output_stride == 8:
1564
+ dilations = [1, 12, 24, 36]
1565
+ else:
1566
+ raise NotImplementedError
1567
+
1568
+ self.aspp1 = _ASPPModule(in_channels, self.in_channelster, 1, padding=0, dilation=dilations[0])
1569
+ self.aspp2 = _ASPPModule(in_channels, self.in_channelster, 3, padding=dilations[1], dilation=dilations[1])
1570
+ self.aspp3 = _ASPPModule(in_channels, self.in_channelster, 3, padding=dilations[2], dilation=dilations[2])
1571
+ self.aspp4 = _ASPPModule(in_channels, self.in_channelster, 3, padding=dilations[3], dilation=dilations[3])
1572
+
1573
+ self.global_avg_pool = nn.Sequential(nn.AdaptiveAvgPool2d((1, 1)),
1574
+ nn.Conv2d(in_channels, self.in_channelster, 1, stride=1, bias=False),
1575
+ nn.BatchNorm2d(self.in_channelster) if config.batch_size > 1 else nn.Identity(),
1576
+ nn.ReLU(inplace=True))
1577
+ self.conv1 = nn.Conv2d(self.in_channelster * 5, out_channels, 1, bias=False)
1578
+ self.bn1 = nn.BatchNorm2d(out_channels) if config.batch_size > 1 else nn.Identity()
1579
+ self.relu = nn.ReLU(inplace=True)
1580
+ self.dropout = nn.Dropout(0.5)
1581
+
1582
+ def forward(self, x):
1583
+ x1 = self.aspp1(x)
1584
+ x2 = self.aspp2(x)
1585
+ x3 = self.aspp3(x)
1586
+ x4 = self.aspp4(x)
1587
+ x5 = self.global_avg_pool(x)
1588
+ x5 = F.interpolate(x5, size=x1.size()[2:], mode='bilinear', align_corners=True)
1589
+ x = torch.cat((x1, x2, x3, x4, x5), dim=1)
1590
+
1591
+ x = self.conv1(x)
1592
+ x = self.bn1(x)
1593
+ x = self.relu(x)
1594
+
1595
+ return self.dropout(x)
1596
+
1597
+
1598
+ ##################### Deformable
1599
+ class _ASPPModuleDeformable(nn.Module):
1600
+ def __init__(self, in_channels, planes, kernel_size, padding):
1601
+ super(_ASPPModuleDeformable, self).__init__()
1602
+ self.atrous_conv = DeformableConv2d(in_channels, planes, kernel_size=kernel_size,
1603
+ stride=1, padding=padding, bias=False)
1604
+ self.bn = nn.BatchNorm2d(planes) if config.batch_size > 1 else nn.Identity()
1605
+ self.relu = nn.ReLU(inplace=True)
1606
+
1607
+ def forward(self, x):
1608
+ x = self.atrous_conv(x)
1609
+ x = self.bn(x)
1610
+
1611
+ return self.relu(x)
1612
+
1613
+
1614
+ class ASPPDeformable(nn.Module):
1615
+ def __init__(self, in_channels, out_channels=None, parallel_block_sizes=[1, 3, 7]):
1616
+ super(ASPPDeformable, self).__init__()
1617
+ self.down_scale = 1
1618
+ if out_channels is None:
1619
+ out_channels = in_channels
1620
+ self.in_channelster = 256 // self.down_scale
1621
+
1622
+ self.aspp1 = _ASPPModuleDeformable(in_channels, self.in_channelster, 1, padding=0)
1623
+ self.aspp_deforms = nn.ModuleList([
1624
+ _ASPPModuleDeformable(in_channels, self.in_channelster, conv_size, padding=int(conv_size//2)) for conv_size in parallel_block_sizes
1625
+ ])
1626
+
1627
+ self.global_avg_pool = nn.Sequential(nn.AdaptiveAvgPool2d((1, 1)),
1628
+ nn.Conv2d(in_channels, self.in_channelster, 1, stride=1, bias=False),
1629
+ nn.BatchNorm2d(self.in_channelster) if config.batch_size > 1 else nn.Identity(),
1630
+ nn.ReLU(inplace=True))
1631
+ self.conv1 = nn.Conv2d(self.in_channelster * (2 + len(self.aspp_deforms)), out_channels, 1, bias=False)
1632
+ self.bn1 = nn.BatchNorm2d(out_channels) if config.batch_size > 1 else nn.Identity()
1633
+ self.relu = nn.ReLU(inplace=True)
1634
+ self.dropout = nn.Dropout(0.5)
1635
+
1636
+ def forward(self, x):
1637
+ x1 = self.aspp1(x)
1638
+ x_aspp_deforms = [aspp_deform(x) for aspp_deform in self.aspp_deforms]
1639
+ x5 = self.global_avg_pool(x)
1640
+ x5 = F.interpolate(x5, size=x1.size()[2:], mode='bilinear', align_corners=True)
1641
+ x = torch.cat((x1, *x_aspp_deforms, x5), dim=1)
1642
+
1643
+ x = self.conv1(x)
1644
+ x = self.bn1(x)
1645
+ x = self.relu(x)
1646
+
1647
+ return self.dropout(x)
1648
+
1649
+
1650
+
1651
+ ### models/refinement/refiner.py
1652
+
1653
+ import torch
1654
+ import torch.nn as nn
1655
+ from collections import OrderedDict
1656
+ import torch
1657
+ import torch.nn as nn
1658
+ import torch.nn.functional as F
1659
+ from torchvision.models import vgg16, vgg16_bn
1660
+ from torchvision.models import resnet50
1661
+
1662
+ # from config import Config
1663
+ # from dataset import class_labels_TR_sorted
1664
+ # from models.build_backbone import build_backbone
1665
+ # from models.decoder_blocks import BasicDecBlk
1666
+ # from models.lateral_blocks import BasicLatBlk
1667
+ # from models.ing import *
1668
+ # from models.stem_layer import StemLayer
1669
+
1670
+
1671
+ class RefinerPVTInChannels4(nn.Module):
1672
+ def __init__(self, in_channels=3+1):
1673
+ super(RefinerPVTInChannels4, self).__init__()
1674
+ self.config = Config()
1675
+ self.epoch = 1
1676
+ self.bb = build_backbone(self.config.bb, params_settings='in_channels=4')
1677
+
1678
+ lateral_channels_in_collection = {
1679
+ 'vgg16': [512, 256, 128, 64], 'vgg16bn': [512, 256, 128, 64], 'resnet50': [1024, 512, 256, 64],
1680
+ 'pvt_v2_b2': [512, 320, 128, 64], 'pvt_v2_b5': [512, 320, 128, 64],
1681
+ 'swin_v1_b': [1024, 512, 256, 128], 'swin_v1_l': [1536, 768, 384, 192],
1682
+ }
1683
+ channels = lateral_channels_in_collection[self.config.bb]
1684
+ self.squeeze_module = BasicDecBlk(channels[0], channels[0])
1685
+
1686
+ self.decoder = Decoder(channels)
1687
+
1688
+ if 0:
1689
+ for key, value in self.named_parameters():
1690
+ if 'bb.' in key:
1691
+ value.requires_grad = False
1692
+
1693
+ def forward(self, x):
1694
+ if isinstance(x, list):
1695
+ x = torch.cat(x, dim=1)
1696
+ ########## Encoder ##########
1697
+ if self.config.bb in ['vgg16', 'vgg16bn', 'resnet50']:
1698
+ x1 = self.bb.conv1(x)
1699
+ x2 = self.bb.conv2(x1)
1700
+ x3 = self.bb.conv3(x2)
1701
+ x4 = self.bb.conv4(x3)
1702
+ else:
1703
+ x1, x2, x3, x4 = self.bb(x)
1704
+
1705
+ x4 = self.squeeze_module(x4)
1706
+
1707
+ ########## Decoder ##########
1708
+
1709
+ features = [x, x1, x2, x3, x4]
1710
+ scaled_preds = self.decoder(features)
1711
+
1712
+ return scaled_preds
1713
+
1714
+
1715
+ class Refiner(nn.Module):
1716
+ def __init__(self, in_channels=3+1):
1717
+ super(Refiner, self).__init__()
1718
+ self.config = Config()
1719
+ self.epoch = 1
1720
+ self.stem_layer = StemLayer(in_channels=in_channels, inter_channels=48, out_channels=3, norm_layer='BN' if self.config.batch_size > 1 else 'LN')
1721
+ self.bb = build_backbone(self.config.bb)
1722
+
1723
+ lateral_channels_in_collection = {
1724
+ 'vgg16': [512, 256, 128, 64], 'vgg16bn': [512, 256, 128, 64], 'resnet50': [1024, 512, 256, 64],
1725
+ 'pvt_v2_b2': [512, 320, 128, 64], 'pvt_v2_b5': [512, 320, 128, 64],
1726
+ 'swin_v1_b': [1024, 512, 256, 128], 'swin_v1_l': [1536, 768, 384, 192],
1727
+ }
1728
+ channels = lateral_channels_in_collection[self.config.bb]
1729
+ self.squeeze_module = BasicDecBlk(channels[0], channels[0])
1730
+
1731
+ self.decoder = Decoder(channels)
1732
+
1733
+ if 0:
1734
+ for key, value in self.named_parameters():
1735
+ if 'bb.' in key:
1736
+ value.requires_grad = False
1737
+
1738
+ def forward(self, x):
1739
+ if isinstance(x, list):
1740
+ x = torch.cat(x, dim=1)
1741
+ x = self.stem_layer(x)
1742
+ ########## Encoder ##########
1743
+ if self.config.bb in ['vgg16', 'vgg16bn', 'resnet50']:
1744
+ x1 = self.bb.conv1(x)
1745
+ x2 = self.bb.conv2(x1)
1746
+ x3 = self.bb.conv3(x2)
1747
+ x4 = self.bb.conv4(x3)
1748
+ else:
1749
+ x1, x2, x3, x4 = self.bb(x)
1750
+
1751
+ x4 = self.squeeze_module(x4)
1752
+
1753
+ ########## Decoder ##########
1754
+
1755
+ features = [x, x1, x2, x3, x4]
1756
+ scaled_preds = self.decoder(features)
1757
+
1758
+ return scaled_preds
1759
+
1760
+
1761
+ class Decoder(nn.Module):
1762
+ def __init__(self, channels):
1763
+ super(Decoder, self).__init__()
1764
+ self.config = Config()
1765
+ DecoderBlock = eval('BasicDecBlk')
1766
+ LateralBlock = eval('BasicLatBlk')
1767
+
1768
+ self.decoder_block4 = DecoderBlock(channels[0], channels[1])
1769
+ self.decoder_block3 = DecoderBlock(channels[1], channels[2])
1770
+ self.decoder_block2 = DecoderBlock(channels[2], channels[3])
1771
+ self.decoder_block1 = DecoderBlock(channels[3], channels[3]//2)
1772
+
1773
+ self.lateral_block4 = LateralBlock(channels[1], channels[1])
1774
+ self.lateral_block3 = LateralBlock(channels[2], channels[2])
1775
+ self.lateral_block2 = LateralBlock(channels[3], channels[3])
1776
+
1777
+ if self.config.ms_supervision:
1778
+ self.conv_ms_spvn_4 = nn.Conv2d(channels[1], 1, 1, 1, 0)
1779
+ self.conv_ms_spvn_3 = nn.Conv2d(channels[2], 1, 1, 1, 0)
1780
+ self.conv_ms_spvn_2 = nn.Conv2d(channels[3], 1, 1, 1, 0)
1781
+ self.conv_out1 = nn.Sequential(nn.Conv2d(channels[3]//2, 1, 1, 1, 0))
1782
+
1783
+ def forward(self, features):
1784
+ x, x1, x2, x3, x4 = features
1785
+ outs = []
1786
+ p4 = self.decoder_block4(x4)
1787
+ _p4 = F.interpolate(p4, size=x3.shape[2:], mode='bilinear', align_corners=True)
1788
+ _p3 = _p4 + self.lateral_block4(x3)
1789
+
1790
+ p3 = self.decoder_block3(_p3)
1791
+ _p3 = F.interpolate(p3, size=x2.shape[2:], mode='bilinear', align_corners=True)
1792
+ _p2 = _p3 + self.lateral_block3(x2)
1793
+
1794
+ p2 = self.decoder_block2(_p2)
1795
+ _p2 = F.interpolate(p2, size=x1.shape[2:], mode='bilinear', align_corners=True)
1796
+ _p1 = _p2 + self.lateral_block2(x1)
1797
+
1798
+ _p1 = self.decoder_block1(_p1)
1799
+ _p1 = F.interpolate(_p1, size=x.shape[2:], mode='bilinear', align_corners=True)
1800
+ p1_out = self.conv_out1(_p1)
1801
+
1802
+ if self.config.ms_supervision:
1803
+ outs.append(self.conv_ms_spvn_4(p4))
1804
+ outs.append(self.conv_ms_spvn_3(p3))
1805
+ outs.append(self.conv_ms_spvn_2(p2))
1806
+ outs.append(p1_out)
1807
+ return outs
1808
+
1809
+
1810
+ class RefUNet(nn.Module):
1811
+ # Refinement
1812
+ def __init__(self, in_channels=3+1):
1813
+ super(RefUNet, self).__init__()
1814
+ self.encoder_1 = nn.Sequential(
1815
+ nn.Conv2d(in_channels, 64, 3, 1, 1),
1816
+ nn.Conv2d(64, 64, 3, 1, 1),
1817
+ nn.BatchNorm2d(64),
1818
+ nn.ReLU(inplace=True)
1819
+ )
1820
+
1821
+ self.encoder_2 = nn.Sequential(
1822
+ nn.MaxPool2d(2, 2, ceil_mode=True),
1823
+ nn.Conv2d(64, 64, 3, 1, 1),
1824
+ nn.BatchNorm2d(64),
1825
+ nn.ReLU(inplace=True)
1826
+ )
1827
+
1828
+ self.encoder_3 = nn.Sequential(
1829
+ nn.MaxPool2d(2, 2, ceil_mode=True),
1830
+ nn.Conv2d(64, 64, 3, 1, 1),
1831
+ nn.BatchNorm2d(64),
1832
+ nn.ReLU(inplace=True)
1833
+ )
1834
+
1835
+ self.encoder_4 = nn.Sequential(
1836
+ nn.MaxPool2d(2, 2, ceil_mode=True),
1837
+ nn.Conv2d(64, 64, 3, 1, 1),
1838
+ nn.BatchNorm2d(64),
1839
+ nn.ReLU(inplace=True)
1840
+ )
1841
+
1842
+ self.pool4 = nn.MaxPool2d(2, 2, ceil_mode=True)
1843
+ #####
1844
+ self.decoder_5 = nn.Sequential(
1845
+ nn.Conv2d(64, 64, 3, 1, 1),
1846
+ nn.BatchNorm2d(64),
1847
+ nn.ReLU(inplace=True)
1848
+ )
1849
+ #####
1850
+ self.decoder_4 = nn.Sequential(
1851
+ nn.Conv2d(128, 64, 3, 1, 1),
1852
+ nn.BatchNorm2d(64),
1853
+ nn.ReLU(inplace=True)
1854
+ )
1855
+
1856
+ self.decoder_3 = nn.Sequential(
1857
+ nn.Conv2d(128, 64, 3, 1, 1),
1858
+ nn.BatchNorm2d(64),
1859
+ nn.ReLU(inplace=True)
1860
+ )
1861
+
1862
+ self.decoder_2 = nn.Sequential(
1863
+ nn.Conv2d(128, 64, 3, 1, 1),
1864
+ nn.BatchNorm2d(64),
1865
+ nn.ReLU(inplace=True)
1866
+ )
1867
+
1868
+ self.decoder_1 = nn.Sequential(
1869
+ nn.Conv2d(128, 64, 3, 1, 1),
1870
+ nn.BatchNorm2d(64),
1871
+ nn.ReLU(inplace=True)
1872
+ )
1873
+
1874
+ self.conv_d0 = nn.Conv2d(64, 1, 3, 1, 1)
1875
+
1876
+ self.upscore2 = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
1877
+
1878
+ def forward(self, x):
1879
+ outs = []
1880
+ if isinstance(x, list):
1881
+ x = torch.cat(x, dim=1)
1882
+ hx = x
1883
+
1884
+ hx1 = self.encoder_1(hx)
1885
+ hx2 = self.encoder_2(hx1)
1886
+ hx3 = self.encoder_3(hx2)
1887
+ hx4 = self.encoder_4(hx3)
1888
+
1889
+ hx = self.decoder_5(self.pool4(hx4))
1890
+ hx = torch.cat((self.upscore2(hx), hx4), 1)
1891
+
1892
+ d4 = self.decoder_4(hx)
1893
+ hx = torch.cat((self.upscore2(d4), hx3), 1)
1894
+
1895
+ d3 = self.decoder_3(hx)
1896
+ hx = torch.cat((self.upscore2(d3), hx2), 1)
1897
+
1898
+ d2 = self.decoder_2(hx)
1899
+ hx = torch.cat((self.upscore2(d2), hx1), 1)
1900
+
1901
+ d1 = self.decoder_1(hx)
1902
+
1903
+ x = self.conv_d0(d1)
1904
+ outs.append(x)
1905
+ return outs
1906
+
1907
+
1908
+
1909
+ ### models/stem_layer.py
1910
+
1911
+ import torch.nn as nn
1912
+ # from utils import build_act_layer, build_norm_layer
1913
+
1914
+
1915
+ class StemLayer(nn.Module):
1916
+ r""" Stem layer of InternImage
1917
+ Args:
1918
+ in_channels (int): number of input channels
1919
+ out_channels (int): number of output channels
1920
+ act_layer (str): activation layer
1921
+ norm_layer (str): normalization layer
1922
+ """
1923
+
1924
+ def __init__(self,
1925
+ in_channels=3+1,
1926
+ inter_channels=48,
1927
+ out_channels=96,
1928
+ act_layer='GELU',
1929
+ norm_layer='BN'):
1930
+ super().__init__()
1931
+ self.conv1 = nn.Conv2d(in_channels,
1932
+ inter_channels,
1933
+ kernel_size=3,
1934
+ stride=1,
1935
+ padding=1)
1936
+ self.norm1 = build_norm_layer(
1937
+ inter_channels, norm_layer, 'channels_first', 'channels_first'
1938
+ )
1939
+ self.act = build_act_layer(act_layer)
1940
+ self.conv2 = nn.Conv2d(inter_channels,
1941
+ out_channels,
1942
+ kernel_size=3,
1943
+ stride=1,
1944
+ padding=1)
1945
+ self.norm2 = build_norm_layer(
1946
+ out_channels, norm_layer, 'channels_first', 'channels_first'
1947
+ )
1948
+
1949
+ def forward(self, x):
1950
+ x = self.conv1(x)
1951
+ x = self.norm1(x)
1952
+ x = self.act(x)
1953
+ x = self.conv2(x)
1954
+ x = self.norm2(x)
1955
+ return x
1956
+
1957
+
1958
+ ### models/birefnet.py
1959
+
1960
+ import torch
1961
+ import torch.nn as nn
1962
+ import torch.nn.functional as F
1963
+ from kornia.filters import laplacian
1964
+ from transformers import PreTrainedModel
1965
+
1966
+ # from config import Config
1967
+ # from dataset import class_labels_TR_sorted
1968
+ # from models.build_backbone import build_backbone
1969
+ # from models.decoder_blocks import BasicDecBlk, ResBlk, HierarAttDecBlk
1970
+ # from models.lateral_blocks import BasicLatBlk
1971
+ # from models.aspp import ASPP, ASPPDeformable
1972
+ # from models.ing import *
1973
+ # from models.refiner import Refiner, RefinerPVTInChannels4, RefUNet
1974
+ # from models.stem_layer import StemLayer
1975
+ from .BiRefNet_config import BiRefNetConfig
1976
+
1977
+
1978
+ class BiRefNet(
1979
+ PreTrainedModel
1980
+ ):
1981
+ config_class = BiRefNetConfig
1982
+ def __init__(self, bb_pretrained=True, config=BiRefNetConfig()):
1983
+ super(BiRefNet, self).__init__(config)
1984
+ bb_pretrained = config.bb_pretrained
1985
+ self.config = Config()
1986
+ self.epoch = 1
1987
+ self.bb = build_backbone(self.config.bb, pretrained=bb_pretrained)
1988
+
1989
+ channels = self.config.lateral_channels_in_collection
1990
+
1991
+ if self.config.auxiliary_classification:
1992
+ self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
1993
+ self.cls_head = nn.Sequential(
1994
+ nn.Linear(channels[0], len(class_labels_TR_sorted))
1995
+ )
1996
+
1997
+ if self.config.squeeze_block:
1998
+ self.squeeze_module = nn.Sequential(*[
1999
+ eval(self.config.squeeze_block.split('_x')[0])(channels[0]+sum(self.config.cxt), channels[0])
2000
+ for _ in range(eval(self.config.squeeze_block.split('_x')[1]))
2001
+ ])
2002
+
2003
+ self.decoder = Decoder(channels)
2004
+
2005
+ if self.config.ender:
2006
+ self.dec_end = nn.Sequential(
2007
+ nn.Conv2d(1, 16, 3, 1, 1),
2008
+ nn.Conv2d(16, 1, 3, 1, 1),
2009
+ nn.ReLU(inplace=True),
2010
+ )
2011
+
2012
+ # refine patch-level segmentation
2013
+ if self.config.refine:
2014
+ if self.config.refine == 'itself':
2015
+ self.stem_layer = StemLayer(in_channels=3+1, inter_channels=48, out_channels=3, norm_layer='BN' if self.config.batch_size > 1 else 'LN')
2016
+ else:
2017
+ self.refiner = eval('{}({})'.format(self.config.refine, 'in_channels=3+1'))
2018
+
2019
+ if self.config.freeze_bb:
2020
+ # Freeze the backbone...
2021
+ print(self.named_parameters())
2022
+ for key, value in self.named_parameters():
2023
+ if 'bb.' in key and 'refiner.' not in key:
2024
+ value.requires_grad = False
2025
+
2026
+ self.post_init()
2027
+
2028
+
2029
+ def forward_enc(self, x):
2030
+ if self.config.bb in ['vgg16', 'vgg16bn', 'resnet50']:
2031
+ x1 = self.bb.conv1(x); x2 = self.bb.conv2(x1); x3 = self.bb.conv3(x2); x4 = self.bb.conv4(x3)
2032
+ else:
2033
+ x1, x2, x3, x4 = self.bb(x)
2034
+ if self.config.mul_scl_ipt == 'cat':
2035
+ B, C, H, W = x.shape
2036
+ x1_, x2_, x3_, x4_ = self.bb(F.interpolate(x, size=(H//2, W//2), mode='bilinear', align_corners=True))
2037
+ x1 = torch.cat([x1, F.interpolate(x1_, size=x1.shape[2:], mode='bilinear', align_corners=True)], dim=1)
2038
+ x2 = torch.cat([x2, F.interpolate(x2_, size=x2.shape[2:], mode='bilinear', align_corners=True)], dim=1)
2039
+ x3 = torch.cat([x3, F.interpolate(x3_, size=x3.shape[2:], mode='bilinear', align_corners=True)], dim=1)
2040
+ x4 = torch.cat([x4, F.interpolate(x4_, size=x4.shape[2:], mode='bilinear', align_corners=True)], dim=1)
2041
+ elif self.config.mul_scl_ipt == 'add':
2042
+ B, C, H, W = x.shape
2043
+ x1_, x2_, x3_, x4_ = self.bb(F.interpolate(x, size=(H//2, W//2), mode='bilinear', align_corners=True))
2044
+ x1 = x1 + F.interpolate(x1_, size=x1.shape[2:], mode='bilinear', align_corners=True)
2045
+ x2 = x2 + F.interpolate(x2_, size=x2.shape[2:], mode='bilinear', align_corners=True)
2046
+ x3 = x3 + F.interpolate(x3_, size=x3.shape[2:], mode='bilinear', align_corners=True)
2047
+ x4 = x4 + F.interpolate(x4_, size=x4.shape[2:], mode='bilinear', align_corners=True)
2048
+ class_preds = self.cls_head(self.avgpool(x4).view(x4.shape[0], -1)) if self.training and self.config.auxiliary_classification else None
2049
+ if self.config.cxt:
2050
+ x4 = torch.cat(
2051
+ (
2052
+ *[
2053
+ F.interpolate(x1, size=x4.shape[2:], mode='bilinear', align_corners=True),
2054
+ F.interpolate(x2, size=x4.shape[2:], mode='bilinear', align_corners=True),
2055
+ F.interpolate(x3, size=x4.shape[2:], mode='bilinear', align_corners=True),
2056
+ ][-len(self.config.cxt):],
2057
+ x4
2058
+ ),
2059
+ dim=1
2060
+ )
2061
+ return (x1, x2, x3, x4), class_preds
2062
+
2063
+ def forward_ori(self, x):
2064
+ ########## Encoder ##########
2065
+ (x1, x2, x3, x4), class_preds = self.forward_enc(x)
2066
+ if self.config.squeeze_block:
2067
+ x4 = self.squeeze_module(x4)
2068
+ ########## Decoder ##########
2069
+ features = [x, x1, x2, x3, x4]
2070
+ if self.training and self.config.out_ref:
2071
+ features.append(laplacian(torch.mean(x, dim=1).unsqueeze(1), kernel_size=5))
2072
+ scaled_preds = self.decoder(features)
2073
+ return scaled_preds, class_preds
2074
+
2075
+ def forward(self, x):
2076
+ scaled_preds, class_preds = self.forward_ori(x)
2077
+ class_preds_lst = [class_preds]
2078
+ return [scaled_preds, class_preds_lst] if self.training else scaled_preds
2079
+
2080
+
2081
+ class Decoder(nn.Module):
2082
+ def __init__(self, channels):
2083
+ super(Decoder, self).__init__()
2084
+ self.config = Config()
2085
+ DecoderBlock = eval(self.config.dec_blk)
2086
+ LateralBlock = eval(self.config.lat_blk)
2087
+
2088
+ if self.config.dec_ipt:
2089
+ self.split = self.config.dec_ipt_split
2090
+ N_dec_ipt = 64
2091
+ DBlock = SimpleConvs
2092
+ ic = 64
2093
+ ipt_cha_opt = 1
2094
+ self.ipt_blk5 = DBlock(2**10*3 if self.split else 3, [N_dec_ipt, channels[0]//8][ipt_cha_opt], inter_channels=ic)
2095
+ self.ipt_blk4 = DBlock(2**8*3 if self.split else 3, [N_dec_ipt, channels[0]//8][ipt_cha_opt], inter_channels=ic)
2096
+ self.ipt_blk3 = DBlock(2**6*3 if self.split else 3, [N_dec_ipt, channels[1]//8][ipt_cha_opt], inter_channels=ic)
2097
+ self.ipt_blk2 = DBlock(2**4*3 if self.split else 3, [N_dec_ipt, channels[2]//8][ipt_cha_opt], inter_channels=ic)
2098
+ self.ipt_blk1 = DBlock(2**0*3 if self.split else 3, [N_dec_ipt, channels[3]//8][ipt_cha_opt], inter_channels=ic)
2099
+ else:
2100
+ self.split = None
2101
+
2102
+ self.decoder_block4 = DecoderBlock(channels[0]+([N_dec_ipt, channels[0]//8][ipt_cha_opt] if self.config.dec_ipt else 0), channels[1])
2103
+ self.decoder_block3 = DecoderBlock(channels[1]+([N_dec_ipt, channels[0]//8][ipt_cha_opt] if self.config.dec_ipt else 0), channels[2])
2104
+ self.decoder_block2 = DecoderBlock(channels[2]+([N_dec_ipt, channels[1]//8][ipt_cha_opt] if self.config.dec_ipt else 0), channels[3])
2105
+ self.decoder_block1 = DecoderBlock(channels[3]+([N_dec_ipt, channels[2]//8][ipt_cha_opt] if self.config.dec_ipt else 0), channels[3]//2)
2106
+ self.conv_out1 = nn.Sequential(nn.Conv2d(channels[3]//2+([N_dec_ipt, channels[3]//8][ipt_cha_opt] if self.config.dec_ipt else 0), 1, 1, 1, 0))
2107
+
2108
+ self.lateral_block4 = LateralBlock(channels[1], channels[1])
2109
+ self.lateral_block3 = LateralBlock(channels[2], channels[2])
2110
+ self.lateral_block2 = LateralBlock(channels[3], channels[3])
2111
+
2112
+ if self.config.ms_supervision:
2113
+ self.conv_ms_spvn_4 = nn.Conv2d(channels[1], 1, 1, 1, 0)
2114
+ self.conv_ms_spvn_3 = nn.Conv2d(channels[2], 1, 1, 1, 0)
2115
+ self.conv_ms_spvn_2 = nn.Conv2d(channels[3], 1, 1, 1, 0)
2116
+
2117
+ if self.config.out_ref:
2118
+ _N = 16
2119
+ self.gdt_convs_4 = nn.Sequential(nn.Conv2d(channels[1], _N, 3, 1, 1), nn.BatchNorm2d(_N) if self.config.batch_size > 1 else nn.Identity(), nn.ReLU(inplace=True))
2120
+ self.gdt_convs_3 = nn.Sequential(nn.Conv2d(channels[2], _N, 3, 1, 1), nn.BatchNorm2d(_N) if self.config.batch_size > 1 else nn.Identity(), nn.ReLU(inplace=True))
2121
+ self.gdt_convs_2 = nn.Sequential(nn.Conv2d(channels[3], _N, 3, 1, 1), nn.BatchNorm2d(_N) if self.config.batch_size > 1 else nn.Identity(), nn.ReLU(inplace=True))
2122
+
2123
+ self.gdt_convs_pred_4 = nn.Sequential(nn.Conv2d(_N, 1, 1, 1, 0))
2124
+ self.gdt_convs_pred_3 = nn.Sequential(nn.Conv2d(_N, 1, 1, 1, 0))
2125
+ self.gdt_convs_pred_2 = nn.Sequential(nn.Conv2d(_N, 1, 1, 1, 0))
2126
+
2127
+ self.gdt_convs_attn_4 = nn.Sequential(nn.Conv2d(_N, 1, 1, 1, 0))
2128
+ self.gdt_convs_attn_3 = nn.Sequential(nn.Conv2d(_N, 1, 1, 1, 0))
2129
+ self.gdt_convs_attn_2 = nn.Sequential(nn.Conv2d(_N, 1, 1, 1, 0))
2130
+
2131
+ def get_patches_batch(self, x, p):
2132
+ _size_h, _size_w = p.shape[2:]
2133
+ patches_batch = []
2134
+ for idx in range(x.shape[0]):
2135
+ columns_x = torch.split(x[idx], split_size_or_sections=_size_w, dim=-1)
2136
+ patches_x = []
2137
+ for column_x in columns_x:
2138
+ patches_x += [p.unsqueeze(0) for p in torch.split(column_x, split_size_or_sections=_size_h, dim=-2)]
2139
+ patch_sample = torch.cat(patches_x, dim=1)
2140
+ patches_batch.append(patch_sample)
2141
+ return torch.cat(patches_batch, dim=0)
2142
+
2143
+ def forward(self, features):
2144
+ if self.training and self.config.out_ref:
2145
+ outs_gdt_pred = []
2146
+ outs_gdt_label = []
2147
+ x, x1, x2, x3, x4, gdt_gt = features
2148
+ else:
2149
+ x, x1, x2, x3, x4 = features
2150
+ outs = []
2151
+
2152
+ if self.config.dec_ipt:
2153
+ patches_batch = self.get_patches_batch(x, x4) if self.split else x
2154
+ x4 = torch.cat((x4, self.ipt_blk5(F.interpolate(patches_batch, size=x4.shape[2:], mode='bilinear', align_corners=True))), 1)
2155
+ p4 = self.decoder_block4(x4)
2156
+ m4 = self.conv_ms_spvn_4(p4) if self.config.ms_supervision else None
2157
+ if self.config.out_ref:
2158
+ p4_gdt = self.gdt_convs_4(p4)
2159
+ if self.training:
2160
+ # >> GT:
2161
+ m4_dia = m4
2162
+ gdt_label_main_4 = gdt_gt * F.interpolate(m4_dia, size=gdt_gt.shape[2:], mode='bilinear', align_corners=True)
2163
+ outs_gdt_label.append(gdt_label_main_4)
2164
+ # >> Pred:
2165
+ gdt_pred_4 = self.gdt_convs_pred_4(p4_gdt)
2166
+ outs_gdt_pred.append(gdt_pred_4)
2167
+ gdt_attn_4 = self.gdt_convs_attn_4(p4_gdt).sigmoid()
2168
+ # >> Finally:
2169
+ p4 = p4 * gdt_attn_4
2170
+ _p4 = F.interpolate(p4, size=x3.shape[2:], mode='bilinear', align_corners=True)
2171
+ _p3 = _p4 + self.lateral_block4(x3)
2172
+
2173
+ if self.config.dec_ipt:
2174
+ patches_batch = self.get_patches_batch(x, _p3) if self.split else x
2175
+ _p3 = torch.cat((_p3, self.ipt_blk4(F.interpolate(patches_batch, size=x3.shape[2:], mode='bilinear', align_corners=True))), 1)
2176
+ p3 = self.decoder_block3(_p3)
2177
+ m3 = self.conv_ms_spvn_3(p3) if self.config.ms_supervision else None
2178
+ if self.config.out_ref:
2179
+ p3_gdt = self.gdt_convs_3(p3)
2180
+ if self.training:
2181
+ # >> GT:
2182
+ # m3 --dilation--> m3_dia
2183
+ # G_3^gt * m3_dia --> G_3^m, which is the label of gradient
2184
+ m3_dia = m3
2185
+ gdt_label_main_3 = gdt_gt * F.interpolate(m3_dia, size=gdt_gt.shape[2:], mode='bilinear', align_corners=True)
2186
+ outs_gdt_label.append(gdt_label_main_3)
2187
+ # >> Pred:
2188
+ # p3 --conv--BN--> F_3^G, where F_3^G predicts the \hat{G_3} with xx
2189
+ # F_3^G --sigmoid--> A_3^G
2190
+ gdt_pred_3 = self.gdt_convs_pred_3(p3_gdt)
2191
+ outs_gdt_pred.append(gdt_pred_3)
2192
+ gdt_attn_3 = self.gdt_convs_attn_3(p3_gdt).sigmoid()
2193
+ # >> Finally:
2194
+ # p3 = p3 * A_3^G
2195
+ p3 = p3 * gdt_attn_3
2196
+ _p3 = F.interpolate(p3, size=x2.shape[2:], mode='bilinear', align_corners=True)
2197
+ _p2 = _p3 + self.lateral_block3(x2)
2198
+
2199
+ if self.config.dec_ipt:
2200
+ patches_batch = self.get_patches_batch(x, _p2) if self.split else x
2201
+ _p2 = torch.cat((_p2, self.ipt_blk3(F.interpolate(patches_batch, size=x2.shape[2:], mode='bilinear', align_corners=True))), 1)
2202
+ p2 = self.decoder_block2(_p2)
2203
+ m2 = self.conv_ms_spvn_2(p2) if self.config.ms_supervision else None
2204
+ if self.config.out_ref:
2205
+ p2_gdt = self.gdt_convs_2(p2)
2206
+ if self.training:
2207
+ # >> GT:
2208
+ m2_dia = m2
2209
+ gdt_label_main_2 = gdt_gt * F.interpolate(m2_dia, size=gdt_gt.shape[2:], mode='bilinear', align_corners=True)
2210
+ outs_gdt_label.append(gdt_label_main_2)
2211
+ # >> Pred:
2212
+ gdt_pred_2 = self.gdt_convs_pred_2(p2_gdt)
2213
+ outs_gdt_pred.append(gdt_pred_2)
2214
+ gdt_attn_2 = self.gdt_convs_attn_2(p2_gdt).sigmoid()
2215
+ # >> Finally:
2216
+ p2 = p2 * gdt_attn_2
2217
+ _p2 = F.interpolate(p2, size=x1.shape[2:], mode='bilinear', align_corners=True)
2218
+ _p1 = _p2 + self.lateral_block2(x1)
2219
+
2220
+ if self.config.dec_ipt:
2221
+ patches_batch = self.get_patches_batch(x, _p1) if self.split else x
2222
+ _p1 = torch.cat((_p1, self.ipt_blk2(F.interpolate(patches_batch, size=x1.shape[2:], mode='bilinear', align_corners=True))), 1)
2223
+ _p1 = self.decoder_block1(_p1)
2224
+ _p1 = F.interpolate(_p1, size=x.shape[2:], mode='bilinear', align_corners=True)
2225
+
2226
+ if self.config.dec_ipt:
2227
+ patches_batch = self.get_patches_batch(x, _p1) if self.split else x
2228
+ _p1 = torch.cat((_p1, self.ipt_blk1(F.interpolate(patches_batch, size=x.shape[2:], mode='bilinear', align_corners=True))), 1)
2229
+ p1_out = self.conv_out1(_p1)
2230
+
2231
+ if self.config.ms_supervision:
2232
+ outs.append(m4)
2233
+ outs.append(m3)
2234
+ outs.append(m2)
2235
+ outs.append(p1_out)
2236
+ return outs if not (self.config.out_ref and self.training) else ([outs_gdt_pred, outs_gdt_label], outs)
2237
+
2238
+
2239
+ class SimpleConvs(nn.Module):
2240
+ def __init__(
2241
+ self, in_channels: int, out_channels: int, inter_channels=64
2242
+ ) -> None:
2243
+ super().__init__()
2244
+ self.conv1 = nn.Conv2d(in_channels, inter_channels, 3, 1, 1)
2245
+ self.conv_out = nn.Conv2d(inter_channels, out_channels, 3, 1, 1)
2246
+
2247
+ def forward(self, x):
2248
+ return self.conv_out(self.conv1(x))
rmbg/config.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_name_or_path": "ZhengPeng7/BiRefNet",
3
+ "architectures": [
4
+ "BiRefNet"
5
+ ],
6
+ "auto_map": {
7
+ "AutoConfig": "BiRefNet_config.BiRefNetConfig",
8
+ "AutoModelForImageSegmentation": "birefnet.BiRefNet"
9
+ },
10
+ "custom_pipelines": {
11
+ "image-segmentation": {
12
+ "pt": [
13
+ "AutoModelForImageSegmentation"
14
+ ],
15
+ "tf": [],
16
+ "type": "image"
17
+ }
18
+ },
19
+ "bb_pretrained": false
20
+ }
rmbg/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4b3234acfc46185b08c279e6aa02c1363f8d3fffa05e3afc845d55f12b8cac3b
3
+ size 343122500
texturing_pipeline.json ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "Trellis2TexturingPipeline",
3
+ "args": {
4
+ "models": {
5
+ "shape_slat_encoder": "ckpts/shape_enc_next_dc_f16c32_fp16",
6
+ "tex_slat_decoder": "ckpts/tex_dec_next_dc_f16c32_fp16",
7
+ "tex_slat_flow_model_512": "ckpts/slat_flow_imgshape2tex_dit_1_3B_512_bf16",
8
+ "tex_slat_flow_model_1024": "ckpts/slat_flow_imgshape2tex_dit_1_3B_1024_bf16"
9
+ },
10
+ "shape_slat_normalization": {
11
+ "mean": [
12
+ 0.781296, 0.018091, -0.495192, -0.558457, 1.060530, 0.093252, 1.518149, -0.933218,
13
+ -0.732996, 2.604095, -0.118341, -2.143904, 0.495076, -2.179512, -2.130751, -0.996944,
14
+ 0.261421, -2.217463, 1.260067, -0.150213, 3.790713, 1.481266, -1.046058, -1.523667,
15
+ -0.059621, 2.220780, 1.621212, 0.877230, 0.567247, -3.175944, -3.186688, 1.578665
16
+ ],
17
+ "std": [
18
+ 5.972266, 4.706852, 5.445010, 5.209927, 5.320220, 4.547237, 5.020802, 5.444004,
19
+ 5.226681, 5.683095, 4.831436, 5.286469, 5.652043, 5.367606, 5.525084, 4.730578,
20
+ 4.805265, 5.124013, 5.530808, 5.619001, 5.103930, 5.417670, 5.269677, 5.547194,
21
+ 5.634698, 5.235274, 6.110351, 5.511298, 6.237273, 4.879207, 5.347008, 5.405691
22
+ ]
23
+ },
24
+ "tex_slat_sampler": {
25
+ "name": "FlowEulerGuidanceIntervalSampler",
26
+ "args": {
27
+ "sigma_min": 1e-5
28
+ },
29
+ "params": {
30
+ "steps": 12,
31
+ "guidance_strength": 1.0,
32
+ "guidance_rescale": 0.0,
33
+ "guidance_interval": [0.6, 0.9],
34
+ "rescale_t": 3.0
35
+ }
36
+ },
37
+ "tex_slat_normalization": {
38
+ "mean": [
39
+ 3.501659, 2.212398, 2.226094, 0.251093, -0.026248, -0.687364, 0.439898, -0.928075,
40
+ 0.029398, -0.339596, -0.869527, 1.038479, -0.972385, 0.126042, -1.129303, 0.455149,
41
+ -1.209521, 2.069067, 0.544735, 2.569128, -0.323407, 2.293000, -1.925608, -1.217717,
42
+ 1.213905, 0.971588, -0.023631, 0.106750, 2.021786, 0.250524, -0.662387, -0.768862
43
+ ],
44
+ "std": [
45
+ 2.665652, 2.743913, 2.765121, 2.595319, 3.037293, 2.291316, 2.144656, 2.911822,
46
+ 2.969419, 2.501689, 2.154811, 3.163343, 2.621215, 2.381943, 3.186697, 3.021588,
47
+ 2.295916, 3.234985, 3.233086, 2.260140, 2.874801, 2.810596, 3.292720, 2.674999,
48
+ 2.680878, 2.372054, 2.451546, 2.353556, 2.995195, 2.379849, 2.786195, 2.775190
49
+ ]
50
+ },
51
+ "image_cond_model": {
52
+ "name": "DinoV3FeatureExtractor",
53
+ "args": {
54
+ "model_name": "facebook/dinov3-vitl16-pretrain-lvd1689m"
55
+ }
56
+ },
57
+ "rembg_model": {
58
+ "name": "BiRefNet",
59
+ "args": {
60
+ "model_name": "briaai/RMBG-2.0"
61
+ }
62
+ }
63
+ }
64
+ }