Spaces:
Sleeping
Sleeping
Add application file
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- README.md +196 -12
- __pycache__/utils.cpython-310.pyc +0 -0
- app.py +68 -0
- cog.yaml +19 -0
- configs/eval5d.yml +38 -0
- data/.gitkeep +0 -0
- datasets.py +211 -0
- demo.ipynb +0 -0
- eval_instructir.py +204 -0
- im_instructir-7d.pt +3 -0
- index.html +440 -0
- lm_instructir-7d.pt +3 -0
- metrics.py +278 -0
- models/__pycache__/instructir.cpython-310.pyc +0 -0
- models/__pycache__/nafnet.cpython-310.pyc +0 -0
- models/__pycache__/nafnet_utils.cpython-310.pyc +0 -0
- models/im_instructir-7d.pt +3 -0
- models/instructir.py +134 -0
- models/lm_instructir-7d.pt +3 -0
- models/nafnet.py +201 -0
- models/nafnet_utils.py +146 -0
- predict.py +113 -0
- requirements.txt +8 -0
- results/.gitkeep +0 -0
- static/1.html +559 -0
- static/Blocks-005a10ea.css +1 -0
- static/Button-3657eefc.css +1 -0
- static/ColorPicker-41813019.css +1 -0
- static/Column-2853eb31.css +1 -0
- static/DropdownArrow-5fa4dd09.css +1 -0
- static/Form-a4a7741e.css +1 -0
- static/Image-003ee87c.css +1 -0
- static/Model3D-98fc2b2c.css +1 -0
- static/ModifyUpload-77b0d4b2.css +1 -0
- static/StaticImage-ede66243.css +1 -0
- static/UploadText-33d53a1c.css +1 -0
- static/a.html +2 -0
- static/academicons.min.css +1 -0
- static/all.min.css +5 -0
- static/all.min.js +0 -0
- static/bootstrap.min.css +0 -0
- static/bulma.min.css +0 -0
- static/css.css +259 -0
- static/css2.css +126 -0
- static/css2_002.css +90 -0
- static/gradio.js +10 -0
- static/icon.css +23 -0
- static/index-3ca142e0.css +1 -0
- static/index-4a8edf2e.css +1 -0
- static/index-8f1feca1.css +1 -0
README.md
CHANGED
@@ -1,12 +1,196 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# InstructIR: High-Quality Image Restoration Following Human Instructions (ECCV 2024)
|
2 |
+
|
3 |
+
[](https://arxiv.org/abs/2401.16468)
|
4 |
+
<a href="https://colab.research.google.com/drive/1OrTvS-i6uLM2Y8kIkq8ZZRwEQxQFchfq?usp=sharing"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="google colab logo"></a>
|
5 |
+
[](https://huggingface.co/spaces/marcosv/InstructIR)
|
6 |
+
[](https://replicate.com/mv-lab/instructir)
|
7 |
+
[](https://huggingface.co/papers/2401.16468)
|
8 |
+
|
9 |
+
|
10 |
+
[Marcos V. Conde](https://mv-lab.github.io/), [Gregor Geigle](https://scholar.google.com/citations?user=uIlyqRwAAAAJ&hl=en), [Radu Timofte](https://scholar.google.com/citations?user=u3MwH5kAAAAJ&hl=en)
|
11 |
+
|
12 |
+
Computer Vision Lab, University of Wuerzburg | Sony PlayStation, FTG
|
13 |
+
|
14 |
+
|
15 |
+
<a href="https://mv-lab.github.io/InstructIR/"><img src="images/instructir.gif" alt="InstructIR" width=100%></a>
|
16 |
+
|
17 |
+
Video courtesy of Gradio ([see their post about InstructIR](https://twitter.com/Gradio/status/1752776176811041049)). Also shoutout to AK -- [see his tweet](https://twitter.com/_akhaliq/status/1752551364566126798).
|
18 |
+
|
19 |
+
|
20 |
+
### TL;DR: quickstart
|
21 |
+
InstructIR takes as input an image and a human-written instruction for how to improve that image. The neural model performs all-in-one image restoration. InstructIR achieves state-of-the-art results on several restoration tasks including image denoising, deraining, deblurring, dehazing, and (low-light) image enhancement.
|
22 |
+
|
23 |
+
**🚀 You can start with the [demo tutorial](demo.ipynb)**
|
24 |
+
|
25 |
+
<details>
|
26 |
+
<summary> <b> Abstract</b> (click me to read)</summary>
|
27 |
+
<p>
|
28 |
+
Image restoration is a fundamental problem that involves recovering a high-quality clean image from its degraded observation. All-In-One image restoration models can effectively restore images from various types and levels of degradation using degradation-specific information as prompts to guide the restoration model. In this work, we present the first approach that uses human-written instructions to guide the image restoration model. Given natural language prompts, our model can recover high-quality images from their degraded counterparts, considering multiple degradation types. Our method, InstructIR, achieves state-of-the-art results on several restoration tasks including image denoising, deraining, deblurring, dehazing, and (low-light) image enhancement. InstructIR improves +1dB over previous all-in-one restoration methods. Moreover, our dataset and results represent a novel benchmark for new research on text-guided image restoration and enhancement.
|
29 |
+
</p>
|
30 |
+
</details>
|
31 |
+
|
32 |
+
|
33 |
+
### TODO / News 🔥
|
34 |
+
|
35 |
+
- [ ] Upload Model weights and results for other InstructIR variants (3D, 5D).
|
36 |
+
|
37 |
+
- [x] [download all the test datasets](https://drive.google.com/file/d/11wGsKOMDVrBlsle4xtzORPLZAsGhel8c/view?usp=sharing) for all-in-one restoration.
|
38 |
+
|
39 |
+
- [x] check the instructions below to run `eval_instructir.py` and get all the metrics and results for all-in-one restoration.
|
40 |
+
|
41 |
+
- [x] You can download all the qualitative results here [instructir_results.zip](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip)
|
42 |
+
|
43 |
+
- [x] Upload models to HF 🤗 [(download the models here)](https://huggingface.co/marcosv/InstructIR)
|
44 |
+
|
45 |
+
- [x] 🤗 [Hugging Face Demo](https://huggingface.co/spaces/marcosv/InstructIR) try it now
|
46 |
+
|
47 |
+
- [x] [Google Colab Tutorial](https://colab.research.google.com/drive/1OrTvS-i6uLM2Y8kIkq8ZZRwEQxQFchfq?usp=sharing) (check [demo.ipynb](demo.ipynb))
|
48 |
+
|
49 |
+
### Try it / Tutorial
|
50 |
+
|
51 |
+
[Try it]((https://huggingface.co/spaces/marcosv/InstructIR)) directly on 🤗 Hugging Face at no cost, no code.
|
52 |
+
|
53 |
+
|
54 |
+
🚀 You can start with the [demo tutorial](demo.ipynb). We also host the same tutorial on [google colab](https://colab.research.google.com/drive/1OrTvS-i6uLM2Y8kIkq8ZZRwEQxQFchfq?usp=sharing) so you can run it using free GPUs!.
|
55 |
+
|
56 |
+
|
57 |
+
<a href="https://mv-lab.github.io/InstructIR/"><img src="images/instructir_teaser.png" alt="InstructIR" width=100%></a>
|
58 |
+
|
59 |
+
## Results
|
60 |
+
|
61 |
+
Check `test.py` and `eval_instructir.py`. The following command provides all the metric for all the benchmarks using the pre-trained models in `models/`. The results from InstructIR are saved in the indicated folder `results/`
|
62 |
+
|
63 |
+
```
|
64 |
+
python eval_instructir.py --model models/im_instructir-7d.pt --lm models/lm_instructir-7d.pt --device 0 --config configs/eval5d.yml --save results/
|
65 |
+
```
|
66 |
+
|
67 |
+
An example of the output log is:
|
68 |
+
|
69 |
+
```
|
70 |
+
>>> Eval on CBSD68_15 noise 0
|
71 |
+
CBSD68_15_base 24.84328738380881
|
72 |
+
CBSD68_15_psnr 33.98722295200123 68
|
73 |
+
CBSD68_15_ssim 0.9315137801801457
|
74 |
+
|
75 |
+
....
|
76 |
+
```
|
77 |
+
|
78 |
+
You can **[download all the test datasets](https://drive.google.com/file/d/11wGsKOMDVrBlsle4xtzORPLZAsGhel8c/view?usp=sharing)**, and locate them in `test-data/`. Make sure the paths are updated in the config file `configs/eval5d.yml`.
|
79 |
+
|
80 |
+
-------
|
81 |
+
|
82 |
+
You can **[download all the paper results](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip)** -check releases-. We test InstructIR in the following benchmarks:
|
83 |
+
|
84 |
+
| Dataset | Task | Test Results |
|
85 |
+
| :---------------- | :------ | ----: |
|
86 |
+
| BSD68 | Denoising | [Download](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) |
|
87 |
+
| Urban100 | Denoising | [Download](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) |
|
88 |
+
| Rain100 | Deraining | [Download](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) |
|
89 |
+
| [GoPro](https://seungjunnah.github.io/Datasets/gopro) | Deblurring | [Download](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) |
|
90 |
+
| [LOL](https://daooshee.github.io/BMVC2018website/) | Lol Image Enhancement | [Download](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) |
|
91 |
+
| [MIT5K](https://data.csail.mit.edu/graphics/fivek/) | Image Enhancement | [Download](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) |
|
92 |
+
|
93 |
+
In releases or clicking the link above you can download [instructir_results.zip](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) which includes all the qualitative results for those datasets [1.9 Gbs].
|
94 |
+
|
95 |
+
|
96 |
+
<img src="static/tables/table1.png" width=100%>
|
97 |
+
|
98 |
+
<br>
|
99 |
+
|
100 |
+
<details>
|
101 |
+
<summary> <b> Multi-task Results on Dehazing, Deraining, Denoising </b> </summary>
|
102 |
+
<img src="static/tables/table-3d.png" width=100%>
|
103 |
+
</details>
|
104 |
+
|
105 |
+
<details>
|
106 |
+
<summary> <b> Denoising Results (click to read) </b> </summary>
|
107 |
+
<img src="static/tables/table-dn.png" width=100%>
|
108 |
+
</details>
|
109 |
+
|
110 |
+
<details>
|
111 |
+
<summary> <b> Low-light Image Enhancement (LOL) Results (click to read) </b> </summary>
|
112 |
+
<img src="static/tables/table-lol.png" width=100%>
|
113 |
+
</details>
|
114 |
+
|
115 |
+
<details>
|
116 |
+
<summary> <b> Color Image Enhancement (MIT5K) Results (click to read) </b> </summary>
|
117 |
+
<img src="static/tables/table-mit5k.png" width=100%>
|
118 |
+
</details>
|
119 |
+
|
120 |
+
<br>
|
121 |
+
|
122 |
+
--------
|
123 |
+
|
124 |
+
### Control and Interact
|
125 |
+
|
126 |
+
Sometimes the blur, rain, or film grain noise are pleasant effects and part of the **"aesthetics"**. Here we show a simple example on how to interact with InstructIR.
|
127 |
+
|
128 |
+
| Input |(1) I love this photo, could you remove the raindrops? please keep the content intact | (2) Can you make it look stunning? like a professional photo |
|
129 |
+
| --- | :---- | :--- |
|
130 |
+
| <img src="images/rain-020.png" width=100%> | <img src="images/results/result1.png" width=95%> | <img src="images/results/result2.png" width=100%> |
|
131 |
+
| Input |(1) my image is too dark, I cannot see anything, can you fix it? | (2) Great it looks nice! can you apply tone mapping? |
|
132 |
+
| <img src="images/lol_748.png" width=100%> | <img src="images/results/resultlol1.png" width=95%> | <img src="images/results/resultlol2.png" width=100%> |
|
133 |
+
| Input |(1) can you remove the tiny dots in the image? it is very unpleasant | (2) now please inprove the quality and resolution of the picture |
|
134 |
+
| <img src="images/frog.png" width=100%> | <img src="images/results/resultns1.png" width=95%> | <img src="images/results/resultns2.png" width=100%> |
|
135 |
+
|
136 |
+
|
137 |
+
As you can see our model accepts diverse humman-written prompts, from ambiguous to precise instructions. *How does it work?* Imagine we have the following image as input:
|
138 |
+
|
139 |
+
<img src="images/rain-020.png" width=50%>
|
140 |
+
|
141 |
+
Now we can use InstructIR. with the following prompt (1):
|
142 |
+
> I love this photo, could you remove the raindrops? please keep the content intact
|
143 |
+
|
144 |
+
<img src="images/results/result1.png" width=50%>
|
145 |
+
|
146 |
+
Now, let's enhance the image a bit further (2).
|
147 |
+
> Can you make it look stunning? like a professional photo
|
148 |
+
|
149 |
+
<img src="images/results/result2.png" width=50%>
|
150 |
+
|
151 |
+
The final result looks indeed stunning 🤗 You can do it yourself in the [demo tutorial]().
|
152 |
+
|
153 |
+
### FAQS
|
154 |
+
|
155 |
+
> Disclaimer: please remember this is not a product, thus, you will notice some limitations. As most all-in-one restoration methods, it struggles to generalize on real-world images -- we are working on improving it.
|
156 |
+
|
157 |
+
- ***How should I start?*** Check our [demo Tutorial](demo.ipynb) and also our [google collab](https://colab.research.google.com/drive/1OrTvS-i6uLM2Y8kIkq8ZZRwEQxQFchfq?usp=sharing) notebook.
|
158 |
+
|
159 |
+
- ***How can I compare with your method?*** You can download the results for several benchmarks above on [Results](###Results).
|
160 |
+
|
161 |
+
- ***How can I test the model? I just want to play with it***: Visit our 🤗 [Hugging Face demo](https://huggingface.co/spaces/marcosv/InstructIR) and test ir for free,
|
162 |
+
|
163 |
+
- ***Why aren't you using diffusion-based models?*** (1) We want to keep the solution simple and efficient. (2) Our priority is high-fidelity --as in many industry scenarios realted to computational photography--.
|
164 |
+
|
165 |
+
### Gradio Demo <a href='https://github.com/gradio-app/gradio'><img src='https://img.shields.io/github/stars/gradio-app/gradio'></a>
|
166 |
+
We made a simple [Gradio demo](app.py) you can run (locally) on your machine [here](app.py). You need Python>=3.9 and [these requirements](requirements_gradio.txt) for it: `pip install -r requirements_gradio.txt`
|
167 |
+
|
168 |
+
```
|
169 |
+
python app.py
|
170 |
+
```
|
171 |
+
|
172 |
+
<br>
|
173 |
+
<a href="https://huggingface.co/spaces/marcosv/InstructIR">
|
174 |
+
<img src="images/gradio.png" alt="InstructIR Gradio">
|
175 |
+
</a>
|
176 |
+
|
177 |
+
|
178 |
+
### Acknowledgments
|
179 |
+
This work was partly supported by the The Humboldt Foundation (AvH). Marcos Conde is also supported by Sony Interactive Entertainment, FTG.
|
180 |
+
|
181 |
+
This work is inspired in [InstructPix2Pix](https://arxiv.org/abs/2211.09800).
|
182 |
+
|
183 |
+
### Contacts
|
184 |
+
For any inquiries contact Marcos V. Conde: <a href="mailto:[email protected]">marcos.conde [at] uni-wuerzburg.de</a>
|
185 |
+
|
186 |
+
|
187 |
+
### Citation BibTeX
|
188 |
+
|
189 |
+
```
|
190 |
+
@inproceedings{conde2024high,
|
191 |
+
title={InstructIR: High-Quality Image Restoration Following Human Instructions},
|
192 |
+
author={Conde, Marcos V and Geigle, Gregor and Timofte, Radu},
|
193 |
+
booktitle = {Proceedings of the European Conference on Computer Vision (ECCV)},
|
194 |
+
year={2024}
|
195 |
+
}
|
196 |
+
```
|
__pycache__/utils.cpython-310.pyc
ADDED
Binary file (2.8 kB). View file
|
|
app.py
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import torch
|
3 |
+
import numpy as np
|
4 |
+
from PIL import Image
|
5 |
+
import yaml
|
6 |
+
import os
|
7 |
+
from utils import load_img, plot_all, dict2namespace, seed_everything
|
8 |
+
from models import instructir
|
9 |
+
from text.models import LanguageModel, LMHead
|
10 |
+
|
11 |
+
# Setup
|
12 |
+
SEED = 42
|
13 |
+
seed_everything(SEED=SEED)
|
14 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
15 |
+
|
16 |
+
CONFIG = "configs/eval5d.yml"
|
17 |
+
LM_MODEL = "models/lm_instructir-7d.pt"
|
18 |
+
MODEL_NAME = "models/im_instructir-7d.pt"
|
19 |
+
|
20 |
+
# Load config
|
21 |
+
with open(CONFIG, "r") as f:
|
22 |
+
config = yaml.safe_load(f)
|
23 |
+
cfg = dict2namespace(config)
|
24 |
+
|
25 |
+
# Load image model
|
26 |
+
model = instructir.create_model(
|
27 |
+
input_channels=cfg.model.in_ch,
|
28 |
+
width=cfg.model.width,
|
29 |
+
enc_blks=cfg.model.enc_blks,
|
30 |
+
middle_blk_num=cfg.model.middle_blk_num,
|
31 |
+
dec_blks=cfg.model.dec_blks,
|
32 |
+
txtdim=cfg.model.textdim
|
33 |
+
).to(device)
|
34 |
+
model.load_state_dict(torch.load(MODEL_NAME, map_location=device), strict=True)
|
35 |
+
model.eval()
|
36 |
+
|
37 |
+
# Load language model
|
38 |
+
language_model = LanguageModel(model=cfg.llm.model)
|
39 |
+
lm_head = LMHead(embedding_dim=cfg.llm.model_dim, hidden_dim=cfg.llm.embd_dim, num_classes=cfg.llm.nclasses)
|
40 |
+
lm_head.load_state_dict(torch.load(LM_MODEL, map_location=device), strict=True)
|
41 |
+
lm_head.eval()
|
42 |
+
|
43 |
+
def process(image, prompt):
|
44 |
+
image = image.convert("RGB")
|
45 |
+
image = np.array(image).astype(np.float32) / 255.0
|
46 |
+
y = torch.tensor(image).permute(2, 0, 1).unsqueeze(0).to(device)
|
47 |
+
|
48 |
+
lm_embd = language_model(prompt)
|
49 |
+
text_embd, _ = lm_head(lm_embd)
|
50 |
+
x_hat = model(y, text_embd)
|
51 |
+
|
52 |
+
restored = x_hat[0].permute(1, 2, 0).cpu().detach().numpy()
|
53 |
+
restored = np.clip(restored, 0., 1.)
|
54 |
+
restored = (restored * 255).astype(np.uint8)
|
55 |
+
return Image.fromarray(restored)
|
56 |
+
|
57 |
+
interface = gr.Interface(
|
58 |
+
fn=process,
|
59 |
+
inputs=[
|
60 |
+
gr.Image(type="pil"),
|
61 |
+
gr.Textbox(label="Prompt", placeholder="Describe the restoration..."),
|
62 |
+
],
|
63 |
+
outputs=gr.Image(type="pil"),
|
64 |
+
title="swiftlens: Prompt-Guided Image Restoration"
|
65 |
+
)
|
66 |
+
|
67 |
+
if __name__ == "__main__":
|
68 |
+
interface.launch()
|
cog.yaml
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Configuration for Cog ⚙️
|
2 |
+
# Reference: https://github.com/replicate/cog/blob/main/docs/yaml.md
|
3 |
+
|
4 |
+
build:
|
5 |
+
gpu: true
|
6 |
+
system_packages:
|
7 |
+
- "libgl1-mesa-glx"
|
8 |
+
- "libglib2.0-0"
|
9 |
+
python_version: "3.11"
|
10 |
+
python_packages:
|
11 |
+
- torch==2.0.1
|
12 |
+
- transformers==4.37.2
|
13 |
+
- PyYAML==6.0.1
|
14 |
+
- Pillow==10.2.0
|
15 |
+
- sentence-transformers==2.3.0
|
16 |
+
- opencv-python==4.9.0.80
|
17 |
+
- matplotlib==3.8.2
|
18 |
+
- imageio==2.33.1
|
19 |
+
predict: "predict.py:Predictor"
|
configs/eval5d.yml
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
llm:
|
2 |
+
model: 'TaylorAI/bge-micro-v2' # See Paper Sec. 3.2 and Appendix
|
3 |
+
model_dim: 384
|
4 |
+
embd_dim: 256
|
5 |
+
nclasses: 7 # noise, blur, rain, haze, lol, enhancement, upsampling (Paper Sec. 4.3)
|
6 |
+
weights: False
|
7 |
+
|
8 |
+
model:
|
9 |
+
arch: "instructir"
|
10 |
+
use_text: True
|
11 |
+
in_ch: 3
|
12 |
+
out_ch: 3
|
13 |
+
width : 32
|
14 |
+
enc_blks: [2, 2, 4, 8]
|
15 |
+
middle_blk_num: 4
|
16 |
+
dec_blks: [2, 2, 2, 2]
|
17 |
+
textdim: 256
|
18 |
+
weights: False
|
19 |
+
|
20 |
+
test:
|
21 |
+
batch_size: 1
|
22 |
+
num_workers: 3
|
23 |
+
|
24 |
+
dn_datapath: "test-data/denoising_testsets/"
|
25 |
+
dn_datasets: ["CBSD68", "urban100", "Kodak24"]
|
26 |
+
dn_sigmas: [15, 25, 50]
|
27 |
+
|
28 |
+
rain_targets: ["test-data/Rain100L/target/"]
|
29 |
+
rain_inputs: ["test-data/Rain100L/input/"]
|
30 |
+
|
31 |
+
haze_targets: "test-data/SOTS/GT/"
|
32 |
+
haze_inputs : "test-data/SOTS/IN/"
|
33 |
+
|
34 |
+
lol_targets: "test-data/LOL/high/"
|
35 |
+
lol_inputs : "test-data/LOL/low/"
|
36 |
+
|
37 |
+
gopro_targets: "test-data/GoPro/target/"
|
38 |
+
gopro_inputs: "test-data/GoPro/input/"
|
data/.gitkeep
ADDED
File without changes
|
datasets.py
ADDED
@@ -0,0 +1,211 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch.nn.functional as F
|
2 |
+
from torch.utils.data import DataLoader, Dataset
|
3 |
+
import torchvision
|
4 |
+
import torchvision.transforms.functional as TF
|
5 |
+
import numpy as np
|
6 |
+
import json
|
7 |
+
import os
|
8 |
+
from glob import glob
|
9 |
+
|
10 |
+
from utils import load_img, modcrop
|
11 |
+
|
12 |
+
|
13 |
+
DEG_MAP = {
|
14 |
+
"noise": 0,
|
15 |
+
"blur" : 1,
|
16 |
+
"rain" : 2,
|
17 |
+
"haze" : 3,
|
18 |
+
"lol" : 4,
|
19 |
+
"sr" : 5,
|
20 |
+
"en" : 6,
|
21 |
+
}
|
22 |
+
|
23 |
+
DEG2TASK = {
|
24 |
+
"noise": "denoising",
|
25 |
+
"blur" : "deblurring",
|
26 |
+
"rain" : "deraining",
|
27 |
+
"haze" : "dehazing",
|
28 |
+
"lol" : "lol",
|
29 |
+
"sr" : "sr",
|
30 |
+
"en" : "enhancement"
|
31 |
+
}
|
32 |
+
|
33 |
+
def augment_prompt (prompt):
|
34 |
+
### special prompts
|
35 |
+
lol_prompts = ["fix the illumination", "increase the exposure of the photo", "the image is too dark to see anything, correct the photo", "poor illumination, improve the shot", "brighten dark regions", "make it HDR", "improve the light of the image", "Can you make the image brighter?"]
|
36 |
+
sr_prompts = ["I need to enhance the size and quality of this image.", "My photo is lacking size and clarity; can you improve it?", "I'd appreciate it if you could upscale this photo.", "My picture is too little, enlarge it.", "upsample this image", "increase the resolution of this photo", "increase the number of pixels", "upsample this photo", "Add details to this image", "improve the quality of this photo"]
|
37 |
+
en_prompts = ["make my image look like DSLR", "improve the colors of my image", "improve the contrast of this photo", "apply tonemapping", "enhance the colors of the image", "retouch the photo like a photograper"]
|
38 |
+
|
39 |
+
init = np.random.choice(["Remove the", "Reduce the", "Clean the", "Fix the", "Remove", "Improve the", "Correct the",])
|
40 |
+
end = np.random.choice(["please", "fast", "now", "in the photo", "in the picture", "in the image", ""])
|
41 |
+
newp = f"{init} {prompt} {end}"
|
42 |
+
|
43 |
+
if "lol" in prompt:
|
44 |
+
newp = np.random.choice(lol_prompts)
|
45 |
+
elif "sr" in prompt:
|
46 |
+
newp = np.random.choice(sr_prompts)
|
47 |
+
elif "en" in prompt:
|
48 |
+
newp = np.random.choice(en_prompts)
|
49 |
+
|
50 |
+
newp = newp.strip().replace(" ", " ").replace("\n", "")
|
51 |
+
return newp
|
52 |
+
|
53 |
+
def get_deg_name(path):
|
54 |
+
"""
|
55 |
+
Get the degradation name from the path
|
56 |
+
"""
|
57 |
+
|
58 |
+
if ("gopro" in path) or ("GoPro" in path) or ("blur" in path) or ("Blur" in path) or ("RealBlur" in path):
|
59 |
+
return "blur"
|
60 |
+
elif ("SOTS" in path) or ("haze" in path) or ("sots" in path) or ("RESIDE" in path):
|
61 |
+
return "haze"
|
62 |
+
elif ("LOL" in path):
|
63 |
+
return "lol"
|
64 |
+
elif ("fiveK" in path):
|
65 |
+
return "en"
|
66 |
+
elif ("super" in path) or ("classicalSR" in path):
|
67 |
+
return "sr"
|
68 |
+
elif ("Rain100" in path) or ("rain13k" in path) or ("Rain13k" in path):
|
69 |
+
return "rain"
|
70 |
+
else:
|
71 |
+
return "noise"
|
72 |
+
|
73 |
+
def crop_img(image, base=16):
|
74 |
+
"""
|
75 |
+
Mod crop the image to ensure the dimension is divisible by base. Also done by SwinIR, Restormer and others.
|
76 |
+
"""
|
77 |
+
h = image.shape[0]
|
78 |
+
w = image.shape[1]
|
79 |
+
crop_h = h % base
|
80 |
+
crop_w = w % base
|
81 |
+
return image[crop_h // 2:h - crop_h + crop_h // 2, crop_w // 2:w - crop_w + crop_w // 2, :]
|
82 |
+
|
83 |
+
|
84 |
+
################# DATASETS
|
85 |
+
|
86 |
+
|
87 |
+
class RefDegImage(Dataset):
|
88 |
+
"""
|
89 |
+
Dataset for Image Restoration having low-quality image and the reference image.
|
90 |
+
Tasks: synthetic denoising, deblurring, super-res, etc.
|
91 |
+
"""
|
92 |
+
|
93 |
+
def __init__(self, hq_img_paths, lq_img_paths, augmentations=None, val=False, name="test", deg_name="noise", deg_class=0):
|
94 |
+
|
95 |
+
assert len(hq_img_paths) == len(lq_img_paths)
|
96 |
+
|
97 |
+
self.hq_paths = hq_img_paths
|
98 |
+
self.lq_paths = lq_img_paths
|
99 |
+
self.totensor = torchvision.transforms.ToTensor()
|
100 |
+
self.val = val
|
101 |
+
self.augs = augmentations
|
102 |
+
self.name = name
|
103 |
+
self.degradation = deg_name
|
104 |
+
self.deg_class = deg_class
|
105 |
+
|
106 |
+
if self.val:
|
107 |
+
self.augs = None # No augmentations during validation/test
|
108 |
+
|
109 |
+
def __len__(self):
|
110 |
+
return len(self.hq_paths)
|
111 |
+
|
112 |
+
def __getitem__(self, idx):
|
113 |
+
hq_path = self.hq_paths[idx]
|
114 |
+
lq_path = self.lq_paths[idx]
|
115 |
+
|
116 |
+
hq_image = load_img(hq_path)
|
117 |
+
lq_image = load_img(lq_path)
|
118 |
+
|
119 |
+
if self.val:
|
120 |
+
# if an image has an odd number dimension we trim for example from [321, 189] to [320, 188].
|
121 |
+
hq_image = crop_img(hq_image)
|
122 |
+
lq_image = crop_img(lq_image)
|
123 |
+
|
124 |
+
hq_image = self.totensor(hq_image.astype(np.float32))
|
125 |
+
lq_image = self.totensor(lq_image.astype(np.float32))
|
126 |
+
|
127 |
+
return hq_image, lq_image, hq_path
|
128 |
+
|
129 |
+
|
130 |
+
|
131 |
+
def create_testsets (testsets, debug=False):
|
132 |
+
"""
|
133 |
+
Given a list of testsets create pytorch datasets for each.
|
134 |
+
The method requires the paths to references and noisy images.
|
135 |
+
"""
|
136 |
+
assert len(testsets) > 0
|
137 |
+
|
138 |
+
if debug:
|
139 |
+
print (20*'****')
|
140 |
+
print ("Creating Testsets", len(testsets))
|
141 |
+
|
142 |
+
datasets = []
|
143 |
+
for testdt in testsets:
|
144 |
+
|
145 |
+
path_hq , path_lq = testdt[0], testdt[1]
|
146 |
+
if debug: print (path_hq , path_lq)
|
147 |
+
|
148 |
+
if ("denoising" in path_hq) or ("jpeg" in path_hq):
|
149 |
+
dataset_name = path_hq.split("/")[-1]
|
150 |
+
dataset_sigma = path_lq.split("/")[-1].split("_")[-1].split(".")[0]
|
151 |
+
dataset_name = dataset_name+ f"_{dataset_sigma}"
|
152 |
+
elif "Rain" in path_hq:
|
153 |
+
if "Rain100L" in path_hq:
|
154 |
+
dataset_name = "Rain100L"
|
155 |
+
else:
|
156 |
+
dataset_name = path_hq.split("/")[3]
|
157 |
+
|
158 |
+
elif ("gopro" in path_hq) or ("GoPro" in path_hq):
|
159 |
+
dataset_name = "GoPro"
|
160 |
+
elif "LOL" in path_hq:
|
161 |
+
dataset_name = "LOL"
|
162 |
+
elif "SOTS" in path_hq:
|
163 |
+
dataset_name = "SOTS"
|
164 |
+
elif "fiveK" in path_hq:
|
165 |
+
dataset_name = "MIT5K"
|
166 |
+
else:
|
167 |
+
assert False, f"{path_hq} - unknown dataset"
|
168 |
+
|
169 |
+
hq_img_paths = sorted(glob(os.path.join(path_hq, "*")))
|
170 |
+
lq_img_paths = sorted(glob(os.path.join(path_lq, "*")))
|
171 |
+
|
172 |
+
if "SOTS" in path_hq:
|
173 |
+
# Haze removal SOTS test dataset
|
174 |
+
dataset_name = "SOTS"
|
175 |
+
hq_img_paths = sorted(glob(os.path.join(path_hq, "*.jpg")))
|
176 |
+
assert len(hq_img_paths) == 500
|
177 |
+
|
178 |
+
lq_img_paths = [file.replace("GT", "IN") for file in hq_img_paths]
|
179 |
+
|
180 |
+
if "fiveK" in path_hq:
|
181 |
+
dataset_name = "MIT5K"
|
182 |
+
testf = "test-data/mit5k/test.txt"
|
183 |
+
f = open(testf, "r")
|
184 |
+
test_ids = f.readlines()
|
185 |
+
test_ids = [x.strip() for x in test_ids]
|
186 |
+
f.close()
|
187 |
+
hq_img_paths = [os.path.join(path_hq, f"{x}.jpg") for x in test_ids]
|
188 |
+
lq_img_paths = [x.replace("expertC", "input") for x in hq_img_paths]
|
189 |
+
assert len(hq_img_paths) == 498
|
190 |
+
|
191 |
+
if "gopro" in path_hq:
|
192 |
+
assert len(hq_img_paths) == 1111
|
193 |
+
|
194 |
+
if "LOL" in path_hq:
|
195 |
+
assert len(hq_img_paths) == 15
|
196 |
+
|
197 |
+
assert len(hq_img_paths) == len(lq_img_paths)
|
198 |
+
|
199 |
+
deg_name = get_deg_name(path_hq)
|
200 |
+
deg_class = DEG_MAP[deg_name]
|
201 |
+
|
202 |
+
valdts = RefDegImage(hq_img_paths = hq_img_paths,
|
203 |
+
lq_img_paths = lq_img_paths,
|
204 |
+
val = True, name= dataset_name, deg_name=deg_name, deg_class=deg_class)
|
205 |
+
|
206 |
+
datasets.append(valdts)
|
207 |
+
|
208 |
+
assert len(datasets) == len(testsets)
|
209 |
+
print (20*'****')
|
210 |
+
|
211 |
+
return datasets
|
demo.ipynb
ADDED
The diff for this file is too large to render.
See raw diff
|
|
eval_instructir.py
ADDED
@@ -0,0 +1,204 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
from torch import nn
|
3 |
+
import torch.nn.functional as F
|
4 |
+
from torch.utils.data import DataLoader, Dataset
|
5 |
+
import torchvision
|
6 |
+
import torchvision.transforms.functional as TF
|
7 |
+
|
8 |
+
import json
|
9 |
+
import os
|
10 |
+
from PIL import Image
|
11 |
+
import numpy as np
|
12 |
+
import matplotlib.pyplot as plt
|
13 |
+
import yaml
|
14 |
+
import random
|
15 |
+
import gc
|
16 |
+
|
17 |
+
from utils import *
|
18 |
+
from models import instructir
|
19 |
+
|
20 |
+
from text.models import LanguageModel, LMHead
|
21 |
+
|
22 |
+
from test import test_model
|
23 |
+
|
24 |
+
|
25 |
+
def seed_everything(SEED=42):
|
26 |
+
random.seed(SEED)
|
27 |
+
np.random.seed(SEED)
|
28 |
+
torch.manual_seed(SEED)
|
29 |
+
torch.cuda.manual_seed(SEED)
|
30 |
+
torch.cuda.manual_seed_all(SEED)
|
31 |
+
torch.backends.cudnn.benchmark = True
|
32 |
+
|
33 |
+
|
34 |
+
if __name__=="__main__":
|
35 |
+
|
36 |
+
parser = argparse.ArgumentParser()
|
37 |
+
parser.add_argument('--config', type=str, default='configs/eval5d.yml', help='Path to config file')
|
38 |
+
parser.add_argument('--model', type=str, default="models/im_instructir-7d.pt", help='Path to the image model weights')
|
39 |
+
parser.add_argument('--lm', type=str, default="models/lm_instructir-7d.pt", help='Path to the language model weights')
|
40 |
+
parser.add_argument('--promptify', type=str, default="simple_augment")
|
41 |
+
parser.add_argument('--device', type=int, default=0, help="GPU device")
|
42 |
+
parser.add_argument('--debug', action='store_true', help="Debug mode")
|
43 |
+
parser.add_argument('--save', type=str, default='results/', help="Path to save the resultant images")
|
44 |
+
args = parser.parse_args()
|
45 |
+
|
46 |
+
SEED=42
|
47 |
+
seed_everything(SEED=SEED)
|
48 |
+
torch.backends.cudnn.deterministic = True
|
49 |
+
|
50 |
+
GPU = args.device
|
51 |
+
DEBUG = args.debug
|
52 |
+
MODEL_NAME = args.model
|
53 |
+
CONFIG = args.config
|
54 |
+
LM_MODEL = args.lm
|
55 |
+
SAVE_PATH = args.save
|
56 |
+
|
57 |
+
print ('CUDA GPU available: ', torch.cuda.is_available())
|
58 |
+
|
59 |
+
torch.cuda.set_device(f'cuda:{GPU}')
|
60 |
+
device = torch.device(f'cuda:{GPU}' if torch.cuda.is_available() else "cpu")
|
61 |
+
print ('CUDA visible devices: ' + str(torch.cuda.device_count()))
|
62 |
+
print ('CUDA current device: ', torch.cuda.current_device(), torch.cuda.get_device_name(torch.cuda.current_device()))
|
63 |
+
|
64 |
+
# parse config file
|
65 |
+
with open(os.path.join(CONFIG), "r") as f:
|
66 |
+
config = yaml.safe_load(f)
|
67 |
+
|
68 |
+
cfg = dict2namespace(config)
|
69 |
+
|
70 |
+
|
71 |
+
print (20*"****")
|
72 |
+
print ("EVALUATION")
|
73 |
+
print (MODEL_NAME, LM_MODEL, device, DEBUG, CONFIG, args.promptify)
|
74 |
+
print (20*"****")
|
75 |
+
|
76 |
+
################### TESTING DATASET
|
77 |
+
|
78 |
+
TESTSETS = []
|
79 |
+
dn_testsets = []
|
80 |
+
rain_testsets = []
|
81 |
+
|
82 |
+
# Denoising
|
83 |
+
try:
|
84 |
+
for testset in cfg.test.dn_datasets:
|
85 |
+
for sigma in cfg.test.dn_sigmas:
|
86 |
+
noisy_testpath = os.path.join(cfg.test.dn_datapath, testset+ f"_{sigma}")
|
87 |
+
clean_testpath = os.path.join(cfg.test.dn_datapath, testset)
|
88 |
+
#print (clean_testpath, noisy_testpath)
|
89 |
+
dn_testsets.append([clean_testpath, noisy_testpath])
|
90 |
+
except:
|
91 |
+
dn_testsets = []
|
92 |
+
|
93 |
+
# RAIN
|
94 |
+
try:
|
95 |
+
for noisy_testpath, clean_testpath in zip(cfg.test.rain_inputs, cfg.test.rain_targets):
|
96 |
+
rain_testsets.append([clean_testpath, noisy_testpath])
|
97 |
+
except:
|
98 |
+
rain_testsets = []
|
99 |
+
|
100 |
+
# HAZE
|
101 |
+
try:
|
102 |
+
haze_testsets = [[cfg.test.haze_targets, cfg.test.haze_inputs]]
|
103 |
+
except:
|
104 |
+
haze_testsets = []
|
105 |
+
|
106 |
+
# BLUR
|
107 |
+
try:
|
108 |
+
blur_testsets = [[cfg.test.gopro_targets, cfg.test.gopro_inputs]]
|
109 |
+
except:
|
110 |
+
blur_testsets = []
|
111 |
+
|
112 |
+
# LOL
|
113 |
+
try:
|
114 |
+
lol_testsets = [[cfg.test.lol_targets, cfg.test.lol_inputs]]
|
115 |
+
except:
|
116 |
+
lol_testsets = []
|
117 |
+
|
118 |
+
# MIT5K
|
119 |
+
try:
|
120 |
+
mit_testsets = [[cfg.test.mit_targets, cfg.test.mit_inputs]]
|
121 |
+
except:
|
122 |
+
mit_testsets = []
|
123 |
+
|
124 |
+
TESTSETS += dn_testsets
|
125 |
+
TESTSETS += rain_testsets
|
126 |
+
TESTSETS += haze_testsets
|
127 |
+
TESTSETS += blur_testsets
|
128 |
+
TESTSETS += lol_testsets
|
129 |
+
TESTSETS += mit_testsets
|
130 |
+
|
131 |
+
# print ("Tests:", TESTSETS)
|
132 |
+
print ("TOTAL TESTSET:", len(TESTSETS))
|
133 |
+
print (20 * "----")
|
134 |
+
|
135 |
+
|
136 |
+
################### RESTORATION MODEL
|
137 |
+
|
138 |
+
print ("Creating InstructIR")
|
139 |
+
model = instructir.create_model(input_channels =cfg.model.in_ch, width=cfg.model.width, enc_blks = cfg.model.enc_blks,
|
140 |
+
middle_blk_num = cfg.model.middle_blk_num, dec_blks = cfg.model.dec_blks, txtdim=cfg.model.textdim)
|
141 |
+
|
142 |
+
################### LOAD IMAGE MODEL
|
143 |
+
|
144 |
+
assert MODEL_NAME, "Model weights required for evaluation"
|
145 |
+
|
146 |
+
print ("IMAGE MODEL CKPT:", MODEL_NAME)
|
147 |
+
model.load_state_dict(torch.load(MODEL_NAME), strict=True)
|
148 |
+
|
149 |
+
model = model.to(device)
|
150 |
+
|
151 |
+
nparams = count_params (model)
|
152 |
+
print ("Loaded weights!", nparams / 1e6)
|
153 |
+
|
154 |
+
################### LANGUAGE MODEL
|
155 |
+
|
156 |
+
try:
|
157 |
+
PROMPT_DB = cfg.llm.text_db
|
158 |
+
except:
|
159 |
+
PROMPT_DB = None
|
160 |
+
|
161 |
+
if cfg.model.use_text:
|
162 |
+
os.environ["TOKENIZERS_PARALLELISM"] = "false"
|
163 |
+
|
164 |
+
# Initialize the LanguageModel class
|
165 |
+
LMODEL = cfg.llm.model
|
166 |
+
language_model = LanguageModel(model=LMODEL)
|
167 |
+
lm_head = LMHead(embedding_dim=cfg.llm.model_dim, hidden_dim=cfg.llm.embd_dim, num_classes=cfg.llm.nclasses)
|
168 |
+
lm_head = lm_head.to(device)
|
169 |
+
lm_nparams = count_params (lm_head)
|
170 |
+
|
171 |
+
print ("LMHEAD MODEL CKPT:", LM_MODEL)
|
172 |
+
lm_head.load_state_dict(torch.load(LM_MODEL), strict=True)
|
173 |
+
print ("Loaded weights!")
|
174 |
+
|
175 |
+
else:
|
176 |
+
LMODEL = None
|
177 |
+
language_model = None
|
178 |
+
lm_head = None
|
179 |
+
lm_nparams = 0
|
180 |
+
|
181 |
+
print (20 * "----")
|
182 |
+
|
183 |
+
################### TESTING !!
|
184 |
+
|
185 |
+
from datasets import RefDegImage, augment_prompt, create_testsets
|
186 |
+
|
187 |
+
if args.promptify == "simple_augment":
|
188 |
+
promptify = augment_prompt
|
189 |
+
elif args.promptify == "chatgpt":
|
190 |
+
prompts = json.load(open(cfg.llm.text_db))
|
191 |
+
def promptify(deg):
|
192 |
+
|
193 |
+
return np.random.choice(prompts[deg])
|
194 |
+
else:
|
195 |
+
def promptify(deg):
|
196 |
+
return args.promptify
|
197 |
+
|
198 |
+
torch.cuda.empty_cache()
|
199 |
+
torch.cuda.reset_peak_memory_stats()
|
200 |
+
|
201 |
+
test_datasets = create_testsets(TESTSETS, debug=True)
|
202 |
+
|
203 |
+
test_model (model, language_model, lm_head, test_datasets, device, promptify, savepath=SAVE_PATH)
|
204 |
+
|
im_instructir-7d.pt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:f28d8f0f66ff57449ebe2be52241dfdd53a3dfab1003d63e65493f96ea152fd0
|
3 |
+
size 63627895
|
index.html
ADDED
@@ -0,0 +1,440 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html class="fontawesome-i2svg-active fontawesome-i2svg-complete" lang="en-US"><head>
|
3 |
+
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
4 |
+
<meta charset="utf-8">
|
5 |
+
<meta name="description" content="InstructIR: High-Quality Image Restoration Following Human Instructions ">
|
6 |
+
<meta name="keywords" content="Computer Vision, Image Restoration, Multimodal, Prompt">
|
7 |
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
8 |
+
<title>InstructIR</title>
|
9 |
+
|
10 |
+
<style type="text/css">svg:not(:root).svg-inline--fa{overflow:visible}.svg-inline--fa{display:inline-block;font-size:inherit;height:1em;overflow:visible;vertical-align:-.125em}.svg-inline--fa.fa-lg{vertical-align:-.225em}.svg-inline--fa.fa-w-1{width:.0625em}.svg-inline--fa.fa-w-2{width:.125em}.svg-inline--fa.fa-w-3{width:.1875em}.svg-inline--fa.fa-w-4{width:.25em}.svg-inline--fa.fa-w-5{width:.3125em}.svg-inline--fa.fa-w-6{width:.375em}.svg-inline--fa.fa-w-7{width:.4375em}.svg-inline--fa.fa-w-8{width:.5em}.svg-inline--fa.fa-w-9{width:.5625em}.svg-inline--fa.fa-w-10{width:.625em}.svg-inline--fa.fa-w-11{width:.6875em}.svg-inline--fa.fa-w-12{width:.75em}.svg-inline--fa.fa-w-13{width:.8125em}.svg-inline--fa.fa-w-14{width:.875em}.svg-inline--fa.fa-w-15{width:.9375em}.svg-inline--fa.fa-w-16{width:1em}.svg-inline--fa.fa-w-17{width:1.0625em}.svg-inline--fa.fa-w-18{width:1.125em}.svg-inline--fa.fa-w-19{width:1.1875em}.svg-inline--fa.fa-w-20{width:1.25em}.svg-inline--fa.fa-pull-left{margin-right:.3em;width:auto}.svg-inline--fa.fa-pull-right{margin-left:.3em;width:auto}.svg-inline--fa.fa-border{height:1.5em}.svg-inline--fa.fa-li{width:2em}.svg-inline--fa.fa-fw{width:1.25em}.fa-layers svg.svg-inline--fa{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.fa-layers{display:inline-block;height:1em;position:relative;text-align:center;vertical-align:-.125em;width:1em}.fa-layers svg.svg-inline--fa{-webkit-transform-origin:center center;transform-origin:center center}.fa-layers-counter,.fa-layers-text{display:inline-block;position:absolute;text-align:center}.fa-layers-text{left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);-webkit-transform-origin:center center;transform-origin:center center}.fa-layers-counter{background-color:#ff253a;border-radius:1em;-webkit-box-sizing:border-box;box-sizing:border-box;color:#fff;height:1.5em;line-height:1;max-width:5em;min-width:1.5em;overflow:hidden;padding:.25em;right:0;text-overflow:ellipsis;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top right;transform-origin:top right}.fa-layers-bottom-right{bottom:0;right:0;top:auto;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:bottom right;transform-origin:bottom right}.fa-layers-bottom-left{bottom:0;left:0;right:auto;top:auto;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:bottom left;transform-origin:bottom left}.fa-layers-top-right{right:0;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top right;transform-origin:top right}.fa-layers-top-left{left:0;right:auto;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top left;transform-origin:top left}.fa-lg{font-size:1.3333333333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:solid .08em #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.fa-rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-webkit-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-webkit-transform:scale(1,-1);transform:scale(1,-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1,-1);transform:scale(-1,-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-rotate-90{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;position:relative;width:2.5em}.fa-stack-1x,.fa-stack-2x{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.svg-inline--fa.fa-stack-1x{height:1em;width:1.25em}.svg-inline--fa.fa-stack-2x{height:2em;width:2.5em}.fa-inverse{color:#fff}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.svg-inline--fa .fa-primary{fill:var(--fa-primary-color,currentColor);opacity:1;opacity:var(--fa-primary-opacity,1)}.svg-inline--fa .fa-secondary{fill:var(--fa-secondary-color,currentColor);opacity:.4;opacity:var(--fa-secondary-opacity,.4)}.svg-inline--fa.fa-swap-opacity .fa-primary{opacity:.4;opacity:var(--fa-secondary-opacity,.4)}.svg-inline--fa.fa-swap-opacity .fa-secondary{opacity:1;opacity:var(--fa-primary-opacity,1)}.svg-inline--fa mask .fa-primary,.svg-inline--fa mask .fa-secondary{fill:#000}.fad.fa-inverse{color:#fff}</style><link rel="stylesheet" href="static/css.css">
|
11 |
+
<link rel="stylesheet" href="static/bulma.min.css">
|
12 |
+
<link rel="stylesheet" href="static/bootstrap.min.css">
|
13 |
+
<link rel="stylesheet" href="static/academicons.min.css">
|
14 |
+
<link rel="stylesheet" href="static/all.min.css">
|
15 |
+
<link rel="stylesheet" href="static/index.css">
|
16 |
+
<link rel="icon" href="https://emojiisland.com/cdn/shop/products/Robot_Emoji_Icon_abe1111a-1293-4668-bdf9-9ceb05cff58e_large.png?v=1571606090">
|
17 |
+
<link href="static/icon.css" rel="stylesheet">
|
18 |
+
|
19 |
+
|
20 |
+
<script src="static/jquery.min.js"></script>
|
21 |
+
<script defer="defer" src="static/all.min.js"></script>
|
22 |
+
<script type="module" src="static/gradio.js"></script>
|
23 |
+
<style>
|
24 |
+
.expandable-card .card-text-container {
|
25 |
+
max-height: 200px;
|
26 |
+
overflow-y: hidden;
|
27 |
+
position: relative;
|
28 |
+
}
|
29 |
+
|
30 |
+
.expandable-card.expanded .card-text-container {
|
31 |
+
max-height: none;
|
32 |
+
}
|
33 |
+
|
34 |
+
.expand-btn {
|
35 |
+
position: relative;
|
36 |
+
display: none;
|
37 |
+
background-color: rgba(255, 255, 255, 0.8);
|
38 |
+
/* margin-top: -20px; */
|
39 |
+
/* justify-content: center; */
|
40 |
+
color: #510c75;
|
41 |
+
border-color: transparent;
|
42 |
+
}
|
43 |
+
|
44 |
+
.expand-btn:hover {
|
45 |
+
background-color: rgba(200, 200, 200, 0.8);
|
46 |
+
text-decoration: none;
|
47 |
+
border-color: transparent;
|
48 |
+
color: #510c75;
|
49 |
+
}
|
50 |
+
|
51 |
+
.expand-btn:focus {
|
52 |
+
outline: none;
|
53 |
+
text-decoration: none;
|
54 |
+
}
|
55 |
+
|
56 |
+
.expandable-card:not(.expanded) .card-text-container:after {
|
57 |
+
content: "";
|
58 |
+
position: absolute;
|
59 |
+
bottom: 0;
|
60 |
+
left: 0;
|
61 |
+
width: 100%;
|
62 |
+
height: 90px;
|
63 |
+
background: linear-gradient(rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 1));
|
64 |
+
}
|
65 |
+
|
66 |
+
.expandable-card:not(.expanded) .expand-btn {
|
67 |
+
margin-top: -40px;
|
68 |
+
}
|
69 |
+
|
70 |
+
.card-body {
|
71 |
+
padding-bottom: 5px;
|
72 |
+
}
|
73 |
+
|
74 |
+
.vertical-flex-layout {
|
75 |
+
justify-content: center;
|
76 |
+
align-items: center;
|
77 |
+
height: 100%;
|
78 |
+
display: flex;
|
79 |
+
flex-direction: column;
|
80 |
+
gap: 5px;
|
81 |
+
}
|
82 |
+
|
83 |
+
.figure-img {
|
84 |
+
max-width: 100%;
|
85 |
+
height: auto;
|
86 |
+
}
|
87 |
+
|
88 |
+
.adjustable-font-size {
|
89 |
+
font-size: calc(0.5rem + 2vw);
|
90 |
+
}
|
91 |
+
|
92 |
+
.chat-history {
|
93 |
+
flex-grow: 1;
|
94 |
+
overflow-y: auto;
|
95 |
+
/* overflow-x: hidden; */
|
96 |
+
padding: 5px;
|
97 |
+
border-bottom: 1px solid #ccc;
|
98 |
+
margin-bottom: 10px;
|
99 |
+
}
|
100 |
+
|
101 |
+
#gradio pre {
|
102 |
+
background-color: transparent;
|
103 |
+
}
|
104 |
+
</style><script type="module" crossorigin="" src="static/index-9405f928.js"></script><link rel="stylesheet" href="static/index-8f5e8d2d.css"><link rel="stylesheet" href="static/theme.css"><link rel="stylesheet" href="static/css2.css"><link rel="stylesheet" href="static/css2_002.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Blocks-b7e1d3bc.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Button-496612d6.js"><link rel="stylesheet" href="static/Button-3657eefc.css"><link rel="stylesheet" href="static/Blocks-005a10ea.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-7da00dd0.js"><link rel="modulepreload" as="script" crossorigin="" href="static/index-9405f928.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-e350ed90.js"><link rel="stylesheet" href="static/index-edf307d2.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-9454ebde.js"><link rel="stylesheet" href="static/index-93c91554.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-29aa4c6e.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Column-56337312.js"><link rel="stylesheet" href="static/Column-2853eb31.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-6c061571.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/BlockTitle-3b63dcc6.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Info-88fa40fc.js"><link rel="stylesheet" href="static/ColorPicker-41813019.css"><link rel="stylesheet" href="static/DropdownArrow-5fa4dd09.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-dc4f9a55.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/BlockLabel-eae79103.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Image-0296a7e2.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/StaticImage.svelte_svelte_type_style_lang-943673fc.js"><link rel="stylesheet" href="static/StaticImage-ede66243.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/ModifyUpload-3ceaec64.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/ModifyUpload.svelte_svelte_type_style_lang-ba6baa96.js"><link rel="stylesheet" href="static/ModifyUpload-77b0d4b2.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Upload-0b7d7edd.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Empty-0bf01d93.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Download-836e8a5d.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/UploadText-67055cc3.js"><link rel="stylesheet" href="static/UploadText-33d53a1c.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Image-4f594cb8.js"><link rel="stylesheet" href="static/Image-003ee87c.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-fb7b6d6a.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-4360065a.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/_commonjsHelpers-042e6b4d.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/csv-b0b7514a.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/dsv-576afacd.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Model3D-49e4759c.js"><link rel="stylesheet" href="static/Model3D-98fc2b2c.css"><link rel="stylesheet" href="static/index-4a8edf2e.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-544cdc5f.js"><link rel="stylesheet" href="static/index-8f1feca1.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-efacc33c.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-5ff6e9da.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Form-e2ba6e12.js"><link rel="stylesheet" href="static/Form-a4a7741e.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-74280621.js"><link rel="stylesheet" href="static/index-d9aad8e1.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-f67a924c.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Textbox-91bfa043.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Copy-4761247d.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-00a3ebda.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-1c9d35e7.js"><link rel="stylesheet" href="static/index-3ca142e0.css"><script async="" defer="defer" src="static/js.js"></script></head>
|
105 |
+
|
106 |
+
|
107 |
+
|
108 |
+
<body>
|
109 |
+
|
110 |
+
|
111 |
+
<section class="hero">
|
112 |
+
<div class="hero-body">
|
113 |
+
<div class="container is-max-desktop">
|
114 |
+
<div class="columns is-centered">
|
115 |
+
<div class="column has-text-centered">
|
116 |
+
<h1 class="title is-1 publication-title">InstructIR: High-Quality Image Restoration Following Human Instructions</h1>
|
117 |
+
<br>
|
118 |
+
<div class="is-size-4 publication-authors">
|
119 |
+
<span class="author-block">
|
120 |
+
<a href="https://mv-lab.github.io/" style="color:#f68946;font-weight:normal;">Marcos V. Conde<sup>1,2</sup></a>,
|
121 |
+
</span>
|
122 |
+
<span class="author-block">
|
123 |
+
<a href="https://scholar.google.com/citations?user=uIlyqRwAAAAJ&hl=en" style="color:#008AD7;font-weight:normal;">Gregor Geigle<sup>1</sup></a>,
|
124 |
+
</span>
|
125 |
+
<span class="author-block">
|
126 |
+
<a href="https://scholar.google.com/citations?hl=en&user=u3MwH5kAAAAJ" style="color:#F2A900;font-weight:normal;">Radu Timofte<sup>1</sup></a>,
|
127 |
+
</span>
|
128 |
+
|
129 |
+
</div>
|
130 |
+
|
131 |
+
<div class="is-size-5 publication-authors">
|
132 |
+
<span class="author-block"><b style="color:#f68946; font-weight:normal">▶ </b> <sup>1</sup>Computer Vision Lab, University of Wuerzburg</span>
|
133 |
+
   <span class="author-block"><b style="color:#008AD7; font-weight:normal">▶ </b> <sup>2</sup>Sony PlayStation, FTG</span>
|
134 |
+
</div>
|
135 |
+
|
136 |
+
<br>
|
137 |
+
|
138 |
+
<div class="column has-text-centered">
|
139 |
+
<div class="publication-links">
|
140 |
+
|
141 |
+
|
142 |
+
<span class="link-block">
|
143 |
+
<a href="https://arxiv.org/pdf/2401.16468.pdf" target="_blank" class="external-link button is-normal is-rounded is-dark">
|
144 |
+
<span class="icon">
|
145 |
+
<svg class="svg-inline--fa fa-file-pdf fa-w-12" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="file-pdf" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" data-fa-i2svg=""><path fill="currentColor" d="M181.9 256.1c-5-16-4.9-46.9-2-46.9 8.4 0 7.6 36.9 2 46.9zm-1.7 47.2c-7.7 20.2-17.3 43.3-28.4 62.7 18.3-7 39-17.2 62.9-21.9-12.7-9.6-24.9-23.4-34.5-40.8zM86.1 428.1c0 .8 13.2-5.4 34.9-40.2-6.7 6.3-29.1 24.5-34.9 40.2zM248 160h136v328c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V24C0 10.7 10.7 0 24 0h200v136c0 13.2 10.8 24 24 24zm-8 171.8c-20-12.2-33.3-29-42.7-53.8 4.5-18.5 11.6-46.6 6.2-64.2-4.7-29.4-42.4-26.5-47.8-6.8-5 18.3-.4 44.1 8.1 77-11.6 27.6-28.7 64.6-40.8 85.8-.1 0-.1.1-.2.1-27.1 13.9-73.6 44.5-54.5 68 5.6 6.9 16 10 21.5 10 17.9 0 35.7-18 61.1-61.8 25.8-8.5 54.1-19.1 79-23.2 21.7 11.8 47.1 19.5 64 19.5 29.2 0 31.2-32 19.7-43.4-13.9-13.6-54.3-9.7-73.6-7.2zM377 105L279 7c-4.5-4.5-10.6-7-17-7h-6v128h128v-6.1c0-6.3-2.5-12.4-7-16.9zm-74.1 255.3c4.1-2.7-2.5-11.9-42.8-9 37.1 15.8 42.8 9 42.8 9z"></path></svg><!-- <i class="fas fa-file-pdf"></i> Font Awesome fontawesome.com -->
|
146 |
+
</span>
|
147 |
+
<span>Paper</span>
|
148 |
+
</a>
|
149 |
+
</span>
|
150 |
+
|
151 |
+
<span class="link-block">
|
152 |
+
<a href="https://arxiv.org/abs/2401.16468" target="_blank" class="external-link button is-normal is-rounded is-dark">
|
153 |
+
<span class="icon">
|
154 |
+
<i class="ai ai-arxiv"></i>
|
155 |
+
</span>
|
156 |
+
<span>arXiv</span>
|
157 |
+
</a>
|
158 |
+
</span>
|
159 |
+
<span class="link-block">
|
160 |
+
<a href="https://github.com/mv-lab/InstructIR/" target="_blank" class="external-link button is-normal is-rounded is-dark">
|
161 |
+
<span class="icon">
|
162 |
+
<svg class="svg-inline--fa fa-github fa-w-16" aria-hidden="true" focusable="false" data-prefix="fab" data-icon="github" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512" data-fa-i2svg=""><path fill="currentColor" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path></svg><!-- <i class="fab fa-github"></i> Font Awesome fontawesome.com -->
|
163 |
+
</span>
|
164 |
+
<span>Code</span>
|
165 |
+
</a>
|
166 |
+
</span>
|
167 |
+
<span class="link-block">
|
168 |
+
<a href="https://huggingface.co/spaces/marcosv/InstructIR" target="_blank" class="external-link button is-normal is-rounded is-dark">
|
169 |
+
<span class="icon">
|
170 |
+
<svg class="svg-inline--fa fa-images fa-w-18" aria-hidden="true" focusable="false" data-prefix="far" data-icon="images" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-fa-i2svg=""><path fill="currentColor" d="M480 416v16c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V176c0-26.51 21.49-48 48-48h16v48H54a6 6 0 0 0-6 6v244a6 6 0 0 0 6 6h372a6 6 0 0 0 6-6v-10h48zm42-336H150a6 6 0 0 0-6 6v244a6 6 0 0 0 6 6h372a6 6 0 0 0 6-6V86a6 6 0 0 0-6-6zm6-48c26.51 0 48 21.49 48 48v256c0 26.51-21.49 48-48 48H144c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h384zM264 144c0 22.091-17.909 40-40 40s-40-17.909-40-40 17.909-40 40-40 40 17.909 40 40zm-72 96l39.515-39.515c4.686-4.686 12.284-4.686 16.971 0L288 240l103.515-103.515c4.686-4.686 12.284-4.686 16.971 0L480 208v80H192v-48z"></path></svg><!-- <i class="far fa-images"></i> Font Awesome fontawesome.com -->
|
171 |
+
</span>
|
172 |
+
<span>Demo 🤗</span>
|
173 |
+
</a>
|
174 |
+
</span>
|
175 |
+
|
176 |
+
<span class="link-block">
|
177 |
+
<a href="https://huggingface.co/marcosv/InstructIR" target="_blank" class="external-link button is-normal is-rounded is-dark">
|
178 |
+
<span class="icon">
|
179 |
+
<svg class="svg-inline--fa fa-images fa-w-18" aria-hidden="true" focusable="false" data-prefix="far" data-icon="images" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-fa-i2svg=""><path fill="currentColor" d="M480 416v16c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V176c0-26.51 21.49-48 48-48h16v48H54a6 6 0 0 0-6 6v244a6 6 0 0 0 6 6h372a6 6 0 0 0 6-6v-10h48zm42-336H150a6 6 0 0 0-6 6v244a6 6 0 0 0 6 6h372a6 6 0 0 0 6-6V86a6 6 0 0 0-6-6zm6-48c26.51 0 48 21.49 48 48v256c0 26.51-21.49 48-48 48H144c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h384zM264 144c0 22.091-17.909 40-40 40s-40-17.909-40-40 17.909-40 40-40 40 17.909 40 40zm-72 96l39.515-39.515c4.686-4.686 12.284-4.686 16.971 0L288 240l103.515-103.515c4.686-4.686 12.284-4.686 16.971 0L480 208v80H192v-48z"></path></svg><!-- <i class="far fa-images"></i> Font Awesome fontawesome.com -->
|
180 |
+
</span>
|
181 |
+
<span>Models 🤗</span>
|
182 |
+
</a>
|
183 |
+
</span>
|
184 |
+
|
185 |
+
</div>
|
186 |
+
</div>
|
187 |
+
</div>
|
188 |
+
</div>
|
189 |
+
</div>
|
190 |
+
</div>
|
191 |
+
</section>
|
192 |
+
|
193 |
+
<section class="section" style="background-color:#efeff081">
|
194 |
+
<div class="container is-max-desktop">
|
195 |
+
<!-- Abstract. -->
|
196 |
+
<div class="columns is-centered has-text-centered">
|
197 |
+
<div class="column is-six-fifths">
|
198 |
+
<h2 class="title is-3">TL;DR</h2>
|
199 |
+
|
200 |
+
<div class="content has-text-justified">
|
201 |
+
|
202 |
+
<b>InstructIR takes as input an image and a human-written instruction for how to improve that image.</b>
|
203 |
+
The (single) neural model performs all-in-one image restoration.
|
204 |
+
InstructIR achieves state-of-the-art results on several restoration tasks including image denoising, deraining, deblurring, dehazing, and (low-light) image enhancement.
|
205 |
+
Test the model now on <a href="https://huggingface.co/spaces/marcosv/InstructIR"> HF 🤗 InstructIR space </a>
|
206 |
+
<br>
|
207 |
+
🚀 You can start with the <a href="https://github.com/mv-lab/InstructIR/blob/main/demo.ipynb">demo tutorial</a> from our github.
|
208 |
+
<br>
|
209 |
+
<br>
|
210 |
+
<b>🔥🔥 More content comming soon: all test results, more model versions, tables, etc.</b>
|
211 |
+
<br>
|
212 |
+
<br>
|
213 |
+
|
214 |
+
</div>
|
215 |
+
|
216 |
+
</div>
|
217 |
+
</div>
|
218 |
+
|
219 |
+
</div>
|
220 |
+
</section>
|
221 |
+
|
222 |
+
|
223 |
+
|
224 |
+
<section class="section">
|
225 |
+
|
226 |
+
<div class="columns is-centered has-text-centered">
|
227 |
+
<div class="column is-six-fifths">
|
228 |
+
<h2 class="title is-3"> Examples of InstructIR</h2>
|
229 |
+
|
230 |
+
<video width="860" height="640" autoplay loop controls>
|
231 |
+
<source src="images/instructir.mp4" type="video/mp4">
|
232 |
+
Your browser does not support the video tag.
|
233 |
+
</video>
|
234 |
+
|
235 |
+
<!--
|
236 |
+
<img src="images/instructir_teaser.png" width="50%">
|
237 |
+
-->
|
238 |
+
|
239 |
+
|
240 |
+
</div>
|
241 |
+
</div>
|
242 |
+
|
243 |
+
|
244 |
+
<center>
|
245 |
+
<br>
|
246 |
+
<br>
|
247 |
+
<h2 class="title">Demo App 🤗</h2>
|
248 |
+
|
249 |
+
<iframe
|
250 |
+
src="https://marcosv-instructir.hf.space"
|
251 |
+
frameborder="0"
|
252 |
+
width="850"
|
253 |
+
height="450"
|
254 |
+
></iframe>
|
255 |
+
|
256 |
+
</center>
|
257 |
+
|
258 |
+
|
259 |
+
<div class="container mt-5">
|
260 |
+
<!-- <h2 class="text-center mb-5">Who's GPT-4's favorite? Battles between State-of-the-Art Chatbots</h2> -->
|
261 |
+
<!-- Selection -->
|
262 |
+
<div class="form-row" style="justify-content: flex-end;">
|
263 |
+
<div class="form-group col-md-1">
|
264 |
+
<div class="col-md-2" style="width: 100%"><label> </label></div>
|
265 |
+
<div class="btn-group" role="group" aria-label="Left and Right Controller" style="width: 100%;align-items: flex-end;justify-content: center;flex-direction: row;display: flex;">
|
266 |
+
<button type="button" class="form-control btn btn-primary" id="prev-question"><i class="material-icons">keyboard_arrow_left</i></button>
|
267 |
+
<button type="button" class="form-control btn btn-primary" id="next-question"><i class="material-icons">keyboard_arrow_right</i></button>
|
268 |
+
|
269 |
+
</div>
|
270 |
+
</div>
|
271 |
+
</div>
|
272 |
+
|
273 |
+
<!-- Question Card -->
|
274 |
+
<div style="display: flex; justify-content: center; align-items: center;">
|
275 |
+
<div class="card mb-4" style="width: 100%; display: flex; align-items: center;">
|
276 |
+
<!-- <p><b>Description:</b> Monalisa is a famous painting by Leonardo da Vinci. </p> -->
|
277 |
+
|
278 |
+
<div class="card-body" id="selected-question" style="display: flex; height: 80vh;">
|
279 |
+
<div class="chat-history"><article class="media"><figure class="media-left"><span class="icon is-large"><svg class="svg-inline--fa fa-user fa-w-14 fa-2x" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="user" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" data-fa-i2svg=""><path fill="currentColor" d="M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z"></path></svg><!-- <i class="fas fas fa-2x fa-user "></i> Font Awesome fontawesome.com --></span></figure><div class="media-content"><div class="content"><p><strong>User</strong><br><pre style="background-color: white; font-size: 18px; font-family: Arial; padding: 0px; margin: 0px; white-space: pre-wrap; overflow-wrap: break-word;"></pre><img src="static/monalisa.jpg" style="max-width: 100%; max-height: 300px;"></p></div></div></article><article class="media"><figure class="media-left"><span class="icon is-large"><svg class="svg-inline--fa fa-user fa-w-14 fa-2x" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="user" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" data-fa-i2svg=""><path fill="currentColor" d="M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z"></path></svg><!-- <i class="fas fas fa-2x fa-user "></i> Font Awesome fontawesome.com --></span></figure><div class="media-content"><div class="content"><p><strong>User</strong><br><pre style="background-color: white; font-size: 18px; font-family: Arial; padding: 0px; margin: 0px; white-space: pre-wrap; overflow-wrap: break-word;">Do you know who drew this painting?</pre></p></div></div></article><article class="media"><figure class="media-left"><span class="icon is-large"><svg class="svg-inline--fa fa-robot fa-w-20 fa-2x" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="robot" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" data-fa-i2svg=""><path fill="currentColor" d="M32,224H64V416H32A31.96166,31.96166,0,0,1,0,384V256A31.96166,31.96166,0,0,1,32,224Zm512-48V448a64.06328,64.06328,0,0,1-64,64H160a64.06328,64.06328,0,0,1-64-64V176a79.974,79.974,0,0,1,80-80H288V32a32,32,0,0,1,64,0V96H464A79.974,79.974,0,0,1,544,176ZM264,256a40,40,0,1,0-40,40A39.997,39.997,0,0,0,264,256Zm-8,128H192v32h64Zm96,0H288v32h64ZM456,256a40,40,0,1,0-40,40A39.997,39.997,0,0,0,456,256Zm-8,128H384v32h64ZM640,256V384a31.96166,31.96166,0,0,1-32,32H576V224h32A31.96166,31.96166,0,0,1,640,256Z"></path></svg><!-- <i class="fas fas fa-2x fa-robot"></i> Font Awesome fontawesome.com --></span></figure><div class="media-content"><div class="content"><p><strong>LLaVA</strong><br><pre style="background-color: white; font-size: 18px; font-family: Arial; padding: 0px; margin: 0px; white-space: pre-wrap; overflow-wrap: break-word;">The painting depicts a woman, commonly believed to be Mona Lisa, the famous artwork by Leonardo da Vinci. It is a portrait painting that showcases the woman's enigmatic smile and has become one of the most famous and iconic art pieces in the world. The original work is displayed in the Louvre Museum in Paris, and it is known for its intricate details, use of oil paint, and the artist's innovative techniques that contributed to its enduring appeal and mystery.</pre></p></div></div></article></div>
|
280 |
+
|
281 |
+
</div>
|
282 |
+
</div>
|
283 |
+
</div>
|
284 |
+
|
285 |
+
</div>
|
286 |
+
</section>
|
287 |
+
|
288 |
+
|
289 |
+
<section class="section" id="BibTeX">
|
290 |
+
<div class="container is-max-desktop content">
|
291 |
+
<h2 class="title">Citation BibTeX</h2>
|
292 |
+
<pre><code>
|
293 |
+
@misc{conde2024instructir,
|
294 |
+
title={High-Quality Image Restoration Following Human Instructions},
|
295 |
+
author={Marcos V. Conde, Gregor Geigle, Radu Timofte},
|
296 |
+
year={2024},
|
297 |
+
journal={arXiv preprint}
|
298 |
+
}
|
299 |
+
</code></pre>
|
300 |
+
</div>
|
301 |
+
</section>
|
302 |
+
|
303 |
+
<section class="section" id="Acknowledgement">
|
304 |
+
<div class="container is-max-desktop content">
|
305 |
+
<h2 class="title">Acknowledgement</h2>
|
306 |
+
<p>
|
307 |
+
This work was partly supported by the The Humboldt Foundation (AvH). Marcos Conde is also supported by Sony Interactive Entertainment, FTG.
|
308 |
+
This work is inspired in <a href="https://www.timothybrooks.com/instruct-pix2pix/">InstructPix2Pix</a>.
|
309 |
+
<br>
|
310 |
+
For any inquiries contact Marcos V. Conde: marcos.conde [at] uni-wuerzburg.de
|
311 |
+
</p>
|
312 |
+
<p>
|
313 |
+
This website is adapted from <a href="https://github.com/nerfies/nerfies.github.io">Nerfies</a> and <a href="https://github.com/nerfies/nerfies.github.io">LLaVA</a>, licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative
|
314 |
+
Commons Attribution-ShareAlike 4.0 International License</a>. We thank the original authors of this website template.
|
315 |
+
</p>
|
316 |
+
|
317 |
+
<script>
|
318 |
+
// Handle message showing
|
319 |
+
function createChatRow(sender, text, imageSrc) {
|
320 |
+
var article = document.createElement("article");
|
321 |
+
article.className = "media"
|
322 |
+
|
323 |
+
var figure = document.createElement("figure");
|
324 |
+
figure.className = "media-left";
|
325 |
+
|
326 |
+
var span = document.createElement("span");
|
327 |
+
span.className = "icon is-large";
|
328 |
+
|
329 |
+
var icon = document.createElement("i");
|
330 |
+
icon.className = "fas fas fa-2x" + (sender === "User" ? " fa-user " : sender === "InstructIR" ? " fa-robot" : "");
|
331 |
+
|
332 |
+
var media = document.createElement("div");
|
333 |
+
media.className = "media-content";
|
334 |
+
|
335 |
+
var content = document.createElement("div");
|
336 |
+
content.className = "content";
|
337 |
+
|
338 |
+
var para = document.createElement("p");
|
339 |
+
|
340 |
+
// wrap text in pre tag to preserve whitespace and line breaks
|
341 |
+
var pre_text = document.createElement("pre");
|
342 |
+
pre_text.style = "background-color: white; font-size: 18px; font-family: Arial; padding: 0; margin: 0; white-space: pre-wrap; word-wrap: break-word;";
|
343 |
+
var paraText = document.createTextNode(text);
|
344 |
+
pre_text.appendChild(paraText);
|
345 |
+
|
346 |
+
var strong = document.createElement("strong");
|
347 |
+
strong.innerHTML = sender;
|
348 |
+
var br = document.createElement("br");
|
349 |
+
|
350 |
+
para.appendChild(strong);
|
351 |
+
para.appendChild(br);
|
352 |
+
para.appendChild(pre_text);
|
353 |
+
|
354 |
+
// Add image if imageSrc is provided
|
355 |
+
if (imageSrc) {
|
356 |
+
var img = document.createElement("img");
|
357 |
+
img.src = imageSrc;
|
358 |
+
img.style = "max-width: 100%; max-height: 300px;"; // Adjust the style as needed
|
359 |
+
para.appendChild(img);
|
360 |
+
}
|
361 |
+
|
362 |
+
content.appendChild(para);
|
363 |
+
media.appendChild(content);
|
364 |
+
span.appendChild(icon);
|
365 |
+
figure.appendChild(span);
|
366 |
+
if (sender !== "Description") {
|
367 |
+
article.appendChild(figure);
|
368 |
+
};
|
369 |
+
article.appendChild(media);
|
370 |
+
return article;
|
371 |
+
}
|
372 |
+
|
373 |
+
function addMessageToChatHistory(sender, message, imageSrc) {
|
374 |
+
const chatHistory = document.querySelector('.chat-history');
|
375 |
+
const chatRow = createChatRow(sender, message, imageSrc);
|
376 |
+
chatHistory.appendChild(chatRow);
|
377 |
+
chatHistory.scrollTop = chatHistory.scrollHeight;
|
378 |
+
}
|
379 |
+
|
380 |
+
function clearChatHistory() {
|
381 |
+
const chatHistory = document.querySelector('.chat-history');
|
382 |
+
chatHistory.innerHTML = "";
|
383 |
+
}
|
384 |
+
|
385 |
+
//
|
386 |
+
const conversations = [
|
387 |
+
{
|
388 |
+
"description": "Restore an image using natural language",
|
389 |
+
"turns": [
|
390 |
+
["User", "I love this photo, could you remove the raindrops? please keep the content intact", "images/rain-020.png"],
|
391 |
+
["InstructIR", "Sure! let me remove the rain", "images/results/result1.png"],
|
392 |
+
["User", "Great! can you make it look stunning? like a professional photo"],
|
393 |
+
["InstructIR", "I will enhance it", "images/results/result2.png"],
|
394 |
+
["User", "amazing, thank you InstructIR"],
|
395 |
+
]
|
396 |
+
},
|
397 |
+
];
|
398 |
+
|
399 |
+
// The current image index
|
400 |
+
let currentIndex = 0;
|
401 |
+
|
402 |
+
// The function to update the displayed chat history
|
403 |
+
function update_dialog_demo() {
|
404 |
+
// Clear the chat history
|
405 |
+
clearChatHistory();
|
406 |
+
|
407 |
+
for (let i = 0; i < conversations[currentIndex].turns.length; i++) {
|
408 |
+
if (conversations[currentIndex].turns[i].length == 2) {
|
409 |
+
addMessageToChatHistory(conversations[currentIndex].turns[i][0], conversations[currentIndex].turns[i][1]);
|
410 |
+
}
|
411 |
+
else {
|
412 |
+
addMessageToChatHistory(conversations[currentIndex].turns[i][0], conversations[currentIndex].turns[i][1], conversations[currentIndex].turns[i][2]);
|
413 |
+
}
|
414 |
+
}
|
415 |
+
|
416 |
+
// scroll to the top of the chat history
|
417 |
+
document.querySelector('.chat-history').scrollTop = 0;
|
418 |
+
}
|
419 |
+
|
420 |
+
// Initialize the displayed image
|
421 |
+
update_dialog_demo();
|
422 |
+
|
423 |
+
// Event listeners for the buttons
|
424 |
+
document.getElementById('prev-question').addEventListener('click', () => {
|
425 |
+
currentIndex = (currentIndex - 1 + conversations.length) % conversations.length;
|
426 |
+
update_dialog_demo();
|
427 |
+
});
|
428 |
+
|
429 |
+
document.getElementById('next-question').addEventListener('click', () => {
|
430 |
+
currentIndex = (currentIndex + 1) % conversations.length;
|
431 |
+
update_dialog_demo();
|
432 |
+
});
|
433 |
+
|
434 |
+
|
435 |
+
</script>
|
436 |
+
|
437 |
+
|
438 |
+
|
439 |
+
|
440 |
+
</body></html>
|
lm_instructir-7d.pt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:b239e5d5dbc811813a90e709f9647dead0e35a96a294a7d6c5263da549016fe6
|
3 |
+
size 403275
|
metrics.py
ADDED
@@ -0,0 +1,278 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import math
|
3 |
+
import cv2
|
4 |
+
import torch
|
5 |
+
|
6 |
+
|
7 |
+
def np_psnr(y_true, y_pred, maxval=1.):
|
8 |
+
mse = np.mean((y_true - y_pred) ** 2)
|
9 |
+
if(mse == 0):
|
10 |
+
return np.inf
|
11 |
+
|
12 |
+
psnr = 20 * np.log10(maxval / np.sqrt(mse))
|
13 |
+
return psnr
|
14 |
+
|
15 |
+
def pt_psnr(y_true, y_pred, maxval=1.):
|
16 |
+
mse = torch.mean((y_true - y_pred) ** 2, dim=(1, 2, 3))
|
17 |
+
psnr = 20 * torch.log10(maxval / torch.sqrt(mse))
|
18 |
+
return psnr.unsqueeze(1)
|
19 |
+
|
20 |
+
|
21 |
+
############# SWINIR METRICS
|
22 |
+
# https://github.com/JingyunLiang/SwinIR/blob/6545850fbf8df298df73d81f3e8cba638787c8bd/utils/util_calculate_psnr_ssim.py#L243
|
23 |
+
|
24 |
+
|
25 |
+
def calculate_psnr(img1, img2, crop_border, input_order='HWC', test_y_channel=False):
|
26 |
+
"""Calculate PSNR (Peak Signal-to-Noise Ratio).
|
27 |
+
|
28 |
+
Ref: https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio
|
29 |
+
|
30 |
+
Args:
|
31 |
+
img1 (ndarray): Images with range [0, 255].
|
32 |
+
img2 (ndarray): Images with range [0, 255].
|
33 |
+
crop_border (int): Cropped pixels in each edge of an image. These
|
34 |
+
pixels are not involved in the PSNR calculation.
|
35 |
+
input_order (str): Whether the input order is 'HWC' or 'CHW'.
|
36 |
+
Default: 'HWC'.
|
37 |
+
test_y_channel (bool): Test on Y channel of YCbCr. Default: False.
|
38 |
+
|
39 |
+
Returns:
|
40 |
+
float: psnr result.
|
41 |
+
"""
|
42 |
+
|
43 |
+
assert img1.shape == img2.shape, (f'Image shapes are differnet: {img1.shape}, {img2.shape}.')
|
44 |
+
if input_order not in ['HWC', 'CHW']:
|
45 |
+
raise ValueError(f'Wrong input_order {input_order}. Supported input_orders are ' '"HWC" and "CHW"')
|
46 |
+
img1 = reorder_image(img1, input_order=input_order)
|
47 |
+
img2 = reorder_image(img2, input_order=input_order)
|
48 |
+
img1 = img1.astype(np.float64)
|
49 |
+
img2 = img2.astype(np.float64)
|
50 |
+
|
51 |
+
if crop_border != 0:
|
52 |
+
img1 = img1[crop_border:-crop_border, crop_border:-crop_border, ...]
|
53 |
+
img2 = img2[crop_border:-crop_border, crop_border:-crop_border, ...]
|
54 |
+
|
55 |
+
if test_y_channel:
|
56 |
+
img1 = to_y_channel(img1)
|
57 |
+
img2 = to_y_channel(img2)
|
58 |
+
|
59 |
+
mse = np.mean((img1 - img2) ** 2)
|
60 |
+
if mse == 0:
|
61 |
+
return float('inf')
|
62 |
+
return 20. * np.log10(255. / np.sqrt(mse))
|
63 |
+
|
64 |
+
|
65 |
+
def _ssim(img1, img2):
|
66 |
+
"""Calculate SSIM (structural similarity) for one channel images.
|
67 |
+
|
68 |
+
It is called by func:`calculate_ssim`.
|
69 |
+
|
70 |
+
Args:
|
71 |
+
img1 (ndarray): Images with range [0, 255] with order 'HWC'.
|
72 |
+
img2 (ndarray): Images with range [0, 255] with order 'HWC'.
|
73 |
+
|
74 |
+
Returns:
|
75 |
+
float: ssim result.
|
76 |
+
"""
|
77 |
+
|
78 |
+
C1 = (0.01 * 255) ** 2
|
79 |
+
C2 = (0.03 * 255) ** 2
|
80 |
+
|
81 |
+
img1 = img1.astype(np.float64)
|
82 |
+
img2 = img2.astype(np.float64)
|
83 |
+
kernel = cv2.getGaussianKernel(11, 1.5)
|
84 |
+
window = np.outer(kernel, kernel.transpose())
|
85 |
+
|
86 |
+
mu1 = cv2.filter2D(img1, -1, window)[5:-5, 5:-5]
|
87 |
+
mu2 = cv2.filter2D(img2, -1, window)[5:-5, 5:-5]
|
88 |
+
mu1_sq = mu1 ** 2
|
89 |
+
mu2_sq = mu2 ** 2
|
90 |
+
mu1_mu2 = mu1 * mu2
|
91 |
+
sigma1_sq = cv2.filter2D(img1 ** 2, -1, window)[5:-5, 5:-5] - mu1_sq
|
92 |
+
sigma2_sq = cv2.filter2D(img2 ** 2, -1, window)[5:-5, 5:-5] - mu2_sq
|
93 |
+
sigma12 = cv2.filter2D(img1 * img2, -1, window)[5:-5, 5:-5] - mu1_mu2
|
94 |
+
|
95 |
+
ssim_map = ((2 * mu1_mu2 + C1) * (2 * sigma12 + C2)) / ((mu1_sq + mu2_sq + C1) * (sigma1_sq + sigma2_sq + C2))
|
96 |
+
return ssim_map.mean()
|
97 |
+
|
98 |
+
|
99 |
+
def calculate_ssim(img1, img2, crop_border, input_order='HWC', test_y_channel=False):
|
100 |
+
"""Calculate SSIM (structural similarity).
|
101 |
+
|
102 |
+
Ref:
|
103 |
+
Image quality assessment: From error visibility to structural similarity
|
104 |
+
|
105 |
+
The results are the same as that of the official released MATLAB code in
|
106 |
+
https://ece.uwaterloo.ca/~z70wang/research/ssim/.
|
107 |
+
|
108 |
+
For three-channel images, SSIM is calculated for each channel and then
|
109 |
+
averaged.
|
110 |
+
|
111 |
+
Args:
|
112 |
+
img1 (ndarray): Images with range [0, 255].
|
113 |
+
img2 (ndarray): Images with range [0, 255].
|
114 |
+
crop_border (int): Cropped pixels in each edge of an image. These
|
115 |
+
pixels are not involved in the SSIM calculation.
|
116 |
+
input_order (str): Whether the input order is 'HWC' or 'CHW'.
|
117 |
+
Default: 'HWC'.
|
118 |
+
test_y_channel (bool): Test on Y channel of YCbCr. Default: False.
|
119 |
+
|
120 |
+
Returns:
|
121 |
+
float: ssim result.
|
122 |
+
"""
|
123 |
+
|
124 |
+
assert img1.shape == img2.shape, (f'Image shapes are differnet: {img1.shape}, {img2.shape}.')
|
125 |
+
if input_order not in ['HWC', 'CHW']:
|
126 |
+
raise ValueError(f'Wrong input_order {input_order}. Supported input_orders are ' '"HWC" and "CHW"')
|
127 |
+
img1 = reorder_image(img1, input_order=input_order)
|
128 |
+
img2 = reorder_image(img2, input_order=input_order)
|
129 |
+
img1 = img1.astype(np.float64)
|
130 |
+
img2 = img2.astype(np.float64)
|
131 |
+
|
132 |
+
if crop_border != 0:
|
133 |
+
img1 = img1[crop_border:-crop_border, crop_border:-crop_border, ...]
|
134 |
+
img2 = img2[crop_border:-crop_border, crop_border:-crop_border, ...]
|
135 |
+
|
136 |
+
if test_y_channel:
|
137 |
+
img1 = to_y_channel(img1)
|
138 |
+
img2 = to_y_channel(img2)
|
139 |
+
|
140 |
+
ssims = []
|
141 |
+
for i in range(img1.shape[2]):
|
142 |
+
ssims.append(_ssim(img1[..., i], img2[..., i]))
|
143 |
+
return np.array(ssims).mean()
|
144 |
+
|
145 |
+
|
146 |
+
def reorder_image(img, input_order='HWC'):
|
147 |
+
"""Reorder images to 'HWC' order.
|
148 |
+
|
149 |
+
If the input_order is (h, w), return (h, w, 1);
|
150 |
+
If the input_order is (c, h, w), return (h, w, c);
|
151 |
+
If the input_order is (h, w, c), return as it is.
|
152 |
+
|
153 |
+
Args:
|
154 |
+
img (ndarray): Input image.
|
155 |
+
input_order (str): Whether the input order is 'HWC' or 'CHW'.
|
156 |
+
If the input image shape is (h, w), input_order will not have
|
157 |
+
effects. Default: 'HWC'.
|
158 |
+
|
159 |
+
Returns:
|
160 |
+
ndarray: reordered image.
|
161 |
+
"""
|
162 |
+
|
163 |
+
if input_order not in ['HWC', 'CHW']:
|
164 |
+
raise ValueError(f'Wrong input_order {input_order}. Supported input_orders are ' "'HWC' and 'CHW'")
|
165 |
+
if len(img.shape) == 2:
|
166 |
+
img = img[..., None]
|
167 |
+
if input_order == 'CHW':
|
168 |
+
img = img.transpose(1, 2, 0)
|
169 |
+
return img
|
170 |
+
|
171 |
+
|
172 |
+
def to_y_channel(img):
|
173 |
+
"""Change to Y channel of YCbCr.
|
174 |
+
|
175 |
+
Args:
|
176 |
+
img (ndarray): Images with range [0, 255].
|
177 |
+
|
178 |
+
Returns:
|
179 |
+
(ndarray): Images with range [0, 255] (float type) without round.
|
180 |
+
"""
|
181 |
+
if np.max(img) > 1.:
|
182 |
+
img = img.astype(np.float32) / 255.
|
183 |
+
|
184 |
+
if img.ndim == 3 and img.shape[2] == 3:
|
185 |
+
img = bgr2ycbcr(img, y_only=True)
|
186 |
+
img = img[..., None]
|
187 |
+
return img * 255.
|
188 |
+
|
189 |
+
|
190 |
+
def _convert_input_type_range(img):
|
191 |
+
"""Convert the type and range of the input image.
|
192 |
+
|
193 |
+
It converts the input image to np.float32 type and range of [0, 1].
|
194 |
+
It is mainly used for pre-processing the input image in colorspace
|
195 |
+
convertion functions such as rgb2ycbcr and ycbcr2rgb.
|
196 |
+
|
197 |
+
Args:
|
198 |
+
img (ndarray): The input image. It accepts:
|
199 |
+
1. np.uint8 type with range [0, 255];
|
200 |
+
2. np.float32 type with range [0, 1].
|
201 |
+
|
202 |
+
Returns:
|
203 |
+
(ndarray): The converted image with type of np.float32 and range of
|
204 |
+
[0, 1].
|
205 |
+
"""
|
206 |
+
img_type = img.dtype
|
207 |
+
img = img.astype(np.float32)
|
208 |
+
if img_type == np.float32:
|
209 |
+
pass
|
210 |
+
elif img_type == np.uint8:
|
211 |
+
img /= 255.
|
212 |
+
else:
|
213 |
+
raise TypeError('The img type should be np.float32 or np.uint8, ' f'but got {img_type}')
|
214 |
+
return img
|
215 |
+
|
216 |
+
|
217 |
+
def _convert_output_type_range(img, dst_type):
|
218 |
+
"""Convert the type and range of the image according to dst_type.
|
219 |
+
|
220 |
+
It converts the image to desired type and range. If `dst_type` is np.uint8,
|
221 |
+
images will be converted to np.uint8 type with range [0, 255]. If
|
222 |
+
`dst_type` is np.float32, it converts the image to np.float32 type with
|
223 |
+
range [0, 1].
|
224 |
+
It is mainly used for post-processing images in colorspace convertion
|
225 |
+
functions such as rgb2ycbcr and ycbcr2rgb.
|
226 |
+
|
227 |
+
Args:
|
228 |
+
img (ndarray): The image to be converted with np.float32 type and
|
229 |
+
range [0, 255].
|
230 |
+
dst_type (np.uint8 | np.float32): If dst_type is np.uint8, it
|
231 |
+
converts the image to np.uint8 type with range [0, 255]. If
|
232 |
+
dst_type is np.float32, it converts the image to np.float32 type
|
233 |
+
with range [0, 1].
|
234 |
+
|
235 |
+
Returns:
|
236 |
+
(ndarray): The converted image with desired type and range.
|
237 |
+
"""
|
238 |
+
if dst_type not in (np.uint8, np.float32):
|
239 |
+
raise TypeError('The dst_type should be np.float32 or np.uint8, ' f'but got {dst_type}')
|
240 |
+
if dst_type == np.uint8:
|
241 |
+
img = img.round()
|
242 |
+
else:
|
243 |
+
img /= 255.
|
244 |
+
return img.astype(dst_type)
|
245 |
+
|
246 |
+
|
247 |
+
def bgr2ycbcr(img, y_only=False):
|
248 |
+
"""Convert a BGR image to YCbCr image.
|
249 |
+
|
250 |
+
The bgr version of rgb2ycbcr.
|
251 |
+
It implements the ITU-R BT.601 conversion for standard-definition
|
252 |
+
television. See more details in
|
253 |
+
https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion.
|
254 |
+
|
255 |
+
It differs from a similar function in cv2.cvtColor: `BGR <-> YCrCb`.
|
256 |
+
In OpenCV, it implements a JPEG conversion. See more details in
|
257 |
+
https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion.
|
258 |
+
|
259 |
+
Args:
|
260 |
+
img (ndarray): The input image. It accepts:
|
261 |
+
1. np.uint8 type with range [0, 255];
|
262 |
+
2. np.float32 type with range [0, 1].
|
263 |
+
y_only (bool): Whether to only return Y channel. Default: False.
|
264 |
+
|
265 |
+
Returns:
|
266 |
+
ndarray: The converted YCbCr image. The output image has the same type
|
267 |
+
and range as input image.
|
268 |
+
"""
|
269 |
+
img_type = img.dtype
|
270 |
+
img = _convert_input_type_range(img)
|
271 |
+
if y_only:
|
272 |
+
out_img = np.dot(img, [24.966, 128.553, 65.481]) + 16.0
|
273 |
+
else:
|
274 |
+
out_img = np.matmul(
|
275 |
+
img, [[24.966, 112.0, -18.214], [128.553, -74.203, -93.786], [65.481, -37.797, 112.0]]) + [16, 128, 128]
|
276 |
+
out_img = _convert_output_type_range(out_img, img_type)
|
277 |
+
return out_img
|
278 |
+
|
models/__pycache__/instructir.cpython-310.pyc
ADDED
Binary file (4.19 kB). View file
|
|
models/__pycache__/nafnet.cpython-310.pyc
ADDED
Binary file (5.51 kB). View file
|
|
models/__pycache__/nafnet_utils.cpython-310.pyc
ADDED
Binary file (5.41 kB). View file
|
|
models/im_instructir-7d.pt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:f28d8f0f66ff57449ebe2be52241dfdd53a3dfab1003d63e65493f96ea152fd0
|
3 |
+
size 63627895
|
models/instructir.py
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import math
|
2 |
+
import torch
|
3 |
+
import torch.nn as nn
|
4 |
+
import torch.nn.functional as F
|
5 |
+
from torch.nn import init as init
|
6 |
+
from torch.nn.modules.batchnorm import _BatchNorm
|
7 |
+
|
8 |
+
from models.nafnet_utils import Local_Base, LayerNorm2d
|
9 |
+
from models.nafnet import SimpleGate, NAFBlock
|
10 |
+
|
11 |
+
|
12 |
+
class ICB(nn.Module):
|
13 |
+
"""
|
14 |
+
Instruction Condition Block (ICB)
|
15 |
+
Paper Section 3.3
|
16 |
+
"""
|
17 |
+
|
18 |
+
def __init__(self, feature_dim, text_dim=768):
|
19 |
+
super(ICB, self).__init__()
|
20 |
+
self.fc = nn.Linear(text_dim, feature_dim)
|
21 |
+
self.block = NAFBlock(feature_dim)
|
22 |
+
self.beta = nn.Parameter(torch.zeros((1, feature_dim, 1, 1)), requires_grad=True)
|
23 |
+
self.gamma = nn.Parameter(torch.zeros((1, feature_dim, 1, 1)), requires_grad=True)
|
24 |
+
|
25 |
+
def forward(self, x, text_embedding):
|
26 |
+
gating_factors = torch.sigmoid(self.fc(text_embedding))
|
27 |
+
gating_factors = gating_factors.unsqueeze(-1).unsqueeze(-1)
|
28 |
+
|
29 |
+
f = x * self.gamma + self.beta # 1) learned feature scaling/modulation
|
30 |
+
f = f * gating_factors # 2) (soft) feature routing based on text
|
31 |
+
f = self.block(f) # 3) block feature enhancement
|
32 |
+
return f + x
|
33 |
+
|
34 |
+
|
35 |
+
class InstructIR(nn.Module):
|
36 |
+
"""
|
37 |
+
InstructIR model using NAFNet (ECCV 2022) as backbone.
|
38 |
+
The model takes as input an RGB image and a text embedding (encoded instruction).
|
39 |
+
Described in Paper Section 3.3
|
40 |
+
"""
|
41 |
+
|
42 |
+
def __init__(self, img_channel=3, width=16, middle_blk_num=1, enc_blk_nums=[], dec_blk_nums=[], txtdim=768):
|
43 |
+
super().__init__()
|
44 |
+
|
45 |
+
self.intro = nn.Conv2d(in_channels=img_channel, out_channels=width, kernel_size=3, padding=1, stride=1, groups=1,
|
46 |
+
bias=True)
|
47 |
+
self.ending = nn.Conv2d(in_channels=width, out_channels=img_channel, kernel_size=3, padding=1, stride=1, groups=1,
|
48 |
+
bias=True)
|
49 |
+
|
50 |
+
self.encoders = nn.ModuleList()
|
51 |
+
self.decoders = nn.ModuleList()
|
52 |
+
self.middle_blks = nn.ModuleList()
|
53 |
+
self.ups = nn.ModuleList()
|
54 |
+
self.downs = nn.ModuleList()
|
55 |
+
self.enc_cond = nn.ModuleList()
|
56 |
+
self.dec_cond = nn.ModuleList()
|
57 |
+
|
58 |
+
chan = width
|
59 |
+
for num in enc_blk_nums:
|
60 |
+
self.encoders.append(
|
61 |
+
nn.Sequential(
|
62 |
+
*[NAFBlock(chan) for _ in range(num)]
|
63 |
+
)
|
64 |
+
)
|
65 |
+
|
66 |
+
self.enc_cond.append(ICB(chan, txtdim))
|
67 |
+
|
68 |
+
self.downs.append(
|
69 |
+
nn.Conv2d(chan, 2*chan, 2, 2)
|
70 |
+
)
|
71 |
+
chan = chan * 2
|
72 |
+
|
73 |
+
self.middle_blks = nn.Sequential(
|
74 |
+
*[NAFBlock(chan) for _ in range(middle_blk_num)]
|
75 |
+
)
|
76 |
+
|
77 |
+
for num in dec_blk_nums:
|
78 |
+
self.ups.append(
|
79 |
+
nn.Sequential(
|
80 |
+
nn.Conv2d(chan, chan * 2, 1, bias=False),
|
81 |
+
nn.PixelShuffle(2)
|
82 |
+
)
|
83 |
+
)
|
84 |
+
chan = chan // 2
|
85 |
+
self.decoders.append(
|
86 |
+
nn.Sequential(
|
87 |
+
*[NAFBlock(chan) for _ in range(num)]
|
88 |
+
)
|
89 |
+
)
|
90 |
+
# Add text embedding as modulation
|
91 |
+
self.dec_cond.append(ICB(chan, txtdim))
|
92 |
+
|
93 |
+
self.padder_size = 2 ** len(self.encoders)
|
94 |
+
|
95 |
+
def forward(self, inp, txtembd):
|
96 |
+
B, C, H, W = inp.shape
|
97 |
+
inp = self.check_image_size(inp)
|
98 |
+
|
99 |
+
x = self.intro(inp)
|
100 |
+
encs = []
|
101 |
+
|
102 |
+
for encoder, enc_mod, down in zip(self.encoders, self.enc_cond, self.downs):
|
103 |
+
x = encoder(x)
|
104 |
+
x = enc_mod(x, txtembd)
|
105 |
+
encs.append(x)
|
106 |
+
x = down(x)
|
107 |
+
|
108 |
+
x = self.middle_blks(x)
|
109 |
+
|
110 |
+
for decoder, up, enc_skip, dec_mod in zip(self.decoders, self.ups, encs[::-1], self.dec_cond):
|
111 |
+
x = up(x)
|
112 |
+
x = x + enc_skip
|
113 |
+
x = decoder(x)
|
114 |
+
x = dec_mod(x, txtembd)
|
115 |
+
|
116 |
+
x = self.ending(x)
|
117 |
+
x = x + inp
|
118 |
+
|
119 |
+
return x[:, :, :H, :W]
|
120 |
+
|
121 |
+
def check_image_size(self, x):
|
122 |
+
_, _, h, w = x.size()
|
123 |
+
mod_pad_h = (self.padder_size - h % self.padder_size) % self.padder_size
|
124 |
+
mod_pad_w = (self.padder_size - w % self.padder_size) % self.padder_size
|
125 |
+
x = F.pad(x, (0, mod_pad_w, 0, mod_pad_h))
|
126 |
+
return x
|
127 |
+
|
128 |
+
|
129 |
+
def create_model(input_channels = 3, width = 32, enc_blks = [2, 2, 4, 8], middle_blk_num = 12, dec_blks = [2, 2, 2, 2], txtdim=768):
|
130 |
+
|
131 |
+
net = InstructIR(img_channel=input_channels, width=width, middle_blk_num=middle_blk_num,
|
132 |
+
enc_blk_nums=enc_blks, dec_blk_nums=dec_blks, txtdim=txtdim)
|
133 |
+
|
134 |
+
return net
|
models/lm_instructir-7d.pt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:b239e5d5dbc811813a90e709f9647dead0e35a96a294a7d6c5263da549016fe6
|
3 |
+
size 403275
|
models/nafnet.py
ADDED
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# ------------------------------------------------------------------------
|
2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
3 |
+
# ------------------------------------------------------------------------
|
4 |
+
# Source: https://github.com/megvii-research/NAFNet
|
5 |
+
|
6 |
+
'''
|
7 |
+
Simple Baselines for Image Restoration
|
8 |
+
|
9 |
+
@article{chen2022simple,
|
10 |
+
title={Simple Baselines for Image Restoration},
|
11 |
+
author={Chen, Liangyu and Chu, Xiaojie and Zhang, Xiangyu and Sun, Jian},
|
12 |
+
journal={arXiv preprint arXiv:2204.04676},
|
13 |
+
year={2022}
|
14 |
+
}
|
15 |
+
'''
|
16 |
+
|
17 |
+
import math
|
18 |
+
import torch
|
19 |
+
import torch.nn as nn
|
20 |
+
import torch.nn.functional as F
|
21 |
+
from torch.nn import init as init
|
22 |
+
from torch.nn.modules.batchnorm import _BatchNorm
|
23 |
+
from models.nafnet_utils import Local_Base, LayerNorm2d
|
24 |
+
|
25 |
+
|
26 |
+
class SimpleGate(nn.Module):
|
27 |
+
def forward(self, x):
|
28 |
+
x1, x2 = x.chunk(2, dim=1)
|
29 |
+
return x1 * x2
|
30 |
+
|
31 |
+
class NAFBlock(nn.Module):
|
32 |
+
def __init__(self, c, DW_Expand=2, FFN_Expand=2, drop_out_rate=0.):
|
33 |
+
super().__init__()
|
34 |
+
dw_channel = c * DW_Expand
|
35 |
+
self.conv1 = nn.Conv2d(in_channels=c, out_channels=dw_channel, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
|
36 |
+
self.conv2 = nn.Conv2d(in_channels=dw_channel, out_channels=dw_channel, kernel_size=3, padding=1, stride=1, groups=dw_channel,
|
37 |
+
bias=True)
|
38 |
+
self.conv3 = nn.Conv2d(in_channels=dw_channel // 2, out_channels=c, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
|
39 |
+
|
40 |
+
# Simplified Channel Attention
|
41 |
+
self.sca = nn.Sequential(
|
42 |
+
nn.AdaptiveAvgPool2d(1),
|
43 |
+
nn.Conv2d(in_channels=dw_channel // 2, out_channels=dw_channel // 2, kernel_size=1, padding=0, stride=1,
|
44 |
+
groups=1, bias=True),
|
45 |
+
)
|
46 |
+
|
47 |
+
# SimpleGate
|
48 |
+
self.sg = SimpleGate()
|
49 |
+
|
50 |
+
ffn_channel = FFN_Expand * c
|
51 |
+
self.conv4 = nn.Conv2d(in_channels=c, out_channels=ffn_channel, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
|
52 |
+
self.conv5 = nn.Conv2d(in_channels=ffn_channel // 2, out_channels=c, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
|
53 |
+
|
54 |
+
self.norm1 = LayerNorm2d(c)
|
55 |
+
self.norm2 = LayerNorm2d(c)
|
56 |
+
|
57 |
+
self.dropout1 = nn.Dropout(drop_out_rate) if drop_out_rate > 0. else nn.Identity()
|
58 |
+
self.dropout2 = nn.Dropout(drop_out_rate) if drop_out_rate > 0. else nn.Identity()
|
59 |
+
|
60 |
+
self.beta = nn.Parameter(torch.zeros((1, c, 1, 1)), requires_grad=True)
|
61 |
+
self.gamma = nn.Parameter(torch.zeros((1, c, 1, 1)), requires_grad=True)
|
62 |
+
|
63 |
+
def forward(self, inp):
|
64 |
+
x = inp
|
65 |
+
|
66 |
+
x = self.norm1(x)
|
67 |
+
|
68 |
+
x = self.conv1(x)
|
69 |
+
x = self.conv2(x)
|
70 |
+
x = self.sg(x)
|
71 |
+
x = x * self.sca(x)
|
72 |
+
x = self.conv3(x)
|
73 |
+
|
74 |
+
x = self.dropout1(x)
|
75 |
+
|
76 |
+
y = inp + x * self.beta
|
77 |
+
|
78 |
+
x = self.conv4(self.norm2(y))
|
79 |
+
x = self.sg(x)
|
80 |
+
x = self.conv5(x)
|
81 |
+
|
82 |
+
x = self.dropout2(x)
|
83 |
+
|
84 |
+
return y + x * self.gamma
|
85 |
+
|
86 |
+
|
87 |
+
class NAFNet(nn.Module):
|
88 |
+
|
89 |
+
def __init__(self, img_channel=3, width=16, middle_blk_num=1, enc_blk_nums=[], dec_blk_nums=[]):
|
90 |
+
super().__init__()
|
91 |
+
|
92 |
+
self.intro = nn.Conv2d(in_channels=img_channel, out_channels=width, kernel_size=3, padding=1, stride=1, groups=1,
|
93 |
+
bias=True)
|
94 |
+
self.ending = nn.Conv2d(in_channels=width, out_channels=img_channel, kernel_size=3, padding=1, stride=1, groups=1,
|
95 |
+
bias=True)
|
96 |
+
|
97 |
+
self.encoders = nn.ModuleList()
|
98 |
+
self.decoders = nn.ModuleList()
|
99 |
+
self.middle_blks = nn.ModuleList()
|
100 |
+
self.ups = nn.ModuleList()
|
101 |
+
self.downs = nn.ModuleList()
|
102 |
+
|
103 |
+
chan = width
|
104 |
+
for num in enc_blk_nums:
|
105 |
+
self.encoders.append(
|
106 |
+
nn.Sequential(
|
107 |
+
*[NAFBlock(chan) for _ in range(num)]
|
108 |
+
)
|
109 |
+
)
|
110 |
+
self.downs.append(
|
111 |
+
nn.Conv2d(chan, 2*chan, 2, 2)
|
112 |
+
)
|
113 |
+
chan = chan * 2
|
114 |
+
|
115 |
+
self.middle_blks = \
|
116 |
+
nn.Sequential(
|
117 |
+
*[NAFBlock(chan) for _ in range(middle_blk_num)]
|
118 |
+
)
|
119 |
+
|
120 |
+
for num in dec_blk_nums:
|
121 |
+
self.ups.append(
|
122 |
+
nn.Sequential(
|
123 |
+
nn.Conv2d(chan, chan * 2, 1, bias=False),
|
124 |
+
nn.PixelShuffle(2)
|
125 |
+
)
|
126 |
+
)
|
127 |
+
chan = chan // 2
|
128 |
+
self.decoders.append(
|
129 |
+
nn.Sequential(
|
130 |
+
*[NAFBlock(chan) for _ in range(num)]
|
131 |
+
)
|
132 |
+
)
|
133 |
+
|
134 |
+
self.padder_size = 2 ** len(self.encoders)
|
135 |
+
|
136 |
+
def forward(self, inp):
|
137 |
+
B, C, H, W = inp.shape
|
138 |
+
inp = self.check_image_size(inp)
|
139 |
+
|
140 |
+
x = self.intro(inp)
|
141 |
+
|
142 |
+
encs = []
|
143 |
+
|
144 |
+
for encoder, down in zip(self.encoders, self.downs):
|
145 |
+
x = encoder(x)
|
146 |
+
encs.append(x)
|
147 |
+
x = down(x)
|
148 |
+
|
149 |
+
x = self.middle_blks(x)
|
150 |
+
|
151 |
+
for decoder, up, enc_skip in zip(self.decoders, self.ups, encs[::-1]):
|
152 |
+
x = up(x)
|
153 |
+
x = x + enc_skip
|
154 |
+
x = decoder(x)
|
155 |
+
|
156 |
+
x = self.ending(x)
|
157 |
+
x = x + inp
|
158 |
+
|
159 |
+
return x[:, :, :H, :W]
|
160 |
+
|
161 |
+
def check_image_size(self, x):
|
162 |
+
_, _, h, w = x.size()
|
163 |
+
mod_pad_h = (self.padder_size - h % self.padder_size) % self.padder_size
|
164 |
+
mod_pad_w = (self.padder_size - w % self.padder_size) % self.padder_size
|
165 |
+
x = F.pad(x, (0, mod_pad_w, 0, mod_pad_h))
|
166 |
+
return x
|
167 |
+
|
168 |
+
class NAFNetLocal(Local_Base, NAFNet):
|
169 |
+
def __init__(self, *args, train_size=(1, 3, 256, 256), fast_imp=False, **kwargs):
|
170 |
+
Local_Base.__init__(self)
|
171 |
+
NAFNet.__init__(self, *args, **kwargs)
|
172 |
+
|
173 |
+
N, C, H, W = train_size
|
174 |
+
base_size = (int(H * 1.5), int(W * 1.5))
|
175 |
+
|
176 |
+
self.eval()
|
177 |
+
with torch.no_grad():
|
178 |
+
self.convert(base_size=base_size, train_size=train_size, fast_imp=fast_imp)
|
179 |
+
|
180 |
+
|
181 |
+
def create_nafnet(input_channels = 3, width = 32, enc_blks = [2, 2, 4, 8], middle_blk_num = 12, dec_blks = [2, 2, 2, 2]):
|
182 |
+
"""
|
183 |
+
Create Nafnet model
|
184 |
+
https://github.com/megvii-research/NAFNet/blob/main/options/test/SIDD/NAFNet-width32.yml
|
185 |
+
"""
|
186 |
+
|
187 |
+
net = NAFNet(img_channel=input_channels, width=width, middle_blk_num=middle_blk_num,
|
188 |
+
enc_blk_nums=enc_blks, dec_blk_nums=dec_blks)
|
189 |
+
|
190 |
+
# inp_shape = (3, 256, 256)
|
191 |
+
|
192 |
+
# from ptflops import get_model_complexity_info
|
193 |
+
|
194 |
+
# macs, params = get_model_complexity_info(net, inp_shape, verbose=False, print_per_layer_stat=False)
|
195 |
+
|
196 |
+
# params = float(params[:-3])
|
197 |
+
# macs = float(macs[:-4])
|
198 |
+
|
199 |
+
# print(macs, params)
|
200 |
+
|
201 |
+
return net
|
models/nafnet_utils.py
ADDED
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# ------------------------------------------------------------------------
|
2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
3 |
+
# ------------------------------------------------------------------------
|
4 |
+
# Source: https://github.com/megvii-research/NAFNet
|
5 |
+
|
6 |
+
import numpy as np
|
7 |
+
import torch
|
8 |
+
import torch.nn as nn
|
9 |
+
import torch.nn.functional as F
|
10 |
+
import math
|
11 |
+
|
12 |
+
class LayerNormFunction(torch.autograd.Function):
|
13 |
+
|
14 |
+
@staticmethod
|
15 |
+
def forward(ctx, x, weight, bias, eps):
|
16 |
+
ctx.eps = eps
|
17 |
+
N, C, H, W = x.size()
|
18 |
+
mu = x.mean(1, keepdim=True)
|
19 |
+
var = (x - mu).pow(2).mean(1, keepdim=True)
|
20 |
+
y = (x - mu) / (var + eps).sqrt()
|
21 |
+
ctx.save_for_backward(y, var, weight)
|
22 |
+
y = weight.view(1, C, 1, 1) * y + bias.view(1, C, 1, 1)
|
23 |
+
return y
|
24 |
+
|
25 |
+
@staticmethod
|
26 |
+
def backward(ctx, grad_output):
|
27 |
+
eps = ctx.eps
|
28 |
+
|
29 |
+
N, C, H, W = grad_output.size()
|
30 |
+
y, var, weight = ctx.saved_variables
|
31 |
+
g = grad_output * weight.view(1, C, 1, 1)
|
32 |
+
mean_g = g.mean(dim=1, keepdim=True)
|
33 |
+
|
34 |
+
mean_gy = (g * y).mean(dim=1, keepdim=True)
|
35 |
+
gx = 1. / torch.sqrt(var + eps) * (g - y * mean_gy - mean_g)
|
36 |
+
return gx, (grad_output * y).sum(dim=3).sum(dim=2).sum(dim=0), grad_output.sum(dim=3).sum(dim=2).sum(
|
37 |
+
dim=0), None
|
38 |
+
|
39 |
+
class LayerNorm2d(nn.Module):
|
40 |
+
|
41 |
+
def __init__(self, channels, eps=1e-6):
|
42 |
+
super(LayerNorm2d, self).__init__()
|
43 |
+
self.register_parameter('weight', nn.Parameter(torch.ones(channels)))
|
44 |
+
self.register_parameter('bias', nn.Parameter(torch.zeros(channels)))
|
45 |
+
self.eps = eps
|
46 |
+
|
47 |
+
def forward(self, x):
|
48 |
+
return LayerNormFunction.apply(x, self.weight, self.bias, self.eps)
|
49 |
+
|
50 |
+
|
51 |
+
|
52 |
+
class AvgPool2d(nn.Module):
|
53 |
+
def __init__(self, kernel_size=None, base_size=None, auto_pad=True, fast_imp=False, train_size=None):
|
54 |
+
super().__init__()
|
55 |
+
self.kernel_size = kernel_size
|
56 |
+
self.base_size = base_size
|
57 |
+
self.auto_pad = auto_pad
|
58 |
+
|
59 |
+
# only used for fast implementation
|
60 |
+
self.fast_imp = fast_imp
|
61 |
+
self.rs = [5, 4, 3, 2, 1]
|
62 |
+
self.max_r1 = self.rs[0]
|
63 |
+
self.max_r2 = self.rs[0]
|
64 |
+
self.train_size = train_size
|
65 |
+
|
66 |
+
def extra_repr(self) -> str:
|
67 |
+
return 'kernel_size={}, base_size={}, stride={}, fast_imp={}'.format(
|
68 |
+
self.kernel_size, self.base_size, self.kernel_size, self.fast_imp
|
69 |
+
)
|
70 |
+
|
71 |
+
def forward(self, x):
|
72 |
+
if self.kernel_size is None and self.base_size:
|
73 |
+
train_size = self.train_size
|
74 |
+
if isinstance(self.base_size, int):
|
75 |
+
self.base_size = (self.base_size, self.base_size)
|
76 |
+
self.kernel_size = list(self.base_size)
|
77 |
+
self.kernel_size[0] = x.shape[2] * self.base_size[0] // train_size[-2]
|
78 |
+
self.kernel_size[1] = x.shape[3] * self.base_size[1] // train_size[-1]
|
79 |
+
|
80 |
+
# only used for fast implementation
|
81 |
+
self.max_r1 = max(1, self.rs[0] * x.shape[2] // train_size[-2])
|
82 |
+
self.max_r2 = max(1, self.rs[0] * x.shape[3] // train_size[-1])
|
83 |
+
|
84 |
+
if self.kernel_size[0] >= x.size(-2) and self.kernel_size[1] >= x.size(-1):
|
85 |
+
return F.adaptive_avg_pool2d(x, 1)
|
86 |
+
|
87 |
+
if self.fast_imp: # Non-equivalent implementation but faster
|
88 |
+
h, w = x.shape[2:]
|
89 |
+
if self.kernel_size[0] >= h and self.kernel_size[1] >= w:
|
90 |
+
out = F.adaptive_avg_pool2d(x, 1)
|
91 |
+
else:
|
92 |
+
r1 = [r for r in self.rs if h % r == 0][0]
|
93 |
+
r2 = [r for r in self.rs if w % r == 0][0]
|
94 |
+
# reduction_constraint
|
95 |
+
r1 = min(self.max_r1, r1)
|
96 |
+
r2 = min(self.max_r2, r2)
|
97 |
+
s = x[:, :, ::r1, ::r2].cumsum(dim=-1).cumsum(dim=-2)
|
98 |
+
n, c, h, w = s.shape
|
99 |
+
k1, k2 = min(h - 1, self.kernel_size[0] // r1), min(w - 1, self.kernel_size[1] // r2)
|
100 |
+
out = (s[:, :, :-k1, :-k2] - s[:, :, :-k1, k2:] - s[:, :, k1:, :-k2] + s[:, :, k1:, k2:]) / (k1 * k2)
|
101 |
+
out = torch.nn.functional.interpolate(out, scale_factor=(r1, r2))
|
102 |
+
else:
|
103 |
+
n, c, h, w = x.shape
|
104 |
+
s = x.cumsum(dim=-1).cumsum_(dim=-2)
|
105 |
+
s = torch.nn.functional.pad(s, (1, 0, 1, 0)) # pad 0 for convenience
|
106 |
+
k1, k2 = min(h, self.kernel_size[0]), min(w, self.kernel_size[1])
|
107 |
+
s1, s2, s3, s4 = s[:, :, :-k1, :-k2], s[:, :, :-k1, k2:], s[:, :, k1:, :-k2], s[:, :, k1:, k2:]
|
108 |
+
out = s4 + s1 - s2 - s3
|
109 |
+
out = out / (k1 * k2)
|
110 |
+
|
111 |
+
if self.auto_pad:
|
112 |
+
n, c, h, w = x.shape
|
113 |
+
_h, _w = out.shape[2:]
|
114 |
+
# print(x.shape, self.kernel_size)
|
115 |
+
pad2d = ((w - _w) // 2, (w - _w + 1) // 2, (h - _h) // 2, (h - _h + 1) // 2)
|
116 |
+
out = torch.nn.functional.pad(out, pad2d, mode='replicate')
|
117 |
+
|
118 |
+
return out
|
119 |
+
|
120 |
+
def replace_layers(model, base_size, train_size, fast_imp, **kwargs):
|
121 |
+
for n, m in model.named_children():
|
122 |
+
if len(list(m.children())) > 0:
|
123 |
+
## compound module, go inside it
|
124 |
+
replace_layers(m, base_size, train_size, fast_imp, **kwargs)
|
125 |
+
|
126 |
+
if isinstance(m, nn.AdaptiveAvgPool2d):
|
127 |
+
pool = AvgPool2d(base_size=base_size, fast_imp=fast_imp, train_size=train_size)
|
128 |
+
assert m.output_size == 1
|
129 |
+
setattr(model, n, pool)
|
130 |
+
|
131 |
+
|
132 |
+
'''
|
133 |
+
ref.
|
134 |
+
@article{chu2021tlsc,
|
135 |
+
title={Revisiting Global Statistics Aggregation for Improving Image Restoration},
|
136 |
+
author={Chu, Xiaojie and Chen, Liangyu and and Chen, Chengpeng and Lu, Xin},
|
137 |
+
journal={arXiv preprint arXiv:2112.04491},
|
138 |
+
year={2021}
|
139 |
+
}
|
140 |
+
'''
|
141 |
+
class Local_Base():
|
142 |
+
def convert(self, *args, train_size, **kwargs):
|
143 |
+
replace_layers(self, *args, train_size=train_size, **kwargs)
|
144 |
+
imgs = torch.rand(train_size)
|
145 |
+
with torch.no_grad():
|
146 |
+
self.forward(imgs)
|
predict.py
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Prediction interface for Cog ⚙️
|
2 |
+
# https://github.com/replicate/cog/blob/main/docs/python.md
|
3 |
+
|
4 |
+
import os
|
5 |
+
import numpy as np
|
6 |
+
import yaml
|
7 |
+
import torch
|
8 |
+
from cog import BasePredictor, Input, Path
|
9 |
+
|
10 |
+
from utils import *
|
11 |
+
from models import instructir
|
12 |
+
from text.models import LanguageModel, LMHead
|
13 |
+
|
14 |
+
os.environ["TOKENIZERS_PARALLELISM"] = "false"
|
15 |
+
|
16 |
+
|
17 |
+
class Predictor(BasePredictor):
|
18 |
+
def setup(self) -> None:
|
19 |
+
"""Load the model into memory to make running multiple predictions efficient"""
|
20 |
+
|
21 |
+
LM_MODEL = "models/lm_instructir-7d.pt"
|
22 |
+
MODEL_NAME = "models/im_instructir-7d.pt"
|
23 |
+
device = torch.device("cpu")
|
24 |
+
|
25 |
+
with open(os.path.join("configs/eval5d.yml"), "r") as f:
|
26 |
+
config = yaml.safe_load(f)
|
27 |
+
|
28 |
+
cfg = dict2namespace(config)
|
29 |
+
|
30 |
+
torch.backends.cudnn.deterministic = True
|
31 |
+
self.model = instructir.create_model(
|
32 |
+
input_channels=cfg.model.in_ch,
|
33 |
+
width=cfg.model.width,
|
34 |
+
enc_blks=cfg.model.enc_blks,
|
35 |
+
middle_blk_num=cfg.model.middle_blk_num,
|
36 |
+
dec_blks=cfg.model.dec_blks,
|
37 |
+
txtdim=cfg.model.textdim,
|
38 |
+
)
|
39 |
+
|
40 |
+
self.model = self.model.to(device)
|
41 |
+
print("IMAGE MODEL CKPT:", MODEL_NAME)
|
42 |
+
self.model.load_state_dict(
|
43 |
+
torch.load(MODEL_NAME, map_location="cpu"), strict=True
|
44 |
+
)
|
45 |
+
|
46 |
+
# Initialize the LanguageModel class
|
47 |
+
LMODEL = cfg.llm.model
|
48 |
+
self.language_model = LanguageModel(model=LMODEL)
|
49 |
+
self.lm_head = LMHead(
|
50 |
+
embedding_dim=cfg.llm.model_dim,
|
51 |
+
hidden_dim=cfg.llm.embd_dim,
|
52 |
+
num_classes=cfg.llm.nclasses,
|
53 |
+
)
|
54 |
+
self.lm_head = self.lm_head # .to(device)
|
55 |
+
|
56 |
+
print("LMHEAD MODEL CKPT:", LM_MODEL)
|
57 |
+
self.lm_head.load_state_dict(
|
58 |
+
torch.load(LM_MODEL, map_location="cpu"), strict=True
|
59 |
+
)
|
60 |
+
print("Loaded weights!")
|
61 |
+
|
62 |
+
def predict(
|
63 |
+
self,
|
64 |
+
image: Path = Input(description="Input image."),
|
65 |
+
prompt: str = Input(description="Input prompt."),
|
66 |
+
seed: int = Input(
|
67 |
+
description="Random seed. Leave blank to randomize the seed", default=None
|
68 |
+
),
|
69 |
+
) -> Path:
|
70 |
+
"""Run a single prediction on the model"""
|
71 |
+
if seed is None:
|
72 |
+
seed = int.from_bytes(os.urandom(2), "big")
|
73 |
+
print(f"Using seed: {seed}")
|
74 |
+
seed_everything(SEED=seed)
|
75 |
+
|
76 |
+
torch.cuda.empty_cache()
|
77 |
+
torch.cuda.reset_peak_memory_stats()
|
78 |
+
|
79 |
+
image = load_img(str(image))
|
80 |
+
out_image = process_img(
|
81 |
+
image, prompt, self.language_model, self.model, self.lm_head
|
82 |
+
)
|
83 |
+
|
84 |
+
out_path = "/tmp/out.png"
|
85 |
+
saveImage(out_path, out_image)
|
86 |
+
|
87 |
+
return Path(out_path)
|
88 |
+
|
89 |
+
|
90 |
+
def process_img(image, prompt, language_model, model, lm_head):
|
91 |
+
"""
|
92 |
+
Given an image and a prompt, we run InstructIR to restore the image following the human prompt.
|
93 |
+
image: RGB image as numpy array normalized to [0,1]
|
94 |
+
prompt: plain python string,
|
95 |
+
|
96 |
+
returns the restored image as numpy array.
|
97 |
+
"""
|
98 |
+
|
99 |
+
# Convert the image to tensor
|
100 |
+
y = torch.Tensor(image).permute(2, 0, 1).unsqueeze(0)
|
101 |
+
|
102 |
+
# Get the text embedding (and predicted degradation class)
|
103 |
+
lm_embd = language_model(prompt)
|
104 |
+
lm_embd = lm_embd # .to(device)
|
105 |
+
text_embd, deg_pred = lm_head(lm_embd)
|
106 |
+
|
107 |
+
# Forward pass: Paper Figure 2
|
108 |
+
x_hat = model(y, text_embd)
|
109 |
+
|
110 |
+
# convert the restored image <x_hat> into a np array
|
111 |
+
restored_img = x_hat[0].permute(1, 2, 0).cpu().detach().numpy()
|
112 |
+
restored_img = np.clip(restored_img, 0.0, 1.0)
|
113 |
+
return restored_img
|
requirements.txt
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
torch
|
2 |
+
transformers
|
3 |
+
numpy
|
4 |
+
PyYAML
|
5 |
+
Pillow>=6.2.2
|
6 |
+
sentence-transformers==2.3.0
|
7 |
+
gradio==4.16.0
|
8 |
+
#gradio_imageslider==0.0.18
|
results/.gitkeep
ADDED
File without changes
|
static/1.html
ADDED
@@ -0,0 +1,559 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html><script type="text/javascript">try {
|
3 |
+
(function injectPageScriptAPI(scriptName, shouldOverrideWebSocket, shouldOverrideWebRTC, isInjected) {
|
4 |
+
|
5 |
+
'use strict';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* If script have been injected into a frame via contentWindow then we can simply take the copy of messageChannel left for us by parent document
|
9 |
+
* Otherwise creates new message channel that sends a message to the content-script to check if request should be allowed or not.
|
10 |
+
*/
|
11 |
+
var messageChannel = isInjected ? window[scriptName] : (function () {
|
12 |
+
|
13 |
+
// Save original postMessage and addEventListener functions to prevent webpage from tampering both.
|
14 |
+
var postMessage = window.postMessage;
|
15 |
+
var addEventListener = window.addEventListener;
|
16 |
+
|
17 |
+
// Current request ID (incremented every time we send a new message)
|
18 |
+
var currentRequestId = 0;
|
19 |
+
var requestsMap = {};
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Handles messages sent from the content script back to the page script.
|
23 |
+
*
|
24 |
+
* @param event Event with necessary data
|
25 |
+
*/
|
26 |
+
var onMessageReceived = function (event) {
|
27 |
+
|
28 |
+
if (!event.data || !event.data.direction || event.data.direction !== "to-page-script@abu") {
|
29 |
+
return;
|
30 |
+
}
|
31 |
+
|
32 |
+
var requestData = requestsMap[event.data.requestId];
|
33 |
+
if (requestData) {
|
34 |
+
var wrapper = requestData.wrapper;
|
35 |
+
requestData.onResponseReceived(wrapper, event.data.block);
|
36 |
+
delete requestsMap[event.data.requestId];
|
37 |
+
}
|
38 |
+
};
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @param url The URL to which wrapped object is willing to connect
|
42 |
+
* @param requestType Request type ( WEBSOCKET or WEBRTC)
|
43 |
+
* @param wrapper WebSocket wrapper instance
|
44 |
+
* @param onResponseReceived Called when response is received
|
45 |
+
*/
|
46 |
+
var sendMessage = function (url, requestType, wrapper, onResponseReceived) {
|
47 |
+
|
48 |
+
if (currentRequestId === 0) {
|
49 |
+
// Subscribe to response when this method is called for the first time
|
50 |
+
addEventListener.call(window, "message", onMessageReceived, false);
|
51 |
+
}
|
52 |
+
|
53 |
+
var requestId = ++currentRequestId;
|
54 |
+
requestsMap[requestId] = {
|
55 |
+
wrapper: wrapper,
|
56 |
+
onResponseReceived: onResponseReceived
|
57 |
+
};
|
58 |
+
|
59 |
+
var message = {
|
60 |
+
requestId: requestId,
|
61 |
+
direction: 'from-page-script@abu',
|
62 |
+
elementUrl: url,
|
63 |
+
documentUrl: document.URL,
|
64 |
+
requestType: requestType
|
65 |
+
};
|
66 |
+
|
67 |
+
// Send a message to the background page to check if the request should be blocked
|
68 |
+
postMessage.call(window, message, "*");
|
69 |
+
};
|
70 |
+
|
71 |
+
return {
|
72 |
+
sendMessage: sendMessage
|
73 |
+
};
|
74 |
+
|
75 |
+
})();
|
76 |
+
|
77 |
+
/*
|
78 |
+
* In some case Chrome won't run content scripts inside frames.
|
79 |
+
* So we have to intercept access to contentWindow/contentDocument and manually inject wrapper script into this context
|
80 |
+
*
|
81 |
+
* Based on: https://github.com/adblockplus/adblockpluschrome/commit/1aabfb3346dc0821c52dd9e97f7d61b8c99cd707
|
82 |
+
*/
|
83 |
+
var injectedToString = Function.prototype.toString.bind(injectPageScriptAPI);
|
84 |
+
|
85 |
+
var injectedFramesAdd;
|
86 |
+
var injectedFramesHas;
|
87 |
+
if (window.WeakSet instanceof Function) {
|
88 |
+
var injectedFrames = new WeakSet();
|
89 |
+
injectedFramesAdd = WeakSet.prototype.add.bind(injectedFrames);
|
90 |
+
injectedFramesHas = WeakSet.prototype.has.bind(injectedFrames);
|
91 |
+
} else {
|
92 |
+
var frames = [];
|
93 |
+
injectedFramesAdd = function (el) {
|
94 |
+
if (frames.indexOf(el) < 0) {
|
95 |
+
frames.push(el);
|
96 |
+
}
|
97 |
+
};
|
98 |
+
injectedFramesHas = function (el) {
|
99 |
+
return frames.indexOf(el) >= 0;
|
100 |
+
};
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Injects wrapper's script into passed window
|
105 |
+
* @param contentWindow Frame's content window
|
106 |
+
*/
|
107 |
+
function injectPageScriptAPIInWindow(contentWindow) {
|
108 |
+
try {
|
109 |
+
if (contentWindow && !injectedFramesHas(contentWindow)) {
|
110 |
+
injectedFramesAdd(contentWindow);
|
111 |
+
contentWindow[scriptName] = messageChannel; // Left message channel for the injected script
|
112 |
+
var args = "'" + scriptName + "', " + shouldOverrideWebSocket + ", " + shouldOverrideWebRTC + ", true";
|
113 |
+
contentWindow.eval("(" + injectedToString() + ")(" + args + ");");
|
114 |
+
delete contentWindow[scriptName];
|
115 |
+
}
|
116 |
+
} catch (e) {
|
117 |
+
}
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Overrides access to contentWindow/contentDocument for the passed HTML element's interface (iframe, frame, object)
|
122 |
+
* If the content of one of these objects is requested we will inject our wrapper script.
|
123 |
+
* @param iface HTML element's interface
|
124 |
+
*/
|
125 |
+
function overrideContentAccess(iface) {
|
126 |
+
|
127 |
+
var contentWindowDescriptor = Object.getOwnPropertyDescriptor(iface.prototype, "contentWindow");
|
128 |
+
var contentDocumentDescriptor = Object.getOwnPropertyDescriptor(iface.prototype, "contentDocument");
|
129 |
+
|
130 |
+
// Apparently in HTMLObjectElement.prototype.contentWindow does not exist
|
131 |
+
// in older versions of Chrome such as 42.
|
132 |
+
if (!contentWindowDescriptor) {
|
133 |
+
return;
|
134 |
+
}
|
135 |
+
|
136 |
+
var getContentWindow = Function.prototype.call.bind(contentWindowDescriptor.get);
|
137 |
+
var getContentDocument = Function.prototype.call.bind(contentDocumentDescriptor.get);
|
138 |
+
|
139 |
+
contentWindowDescriptor.get = function () {
|
140 |
+
var contentWindow = getContentWindow(this);
|
141 |
+
injectPageScriptAPIInWindow(contentWindow);
|
142 |
+
return contentWindow;
|
143 |
+
};
|
144 |
+
contentDocumentDescriptor.get = function () {
|
145 |
+
injectPageScriptAPIInWindow(getContentWindow(this));
|
146 |
+
return getContentDocument(this);
|
147 |
+
};
|
148 |
+
|
149 |
+
Object.defineProperty(iface.prototype, "contentWindow", contentWindowDescriptor);
|
150 |
+
Object.defineProperty(iface.prototype, "contentDocument", contentDocumentDescriptor);
|
151 |
+
}
|
152 |
+
|
153 |
+
var interfaces = [HTMLFrameElement, HTMLIFrameElement, HTMLObjectElement];
|
154 |
+
for (var i = 0; i < interfaces.length; i++) {
|
155 |
+
overrideContentAccess(interfaces[i]);
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Defines properties in destination object
|
160 |
+
* @param src Source object
|
161 |
+
* @param dest Destination object
|
162 |
+
* @param properties Properties to copy
|
163 |
+
*/
|
164 |
+
var copyProperties = function (src, dest, properties) {
|
165 |
+
for (var i = 0; i < properties.length; i++) {
|
166 |
+
var prop = properties[i];
|
167 |
+
var descriptor = Object.getOwnPropertyDescriptor(src, prop);
|
168 |
+
// Passed property may be undefined
|
169 |
+
if (descriptor) {
|
170 |
+
Object.defineProperty(dest, prop, descriptor);
|
171 |
+
}
|
172 |
+
}
|
173 |
+
};
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Check request by sending message to content script
|
177 |
+
* @param url URL to block
|
178 |
+
* @param type Request type
|
179 |
+
* @param callback Result callback
|
180 |
+
*/
|
181 |
+
var checkRequest = function (url, type, callback) {
|
182 |
+
messageChannel.sendMessage(url, type, this, function (wrapper, blockConnection) {
|
183 |
+
callback(blockConnection);
|
184 |
+
});
|
185 |
+
};
|
186 |
+
|
187 |
+
/**
|
188 |
+
* The function overrides window.WebSocket with our wrapper, that will check url with filters through messaging with content-script.
|
189 |
+
*
|
190 |
+
* IMPORTANT NOTE:
|
191 |
+
* This function is first loaded as a content script. The only purpose of it is to call
|
192 |
+
* the "toString" method and use resulting string as a text content for injected script.
|
193 |
+
*/
|
194 |
+
var overrideWebSocket = function () {
|
195 |
+
|
196 |
+
if (!(window.WebSocket instanceof Function)) {
|
197 |
+
return;
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* WebSocket wrapper implementation.
|
202 |
+
* https://github.com/AdguardTeam/AdguardBrowserExtension/issues/349
|
203 |
+
*
|
204 |
+
* Based on:
|
205 |
+
* https://github.com/adblockplus/adblockpluschrome/commit/457a336ee55a433217c3ffe5d363e5c6980f26f4
|
206 |
+
*/
|
207 |
+
|
208 |
+
/**
|
209 |
+
* As far as possible we must track everything we use that could be sabotaged by the website later in order to circumvent us.
|
210 |
+
*/
|
211 |
+
var RealWebSocket = WebSocket;
|
212 |
+
var closeWebSocket = Function.prototype.call.bind(RealWebSocket.prototype.close);
|
213 |
+
|
214 |
+
function WrappedWebSocket(url, protocols) {
|
215 |
+
// Throw correct exceptions if the constructor is used improperly.
|
216 |
+
if (!(this instanceof WrappedWebSocket)) {
|
217 |
+
return RealWebSocket();
|
218 |
+
}
|
219 |
+
if (arguments.length < 1) {
|
220 |
+
return new RealWebSocket();
|
221 |
+
}
|
222 |
+
|
223 |
+
var websocket = new RealWebSocket(url, protocols);
|
224 |
+
|
225 |
+
// This is the key point: checking if this WS should be blocked or not
|
226 |
+
// Don't forget that the type of 'websocket.url' is String, but 'url 'parameter might have another type.
|
227 |
+
checkRequest(websocket.url, 'WEBSOCKET', function (blocked) {
|
228 |
+
if (blocked) {
|
229 |
+
closeWebSocket(websocket);
|
230 |
+
}
|
231 |
+
});
|
232 |
+
|
233 |
+
return websocket;
|
234 |
+
}
|
235 |
+
|
236 |
+
// https://github.com/AdguardTeam/AdguardBrowserExtension/issues/488
|
237 |
+
WrappedWebSocket.prototype = RealWebSocket.prototype;
|
238 |
+
window.WebSocket = WrappedWebSocket.bind();
|
239 |
+
|
240 |
+
copyProperties(RealWebSocket, WebSocket, ["CONNECTING", "OPEN", "CLOSING", "CLOSED", "name", "prototype"]);
|
241 |
+
|
242 |
+
RealWebSocket.prototype.constructor = WebSocket;
|
243 |
+
|
244 |
+
};
|
245 |
+
|
246 |
+
/**
|
247 |
+
* The function overrides window.RTCPeerConnection with our wrapper, that will check ice servers URLs with filters through messaging with content-script.
|
248 |
+
*
|
249 |
+
* IMPORTANT NOTE:
|
250 |
+
* This function is first loaded as a content script. The only purpose of it is to call
|
251 |
+
* the "toString" method and use resulting string as a text content for injected script.
|
252 |
+
*/
|
253 |
+
var overrideWebRTC = function () {
|
254 |
+
|
255 |
+
|
256 |
+
if (!(window.RTCPeerConnection instanceof Function) &&
|
257 |
+
!(window.webkitRTCPeerConnection instanceof Function)) {
|
258 |
+
return;
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
* RTCPeerConnection wrapper implementation.
|
263 |
+
* https://github.com/AdguardTeam/AdguardBrowserExtension/issues/588
|
264 |
+
*
|
265 |
+
* Based on:
|
266 |
+
* https://github.com/adblockplus/adblockpluschrome/commit/af0585137be19011eace1cf68bf61eed2e6db974
|
267 |
+
*
|
268 |
+
* Chromium webRequest API doesn't allow the blocking of WebRTC connections
|
269 |
+
* https://bugs.chromium.org/p/chromium/issues/detail?id=707683
|
270 |
+
*/
|
271 |
+
|
272 |
+
var RealRTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection;
|
273 |
+
var closeRTCPeerConnection = Function.prototype.call.bind(RealRTCPeerConnection.prototype.close);
|
274 |
+
|
275 |
+
var RealArray = Array;
|
276 |
+
var RealString = String;
|
277 |
+
var createObject = Object.create;
|
278 |
+
var defineProperty = Object.defineProperty;
|
279 |
+
|
280 |
+
/**
|
281 |
+
* Convert passed url to string
|
282 |
+
* @param url URL
|
283 |
+
* @returns {string}
|
284 |
+
*/
|
285 |
+
function urlToString(url) {
|
286 |
+
if (typeof url !== "undefined") {
|
287 |
+
return RealString(url);
|
288 |
+
}
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* Creates new immutable array from original with some transform function
|
293 |
+
* @param original
|
294 |
+
* @param transform
|
295 |
+
* @returns {*}
|
296 |
+
*/
|
297 |
+
function safeCopyArray(original, transform) {
|
298 |
+
|
299 |
+
if (original === null || typeof original !== "object") {
|
300 |
+
return original;
|
301 |
+
}
|
302 |
+
|
303 |
+
var immutable = RealArray(original.length);
|
304 |
+
for (var i = 0; i < immutable.length; i++) {
|
305 |
+
defineProperty(immutable, i, {
|
306 |
+
configurable: false, enumerable: false, writable: false,
|
307 |
+
value: transform(original[i])
|
308 |
+
});
|
309 |
+
}
|
310 |
+
defineProperty(immutable, "length", {
|
311 |
+
configurable: false, enumerable: false, writable: false,
|
312 |
+
value: immutable.length
|
313 |
+
});
|
314 |
+
return immutable;
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* Protect configuration from mutations
|
319 |
+
* @param configuration RTCPeerConnection configuration object
|
320 |
+
* @returns {*}
|
321 |
+
*/
|
322 |
+
function protectConfiguration(configuration) {
|
323 |
+
|
324 |
+
if (configuration === null || typeof configuration !== "object") {
|
325 |
+
return configuration;
|
326 |
+
}
|
327 |
+
|
328 |
+
var iceServers = safeCopyArray(
|
329 |
+
configuration.iceServers,
|
330 |
+
function (iceServer) {
|
331 |
+
|
332 |
+
var url = iceServer.url;
|
333 |
+
var urls = iceServer.urls;
|
334 |
+
|
335 |
+
// RTCPeerConnection doesn't iterate through pseudo Arrays of urls.
|
336 |
+
if (typeof urls !== "undefined" && !(urls instanceof RealArray)) {
|
337 |
+
urls = [urls];
|
338 |
+
}
|
339 |
+
|
340 |
+
return createObject(iceServer, {
|
341 |
+
url: {
|
342 |
+
configurable: false, enumerable: false, writable: false,
|
343 |
+
value: urlToString(url)
|
344 |
+
},
|
345 |
+
urls: {
|
346 |
+
configurable: false, enumerable: false, writable: false,
|
347 |
+
value: safeCopyArray(urls, urlToString)
|
348 |
+
}
|
349 |
+
});
|
350 |
+
}
|
351 |
+
);
|
352 |
+
|
353 |
+
return createObject(configuration, {
|
354 |
+
iceServers: {
|
355 |
+
configurable: false, enumerable: false, writable: false,
|
356 |
+
value: iceServers
|
357 |
+
}
|
358 |
+
});
|
359 |
+
}
|
360 |
+
|
361 |
+
/**
|
362 |
+
* Check WebRTC connection's URL and close if it's blocked by rule
|
363 |
+
* @param connection Connection
|
364 |
+
* @param url URL to check
|
365 |
+
*/
|
366 |
+
function checkWebRTCRequest(connection, url) {
|
367 |
+
checkRequest(url, 'WEBRTC', function (blocked) {
|
368 |
+
if (blocked) {
|
369 |
+
try {
|
370 |
+
closeRTCPeerConnection(connection);
|
371 |
+
} catch (e) {
|
372 |
+
// Ignore exceptions
|
373 |
+
}
|
374 |
+
}
|
375 |
+
});
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Check each URL of ice server in configuration for blocking.
|
380 |
+
*
|
381 |
+
* @param connection RTCPeerConnection
|
382 |
+
* @param configuration Configuration for RTCPeerConnection
|
383 |
+
* https://developer.mozilla.org/en-US/docs/Web/API/RTCConfiguration
|
384 |
+
*/
|
385 |
+
function checkConfiguration(connection, configuration) {
|
386 |
+
|
387 |
+
if (!configuration || !configuration.iceServers) {
|
388 |
+
return;
|
389 |
+
}
|
390 |
+
|
391 |
+
var iceServers = configuration.iceServers;
|
392 |
+
for (var i = 0; i < iceServers.length; i++) {
|
393 |
+
|
394 |
+
var iceServer = iceServers[i];
|
395 |
+
if (!iceServer) {
|
396 |
+
continue;
|
397 |
+
}
|
398 |
+
|
399 |
+
if (iceServer.url) {
|
400 |
+
checkWebRTCRequest(connection, iceServer.url);
|
401 |
+
}
|
402 |
+
|
403 |
+
if (iceServer.urls) {
|
404 |
+
for (var j = 0; j < iceServer.urls.length; j++) {
|
405 |
+
checkWebRTCRequest(connection, iceServer.urls[j]);
|
406 |
+
}
|
407 |
+
}
|
408 |
+
}
|
409 |
+
}
|
410 |
+
|
411 |
+
/**
|
412 |
+
* Overrides setConfiguration method
|
413 |
+
* https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setConfiguration
|
414 |
+
*/
|
415 |
+
if (RealRTCPeerConnection.prototype.setConfiguration) {
|
416 |
+
|
417 |
+
var realSetConfiguration = Function.prototype.call.bind(RealRTCPeerConnection.prototype.setConfiguration);
|
418 |
+
|
419 |
+
RealRTCPeerConnection.prototype.setConfiguration = function (configuration) {
|
420 |
+
configuration = protectConfiguration(configuration);
|
421 |
+
// Call the real method first, so that validates the configuration
|
422 |
+
realSetConfiguration(this, configuration);
|
423 |
+
checkConfiguration(this, configuration);
|
424 |
+
};
|
425 |
+
}
|
426 |
+
|
427 |
+
function WrappedRTCPeerConnection(configuration, arg) {
|
428 |
+
|
429 |
+
if (!(this instanceof WrappedRTCPeerConnection)) {
|
430 |
+
return RealRTCPeerConnection();
|
431 |
+
}
|
432 |
+
|
433 |
+
configuration = protectConfiguration(configuration);
|
434 |
+
|
435 |
+
/**
|
436 |
+
* The old webkitRTCPeerConnection constructor takes an optional second argument and we must pass it.
|
437 |
+
*/
|
438 |
+
var connection = new RealRTCPeerConnection(configuration, arg);
|
439 |
+
checkConfiguration(connection, configuration);
|
440 |
+
return connection;
|
441 |
+
}
|
442 |
+
|
443 |
+
WrappedRTCPeerConnection.prototype = RealRTCPeerConnection.prototype;
|
444 |
+
|
445 |
+
var boundWrappedRTCPeerConnection = WrappedRTCPeerConnection.bind();
|
446 |
+
copyProperties(RealRTCPeerConnection, boundWrappedRTCPeerConnection, ["caller", "generateCertificate", "name", "prototype"]);
|
447 |
+
RealRTCPeerConnection.prototype.constructor = boundWrappedRTCPeerConnection;
|
448 |
+
|
449 |
+
if ("RTCPeerConnection" in window) {
|
450 |
+
window.RTCPeerConnection = boundWrappedRTCPeerConnection;
|
451 |
+
}
|
452 |
+
if ("webkitRTCPeerConnection" in window) {
|
453 |
+
window.webkitRTCPeerConnection = boundWrappedRTCPeerConnection;
|
454 |
+
}
|
455 |
+
};
|
456 |
+
|
457 |
+
if (shouldOverrideWebSocket) {
|
458 |
+
overrideWebSocket();
|
459 |
+
}
|
460 |
+
|
461 |
+
if (shouldOverrideWebRTC) {
|
462 |
+
overrideWebRTC();
|
463 |
+
}
|
464 |
+
})('wrapper-script-3215676477346979', false, true);
|
465 |
+
} catch (ex) { console.error('Error executing AG js: ' + ex); }
|
466 |
+
(function () {
|
467 |
+
var current = document.currentScript;
|
468 |
+
var parent = current && current.parentNode;
|
469 |
+
if (parent) {
|
470 |
+
parent.removeChild(current);
|
471 |
+
}
|
472 |
+
})();</script><head>
|
473 |
+
<meta http-equiv="Content-type" content="text/html; charset=UTF-8">
|
474 |
+
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; connect-src 'self'">
|
475 |
+
<title>Page not found · GitHub Pages</title>
|
476 |
+
<style type="text/css" media="screen">
|
477 |
+
body {
|
478 |
+
background-color: #f1f1f1;
|
479 |
+
margin: 0;
|
480 |
+
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
481 |
+
}
|
482 |
+
|
483 |
+
.container { margin: 50px auto 40px auto; width: 600px; text-align: center; }
|
484 |
+
|
485 |
+
a { color: #4183c4; text-decoration: none; }
|
486 |
+
a:hover { text-decoration: underline; }
|
487 |
+
|
488 |
+
h1 { width: 800px; position:relative; left: -100px; letter-spacing: -1px; line-height: 60px; font-size: 60px; font-weight: 100; margin: 0px 0 50px 0; text-shadow: 0 1px 0 #fff; }
|
489 |
+
p { color: rgba(0, 0, 0, 0.5); margin: 20px 0; line-height: 1.6; }
|
490 |
+
|
491 |
+
ul { list-style: none; margin: 25px 0; padding: 0; }
|
492 |
+
li { display: table-cell; font-weight: bold; width: 1%; }
|
493 |
+
|
494 |
+
.logo { display: inline-block; margin-top: 35px; }
|
495 |
+
.logo-img-2x { display: none; }
|
496 |
+
@media
|
497 |
+
only screen and (-webkit-min-device-pixel-ratio: 2),
|
498 |
+
only screen and ( min--moz-device-pixel-ratio: 2),
|
499 |
+
only screen and ( -o-min-device-pixel-ratio: 2/1),
|
500 |
+
only screen and ( min-device-pixel-ratio: 2),
|
501 |
+
only screen and ( min-resolution: 192dpi),
|
502 |
+
only screen and ( min-resolution: 2dppx) {
|
503 |
+
.logo-img-1x { display: none; }
|
504 |
+
.logo-img-2x { display: inline-block; }
|
505 |
+
}
|
506 |
+
|
507 |
+
#suggestions {
|
508 |
+
margin-top: 35px;
|
509 |
+
color: #ccc;
|
510 |
+
}
|
511 |
+
#suggestions a {
|
512 |
+
color: #666666;
|
513 |
+
font-weight: 200;
|
514 |
+
font-size: 14px;
|
515 |
+
margin: 0 10px;
|
516 |
+
}
|
517 |
+
|
518 |
+
</style>
|
519 |
+
</head>
|
520 |
+
<body>
|
521 |
+
|
522 |
+
<div class="container">
|
523 |
+
|
524 |
+
<h1>404</h1>
|
525 |
+
<p><strong>File not found</strong></p>
|
526 |
+
|
527 |
+
<p>
|
528 |
+
The site configured at this address does not
|
529 |
+
contain the requested file.
|
530 |
+
</p>
|
531 |
+
|
532 |
+
<p>
|
533 |
+
If this is your site, make sure that the filename case matches the URL
|
534 |
+
as well as any file permissions.<br>
|
535 |
+
For root URLs (like <code>http://example.com/</code>) you must provide an
|
536 |
+
<code>index.html</code> file.
|
537 |
+
</p>
|
538 |
+
|
539 |
+
<p>
|
540 |
+
<a href="https://help.github.com/pages/">Read the full documentation</a>
|
541 |
+
for more information about using <strong>GitHub Pages</strong>.
|
542 |
+
</p>
|
543 |
+
|
544 |
+
<div id="suggestions">
|
545 |
+
<a href="https://githubstatus.com/">GitHub Status</a> —
|
546 |
+
<a href="https://twitter.com/githubstatus">@githubstatus</a>
|
547 |
+
</div>
|
548 |
+
|
549 |
+
<a href="https://llava-vl.github.io/" class="logo logo-img-1x">
|
550 |
+
<img width="32" height="32" title="" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFMTZCRDY3REIzRjAxMUUyQUQzREIxQzRENUFFNUM5NiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFMTZCRDY3RUIzRjAxMUUyQUQzREIxQzRENUFFNUM5NiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkUxNkJENjdCQjNGMDExRTJBRDNEQjFDNEQ1QUU1Qzk2IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkUxNkJENjdDQjNGMDExRTJBRDNEQjFDNEQ1QUU1Qzk2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+SM9MCAAAA+5JREFUeNrEV11Ik1EY3s4+ddOp29Q5b0opCgKFsoKoi5Kg6CIhuwi6zLJLoYLopq4qsKKgi4i6CYIoU/q5iDAKs6syoS76IRWtyJ+p7cdt7sf1PGOD+e0c3dygAx/67ZzzPM95/877GYdHRg3ZjMXFxepQKNS6sLCwJxqNNuFpiMfjVs4ZjUa/pmmjeD6VlJS8NpvNT4QQ7mxwjSsJiEQim/1+/9lgMHgIr5ohuxG1WCw9Vqv1clFR0dCqBODElV6v90ogEDjGdYbVjXhpaendioqK07CIR7ZAqE49PT09BPL2PMgTByQGsYiZlQD4uMXtdr+JxWINhgINYhGT2MsKgMrm2dnZXgRXhaHAg5jEJodUAHxux4LudHJE9RdEdA+i3Juz7bGHe4mhE9FNrgwBCLirMFV9Okh5eflFh8PR5nK5nDabrR2BNJlKO0T35+Li4n4+/J+/JQCxhmu5h3uJoXNHPbmWZAHMshWB8l5/ipqammaAf0zPDDx1ONV3vurdidqwAQL+pEc8sLcAe1CCvQ3YHxIW8Pl85xSWNC1hADDIv0rIE/o4J0k3kww4xSlwIhcq3EFFOm7KN/hUGOQkt0CFa5WpNJlMvxBEz/IVQAxg/ZRZl9wiHA63yDYieM7DnLP5CiAGsC7I5sgtYKJGWe2A8seFqgFJrJjEPY1Cn3pJ8/9W1e5VWsFDTEmFrBcoDhZJEQkXuhICMyKpjhahqN21hRYATKfUOlDmkygrR4o4C0VOLGJKrOITKB4jijzdXygBKixyC5TDQdnk/Pz8qRw6oOWGlsTKGOQW6OH6FBWsyePxdOXLTgxiyebILZCjz+GLgMIKnXNzc49YMlcRdHXcSwxFVgTInQhC9G33UhNoJLuqq6t345p9y3eUy8OTk5PjAHuI9uo4b07FBaOhsu0A4Unc+T1TU1Nj3KsSSE5yJ65jqF2DDd8QqWYmAZrIM2VlZTdnZmb6AbpdV9V6ec9znf5Q7HjYumdRE0JOp3MjitO4SFa+cZz8Umqe3TCbSLvdfkR/kWDdNQl5InuTcysOcpFT35ZrbBxx4p3JAHlZVVW1D/634VRt+FvLBgK/v5LV9WS+10xMTEwtRw7XvqOL+e2Q8V3AYIOIAXQ26/heWVnZCVfcyKHg2CBgTpmPmjYM8l24GyaUHyaIh7XwfR9ErE8qHoDfn2LTNAVC0HX6MFcBIP8Bi+6F6cdW/DICkANRfx99fEYFQ7Nph5i/uQiA214gno7K+guhaiKg9gC62+M8eR7XsBsYJ4ilam60Fb7r7uAj8wFyuwM1oIOWgfmDy6RXEEQzJMPe23DXrVS7rtyD3Df8z/FPgAEAzWU5Ku59ZAUAAAAASUVORK5CYII=">
|
551 |
+
</a>
|
552 |
+
|
553 |
+
<a href="https://llava-vl.github.io/" class="logo logo-img-2x">
|
554 |
+
<img width="32" height="32" title="" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpEQUM1QkUxRUI0MUMxMUUyQUQzREIxQzRENUFFNUM5NiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpEQUM1QkUxRkI0MUMxMUUyQUQzREIxQzRENUFFNUM5NiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkUxNkJENjdGQjNGMDExRTJBRDNEQjFDNEQ1QUU1Qzk2IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkUxNkJENjgwQjNGMDExRTJBRDNEQjFDNEQ1QUU1Qzk2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+hfPRaQAAB6lJREFUeNrsW2mME2UYbodtt+2222u35QheoCCYGBQligIJgkZJNPzgigoaTEj8AdFEMfADfyABkgWiiWcieK4S+QOiHAYUj2hMNKgYlEujpNttu9vttbvdw+chU1K6M535pt3ubHCSyezR+b73eb73+t7vrfXsufOW4bz6+vom9/b23ovnNNw34b5xYGAgODg46Mbt4mesVmsWd1qSpHhdXd2fuP/Afcput5/A88xwymcdBgLqenp6FuRyuWV4zu/v759QyWBjxoz5t76+/gun09mK5xFyakoCAPSaTCazNpvNPoYVbh6O1YKGRF0u13sNDQ27QMzfpiAAKj0lnU6/gBVfAZW2WWpwwVzy0IgP3G73FpjI6REhAGA9qVRqA1b9mVoBVyIC2tDi8Xg24+dUzQiAbS/s7Ox8G2o/3mKCC+Zw0efzPQEfcVjYrARX3dbV1bUtHo8fMgt42f+Mp0yUTVQbdWsAHVsikdiHkHaPxcQXQufXgUBgMRxme9U0AAxfH4vFvjM7eF6UkbJS5qoQwEQGA57Ac5JllFyUVZZ5ckUEgMVxsK2jlSYzI+QXJsiyjzNEAJyJAzb/KQa41jJKL8pODMQiTEAymXw5n8/P0IjD3bh7Rgog59aanxiIRTVvV/oj0tnHca/WMrVwODwB3raTGxzkBg/gnZVapFV62Wy2n5AO70HM/5wbJ0QnXyQSaVPDIuNZzY0V3ntHMwxiwHA0Gj2Np7ecIBDgaDAYXKCQJM1DhrgJ3nhulcPbl8j4NmHe46X/g60fwbz3aewjkqFQaAqebWU1AOqyQwt8Id6qEHMc97zu7u7FGGsn7HAiVuosVw7P35C1nccdgSCxop1dHeZswmfHMnxBo6ZTk+jN8dl/vF7vWofDsa+MLN9oEUBMxOb3+1eoEsBVw6Zmua49r8YmhAKDiEPcMwBsxMiqQ+ixzPFxZyqRpXARG/YOr1ObFJ0gUskXBbamcR1OKmMUvDxHRAu8/LmY3jFLMUpFqz9HxG65smYJdyKyECOxDiEAe/p1gjF2oonivZAsxVgl2daa4EQWCW6J55qFAFFZiJWYLxNQy2qOSUzGRsyXCUDIeliwAHEO4WSlWQBRFoZakXcKmCXmyXAKs0Ve9vl8q42WoIYpJU4hV3hKcNs8m9gl7p/xQ73eF5kB4j5mNrWmTJRNwAzqiV1CxjVTZCIkEq+Z1bZFZSN2CenmVAFVy4Plz8xKAGWjjAKFk6lCBMDR/MJjLLMSQNm43xAiQKTaA+9/wewhDjL+JVI1kkTSSOTcKbMTwPqESAot6dn6Fr1gHwVJju6IRuyiByPuUUBAg5DGkAgBmxlvdgIEK9gDkohdY/BJo4CAG0R8miRSsGABkgVQs4KXu098IgUXSSRsFAoKZiVAVDY2WUiiPTjYRi41KwGisrGsLtlsth8Fiwnz2fBkQvWfRtlE3iF2yW63/yCacXZ1dW02GwGyTFaRd4idJnCKHRaCxYRHoG5LTKT6SyiToP1fJHbmAYPYRR0UnZQtMnA6s0zg+GZBlt0Gdo7EPHgpE3Q6nZ8YyLhc8Xj8MJh/aKTAY+5FPAKHLE7RdwuYJZmNwzyCMkBCYyKROJBMJl9B/PXXCjjmCmDOVzH3fiPpObEWGqoKe4EBl8v1hlqsdLvd23mkxHM9pc9kMpmno9HoeTii7ewbHEZPPx1ztLS1tV3AnGuMjiNjvbQFuHw6zDo5By7dTPAQNBgMLrRarTkSls1mnwT7uwp9virx9QzbW/HuV/j5d/b+6jniKlllP8lkeONJDk+dq9GsQTnC4fB1heO0K47Hwe7WdDr9nAKgXwOBwHI+C45Htj1d6sd429TUNEcmUdc+PRaLHcvn87dXW4ugzdsaGxufL94NFv9zi1J7GVbhlvb2dnaJ3SVrxfc+n2+NTsZ7/H7/Mr3g5XdSIHyJSH1PZ+7fToyl2+ErqilgZ4NaLYB9goVGaHjR93Hv1ZrU4XDsFT20kH3PObzbWk0CgG1jacVIUnAQb9F+VexyLMzkpcLv0IJV7AHQIOCAUYHx7v5qgScmYHtTqSAyZLEJTK22Bie4iq3xsqpm4SAf9Hq9a2DnJ4uLK3SEULcdRvp3i3zHySqpficxEdsQc1NrlYXXvR+O7qASSezXB+h1SuUomgg9LL8BUoV4749EIolKh+EiqWmqVEZlDgHks2pxHw7xTqUQw9J5NcAXOK10AGIoZ6Zli6JY6Z1Q461KoZ4NiKLHarW+KDsxlDUPHZ5zPQZqUVDPJsTqb5n9malbpAh8C2XXDLl62+WZIDFRUlNVOiwencnNU3aQEkL+cDMSoLvZo2fQB7AJssNAuFuvorlDVVkkg2I87+jo2K2QAVphDrfyViK5VqtO34OkaxXCp+7drdDBCAdubm6eidX+2WwqT5komwh4YQLk+H4aE93h8Xg2gvHekQZOGSgLZTLyDTLJ4Lx9/KZWKBSainT4Iy3FqQBfnUZR42PKQFksBr9QKVXCPusD3OiA/RkQ5kP8qV/Jl1WywAp/6+dcmPM2zL1UrUahe4JqfnWWKXIul3uUbfP8njAFLW1OFr3gdFtZ72cNH+PtQT7/brW+NXqJAHh0y9V8/U/A1U7AfwIMAD7mS3pCbuWJAAAAAElFTkSuQmCC">
|
555 |
+
</a>
|
556 |
+
</div>
|
557 |
+
|
558 |
+
|
559 |
+
</body></html>
|
static/Blocks-005a10ea.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
.wrap.svelte-1i3r921.svelte-1i3r921{padding:var(--size-6)}.attention.svelte-1i3r921.svelte-1i3r921{font-weight:var(--weight-bold);font-size:var(--text-lg)}.attention.svelte-1i3r921 code.svelte-1i3r921{border:none;background:none;color:var(--color-accent);font-weight:var(--weight-bold)}button.svelte-1i3r921.svelte-1i3r921{position:absolute;top:var(--size-5);right:var(--size-6);width:var(--size-4);color:var(--body-text-color)}button.svelte-1i3r921.svelte-1i3r921:hover{color:var(--color-accent)}@media (min-width: 768px){button.svelte-1i3r921.svelte-1i3r921{top:var(--size-6)}}h2.svelte-9i27qi.svelte-9i27qi{display:flex;color:var(--body-text-color);font-weight:var(--weight-semibold)}h2.svelte-9i27qi img.svelte-9i27qi{margin-right:var(--size-2);width:var(--size-4)}span.svelte-9i27qi.svelte-9i27qi{color:var(--color-accent)}button.svelte-9i27qi.svelte-9i27qi{position:absolute;top:var(--size-5);right:var(--size-6);width:var(--size-4);color:var(--body-text-color)}button.svelte-9i27qi.svelte-9i27qi:hover{color:var(--color-accent)}@media (min-width: 768px){button.svelte-9i27qi.svelte-9i27qi{top:var(--size-6)}h2.svelte-9i27qi img.svelte-9i27qi{width:var(--size-5)}}.counts.svelte-9i27qi.svelte-9i27qi{margin-top:auto;margin-right:var(--size-8);margin-bottom:auto;margin-left:auto;color:var(--body-text-color);font-weight:var(--weight-light)}.load-wrap.svelte-1c7hj3i{display:flex;justify-content:center;align-items:center}h4.svelte-1c7hj3i{display:flex;align-items:center;margin-top:var(--size-6);margin-bottom:var(--size-3);color:var(--body-text-color);font-weight:var(--weight-bold)}.toggle-icon.svelte-1c7hj3i{display:flex;align-items:center;margin-right:var(--size-2);border-radius:var(--radius-full);background:var(--color-grey-300);width:12px;height:4px}.toggle-dot.svelte-1c7hj3i{margin-left:auto;border-radius:var(--radius-full);background:var(--color-grey-700);width:6px;height:6px}.response-wrap.svelte-1c7hj3i{font-family:var(--font-mono)}.desc.svelte-1c7hj3i{color:var(--body-text-color-subdued)}.hide.svelte-1c7hj3i{display:none}.second-level.svelte-1c7hj3i{margin-left:var(--size-4)}code.svelte-1pu3gsl pre.svelte-1pu3gsl{overflow-x:auto;color:var(--body-text-color);font-family:var(--font-mono);tab-size:2}code.svelte-1pu3gsl.svelte-1pu3gsl{position:relative}.copy.svelte-1pu3gsl.svelte-1pu3gsl{position:absolute;top:0;right:0;margin-top:-5px;margin-right:-5px}h3.svelte-41kcm6{color:var(--body-text-color);font-weight:var(--section-header-text-weight);font-size:var(--text-lg)}.post.svelte-41kcm6{margin-right:var(--size-2);border:1px solid var(--border-color-accent);border-radius:var(--radius-sm);background:var(--color-accent-soft);padding-right:var(--size-1);padding-bottom:var(--size-1);padding-left:var(--size-1);color:var(--color-accent);font-weight:var(--weight-semibold)}code.svelte-1bqxtsy pre.svelte-1bqxtsy{overflow-x:auto;color:var(--body-text-color);font-family:var(--font-mono);tab-size:2}.token.string.svelte-1bqxtsy.svelte-1bqxtsy{display:contents;color:var(--color-accent-base)}code.svelte-1bqxtsy.svelte-1bqxtsy{position:relative}.copy.svelte-1bqxtsy.svelte-1bqxtsy{position:absolute;top:0;right:0;margin-top:-5px;margin-right:-5px}.container.svelte-1bqxtsy.svelte-1bqxtsy{display:flex;flex-direction:column;gap:var(--spacing-xxl);margin-top:var(--size-3);margin-bottom:var(--size-3)}.error.svelte-1bqxtsy.svelte-1bqxtsy{color:var(--error-text-color)}.desc.svelte-1bqxtsy.svelte-1bqxtsy{color:var(--body-text-color-subdued)}.example-inputs.svelte-1bqxtsy.svelte-1bqxtsy{border:1px solid var(--border-color-accent);border-radius:var(--radius-sm);background:var(--color-accent-soft);padding-right:var(--size-1);padding-left:var(--size-1);color:var(--color-accent)}.space.svelte-1j8n062{display:flex;flex-basis:1;margin-top:var(--size-4)}.banner-wrap.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{position:relative;border-bottom:1px solid var(--border-color-primary);padding:var(--size-4) var(--size-6);font-size:var(--text-md)}@media (min-width: 768px){.banner-wrap.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{font-size:var(--text-xl)}}.docs-wrap.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{display:flex;flex-direction:column;gap:var(--spacing-xxl)}.endpoint.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{border-radius:var(--radius-md);background:var(--background-fill-primary);padding:var(--size-6);padding-top:var(--size-1);font-size:var(--text-md)}.client-doc.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{padding-top:var(--size-6);padding-right:var(--size-6);padding-left:var(--size-6);font-size:var(--text-xl)}.library.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{border:1px solid var(--border-color-accent);border-radius:var(--radius-sm);background:var(--color-accent-soft);padding-right:var(--size-1);padding-bottom:var(--size-1);padding-left:var(--size-1);color:var(--color-accent)}.snippets.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{display:flex;align-items:center;margin-bottom:var(--size-4)}.snippets.svelte-rzp0ym>.svelte-rzp0ym+.svelte-rzp0ym{margin-left:var(--size-2)}.snippet.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{display:flex;align-items:center;border:1px solid var(--border-color-primary);border-radius:var(--radius-md);padding:var(--size-1) var(--size-1-5);color:var(--body-text-color-subdued);color:var(--body-text-color);line-height:1;user-select:none;text-transform:capitalize}.current-lang.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{border:1px solid var(--body-text-color-subdued);color:var(--body-text-color)}.inactive-lang.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{cursor:pointer;color:var(--body-text-color-subdued)}.inactive-lang.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym:hover,.inactive-lang.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym:focus{box-shadow:var(--shadow-drop);color:var(--body-text-color)}.snippet.svelte-rzp0ym img.svelte-rzp0ym.svelte-rzp0ym{margin-right:var(--size-1-5);width:var(--size-3)}.header.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{margin-top:var(--size-3);margin-bottom:var(--size-3);font-size:var(--text-xl)}.endpoint-container.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{margin-top:var(--size-3);margin-bottom:var(--size-3);border:1px solid var(--border-color-primary);border-radius:var(--radius-xl);padding:var(--size-3);padding-top:0}.wrap.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;flex-grow:1;flex-direction:column;width:var(--size-full);font-weight:var(--body-text-weight);font-size:var(--body-text-size)}footer.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;justify-content:center;margin-top:var(--size-4);color:var(--body-text-color-subdued)}footer.svelte-1lyswbr>.svelte-1lyswbr+.svelte-1lyswbr{margin-left:var(--size-2)}.show-api.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;align-items:center}.show-api.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr:hover{color:var(--body-text-color)}.show-api.svelte-1lyswbr img.svelte-1lyswbr.svelte-1lyswbr{margin-right:var(--size-1);margin-left:var(--size-2);width:var(--size-3)}.built-with.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;align-items:center}.built-with.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr:hover{color:var(--body-text-color)}.built-with.svelte-1lyswbr img.svelte-1lyswbr.svelte-1lyswbr{margin-right:var(--size-1);margin-left:var(--size-2);width:var(--size-3)}.api-docs.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;position:fixed;top:0;right:0;z-index:var(--layer-5);background:rgba(0,0,0,.5);width:var(--size-screen);height:var(--size-screen-h)}.backdrop.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{flex:1 1 0%;backdrop-filter:blur(4px)}.api-docs-wrap.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{box-shadow:var(--shadow-drop-lg);background:var(--background-fill-primary);overflow-x:hidden;overflow-y:auto}@media (min-width: 768px){.api-docs-wrap.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{border-top-left-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg);width:950px}}@media (min-width: 1536px){.api-docs-wrap.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{width:1150px}}
|
static/Button-3657eefc.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
.block.svelte-mppz8v{position:relative;margin:0;box-shadow:var(--block-shadow);border-width:var(--block-border-width);border-color:var(--block-border-color);border-radius:var(--block-radius);background:var(--block-background-fill);width:100%;line-height:var(--line-sm)}.block.border_focus.svelte-mppz8v{border-color:var(--color-accent)}.padded.svelte-mppz8v{padding:var(--block-padding)}.hidden.svelte-mppz8v{display:none}div.svelte-e8n7p6{margin-bottom:var(--spacing-lg);color:var(--block-info-text-color);font-weight:var(--block-info-text-weight);font-size:var(--block-info-text-size);line-height:var(--line-sm)}span.has-info.svelte-1gfkn6j{margin-bottom:var(--spacing-xs)}span.svelte-1gfkn6j:not(.has-info){margin-bottom:var(--spacing-lg)}span.svelte-1gfkn6j{display:inline-block;position:relative;z-index:var(--layer-4);border:solid var(--block-title-border-width) var(--block-title-border-color);border-radius:var(--block-title-radius);background:var(--block-title-background-fill);padding:var(--block-title-padding);color:var(--block-title-text-color);font-weight:var(--block-title-text-weight);font-size:var(--block-title-text-size);line-height:var(--line-sm)}.hide.svelte-1gfkn6j{margin:0;height:0}div.svelte-1frtwj3{display:inline-flex;align-items:center;z-index:var(--layer-2);box-shadow:var(--block-shadow);border:var(--block-label-border-width) solid var(--border-color-primary);border-top:none;border-left:none;border-radius:var(--block-label-radius);background:var(--block-label-background-fill);padding:var(--block-label-padding);pointer-events:none;color:var(--block-label-text-color);font-weight:var(--block-label-text-weight);font-size:var(--block-label-text-size);line-height:var(--line-sm)}div.float.svelte-1frtwj3{position:absolute;top:var(--block-label-margin);left:var(--block-label-margin)}div.svelte-1frtwj3:not(.float){position:static;margin-top:var(--block-label-margin);margin-left:var(--block-label-margin)}.hide.svelte-1frtwj3{height:0}span.svelte-1frtwj3{opacity:.8;margin-right:var(--size-2);width:calc(var(--block-label-text-size) - 1px);height:calc(var(--block-label-text-size) - 1px)}button.svelte-1p4r00v{display:flex;justify-content:center;align-items:center;z-index:var(--layer-1);box-shadow:var(--shadow-drop);border:1px solid var(--button-secondary-border-color);border-radius:var(--radius-sm);background:var(--background-fill-primary);width:var(--size-5);height:var(--size-5);color:var(--block-label-text-color)}button.svelte-1p4r00v:hover{cursor:pointer;border:2px solid var(--button-secondary-border-color-hover);color:var(--block-label-text-color)}div.svelte-1p4r00v{width:60%;height:60%}.empty.svelte-1u5vjgs{display:flex;justify-content:center;align-items:center;height:var(--size-full)}.icon.svelte-1u5vjgs{opacity:.5;height:var(--size-5);color:var(--body-text-color)}.small.svelte-1u5vjgs{height:calc(var(--size-32) - 20px)}.large.svelte-1u5vjgs{height:calc(var(--size-64) - 20px)}.unpadded_box.small.svelte-1u5vjgs{min-height:var(--size-32)}.unpadded_box.large.svelte-1u5vjgs{min-height:var(--size-64)}button.svelte-1ipelgc{display:inline-flex;justify-content:center;align-items:center;transition:var(--button-transition);box-shadow:var(--button-shadow);padding:var(--size-0-5) var(--size-2);text-align:center}button.svelte-1ipelgc:hover,button[disabled].svelte-1ipelgc{box-shadow:var(--button-shadow-hover)}button.svelte-1ipelgc:active{box-shadow:var(--button-shadow-active)}button[disabled].svelte-1ipelgc{opacity:.5;filter:grayscale(30%);cursor:not-allowed}.hide.svelte-1ipelgc{display:none}.primary.svelte-1ipelgc{border:var(--button-border-width) solid var(--button-primary-border-color);background:var(--button-primary-background-fill);color:var(--button-primary-text-color)}.primary.svelte-1ipelgc:hover,.primary[disabled].svelte-1ipelgc{border-color:var(--button-primary-border-color-hover);background:var(--button-primary-background-fill-hover);color:var(--button-primary-text-color-hover)}.secondary.svelte-1ipelgc{border:var(--button-border-width) solid var(--button-secondary-border-color);background:var(--button-secondary-background-fill);color:var(--button-secondary-text-color)}.secondary.svelte-1ipelgc:hover,.secondary[disabled].svelte-1ipelgc{border-color:var(--button-secondary-border-color-hover);background:var(--button-secondary-background-fill-hover);color:var(--button-secondary-text-color-hover)}.stop.svelte-1ipelgc{border:var(--button-border-width) solid var(--button-cancel-border-color);background:var(--button-cancel-background-fill);color:var(--button-cancel-text-color)}.stop.svelte-1ipelgc:hover,.stop[disabled].svelte-1ipelgc{border-color:var(--button-cancel-border-color-hover);background:var(--button-cancel-background-fill-hover);color:var(--button-cancel-text-color-hover)}.sm.svelte-1ipelgc{border-radius:var(--button-small-radius);padding:var(--button-small-padding);font-weight:var(--button-small-text-weight);font-size:var(--button-small-text-size)}.lg.svelte-1ipelgc{border-radius:var(--button-large-radius);padding:var(--button-large-padding);font-weight:var(--button-large-text-weight);font-size:var(--button-large-text-size)}
|
static/ColorPicker-41813019.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
label.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70{display:flex;align-items:center;cursor:pointer;color:var(--body-text-color);font-weight:var(--checkbox-label-text-weight);font-size:var(--checkbox-label-text-size);line-height:var(--line-md)}label.svelte-1ojmf70>.svelte-1ojmf70+.svelte-1ojmf70{margin-left:var(--size-2)}input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70{--ring-color:transparent;position:relative;box-shadow:var(--input-shadow);border:1px solid var(--checkbox-border-color);border-radius:var(--checkbox-border-radius);background-color:var(--checkbox-background-color);line-height:var(--line-sm)}input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:checked,input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:checked:hover,input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:checked:focus{border-color:var(--checkbox-border-color-selected);background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected)}input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:hover{border-color:var(--checkbox-border-color-hover);background-color:var(--checkbox-background-color-hover)}input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:focus{border-color:var(--checkbox-border-color-focus);background-color:var(--checkbox-background-color-focus)}input[disabled].svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70,.disabled.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70{cursor:not-allowed}.wrap.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{display:flex;flex-wrap:wrap;gap:var(--checkbox-label-gap)}label.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{display:flex;align-items:center;transition:var(--button-transition);cursor:pointer;box-shadow:var(--checkbox-label-shadow);border:var(--checkbox-label-border-width) solid var(--checkbox-label-border-color);border-radius:var(--button-small-radius);background:var(--checkbox-label-background-fill);padding:var(--checkbox-label-padding);color:var(--checkbox-label-text-color);font-weight:var(--checkbox-label-text-weight);font-size:var(--checkbox-label-text-size);line-height:var(--line-md)}label.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:hover{background:var(--checkbox-label-background-fill-hover)}label.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:focus{background:var(--checkbox-label-background-fill-focus)}label.selected.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{background:var(--checkbox-label-background-fill-selected);color:var(--checkbox-label-text-color-selected)}label.svelte-1qxcj04>.svelte-1qxcj04+.svelte-1qxcj04{margin-left:var(--size-2)}input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{--ring-color:transparent;position:relative;box-shadow:var(--checkbox-shadow);border:var(--checkbox-border-width) solid var(--checkbox-border-color);border-radius:var(--checkbox-border-radius);background-color:var(--checkbox-background-color);line-height:var(--line-sm)}input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:checked,input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:checked:hover,input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:checked:focus{border-color:var(--checkbox-border-color-selected);background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected)}input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:hover{border-color:var(--checkbox-border-color-hover);background-color:var(--checkbox-background-color-hover)}input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:focus{border-color:var(--checkbox-border-color-focus);background-color:var(--checkbox-background-color-focus)}input[disabled].svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04,.disabled.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{cursor:not-allowed}.options.svelte-1oas11n{--window-padding:var(--size-8);position:absolute;z-index:var(--layer-5);margin-left:0;box-shadow:var(--shadow-drop-lg);border-radius:var(--container-radius);background:var(--background-fill-primary);width:var(--size-full);overflow:auto;color:var(--body-text-color);list-style:none}.item.svelte-1oas11n{display:flex;cursor:pointer;padding:var(--size-2)}.item.svelte-1oas11n:hover,.active.svelte-1oas11n{background:var(--background-fill-secondary)}.inner-item.svelte-1oas11n{padding-right:var(--size-1)}.hide.svelte-1oas11n{visibility:hidden}.wrap.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{position:relative;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--border-color-primary);border-radius:var(--input-radius);background:var(--input-background-fill)}.wrap.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu:focus-within{box-shadow:var(--input-shadow-focus);border-color:var(--input-border-color-focus)}.wrap-inner.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{display:flex;position:relative;flex-wrap:wrap;align-items:center;gap:var(--checkbox-label-gap);padding:var(--checkbox-label-gap)}.token.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{display:flex;align-items:center;transition:var(--button-transition);cursor:pointer;box-shadow:var(--checkbox-label-shadow);border:var(--checkbox-label-border-width) solid var(--checkbox-label-border-color);border-radius:var(--button-small-radius);background:var(--checkbox-label-background-fill);padding:var(--checkbox-label-padding);color:var(--checkbox-label-text-color);font-weight:var(--checkbox-label-text-weight);font-size:var(--checkbox-label-text-size);line-height:var(--line-md)}.token.svelte-1ythexu>.svelte-1ythexu+.svelte-1ythexu{margin-left:var(--size-2)}.token-remove.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{fill:var(--body-text-color);display:flex;justify-content:center;align-items:center;cursor:pointer;border:var(--checkbox-border-width) solid var(--border-color-primary);border-radius:var(--radius-full);background:var(--background-fill-primary);padding:var(--size-0-5);width:18px;height:18px}.single-select.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{margin:var(--spacing-sm);color:var(--body-text-color)}.secondary-wrap.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{display:flex;flex:1 1 0%;align-items:center;border:none;min-width:min-content}input.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{margin:var(--spacing-sm);outline:none;border:none;background:inherit;width:var(--size-full);color:var(--body-text-color);font-size:var(--input-text-size)}input.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu:disabled{cursor:not-allowed}.remove-all.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{margin-left:var(--size-1);width:20px;height:20px}.hide.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{display:none}input[type=number].svelte-1nnxs9b{display:block;position:relative;outline:none!important;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--input-border-color);border-radius:var(--input-radius);background:var(--input-background-fill);padding:var(--input-padding);width:100%;color:var(--body-text-color);font-size:var(--input-text-size);line-height:var(--line-sm)}input.svelte-1nnxs9b:focus{box-shadow:var(--input-shadow-focus);border-color:var(--input-border-color-focus)}input.svelte-1nnxs9b::placeholder{color:var(--input-placeholder-color)}.wrap.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{display:flex;flex-wrap:wrap;gap:var(--checkbox-label-gap)}label.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{display:flex;align-items:center;transition:var(--button-transition);cursor:pointer;box-shadow:var(--checkbox-label-shadow);border:var(--checkbox-label-border-width) solid var(--checkbox-label-border-color);border-radius:var(--button-small-radius);background:var(--checkbox-label-background-fill);padding:var(--checkbox-label-padding);color:var(--checkbox-label-text-color);font-weight:var(--checkbox-label-text-weight);font-size:var(--checkbox-label-text-size);line-height:var(--line-md)}label.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:hover{background:var(--checkbox-label-background-fill-hover)}label.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:focus{background:var(--checkbox-label-background-fill-focus)}label.selected.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{background:var(--checkbox-label-background-fill-selected);color:var(--checkbox-label-text-color-selected)}label.svelte-1p9xokt>.svelte-1p9xokt+.svelte-1p9xokt{margin-left:var(--size-2)}input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{--ring-color:transparent;position:relative;box-shadow:var(--checkbox-shadow);border:var(--checkbox-border-width) solid var(--checkbox-border-color);border-radius:var(--radius-full);background-color:var(--checkbox-background-color);line-height:var(--line-sm)}input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:checked,input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:checked:hover,input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:checked:focus{border-color:var(--checkbox-border-color-selected);background-image:var(--radio-circle);background-color:var(--checkbox-background-color-selected)}input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:hover{border-color:var(--checkbox-border-color-hover);background-color:var(--checkbox-background-color-hover)}input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:focus{border-color:var(--checkbox-border-color-focus);background-color:var(--checkbox-background-color-focus)}input[disabled].svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt,.disabled.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{cursor:not-allowed}label.svelte-4xt1ch{display:block;width:100%}input[type=text].svelte-4xt1ch,input[type=password].svelte-4xt1ch,input[type=email].svelte-4xt1ch,textarea.svelte-4xt1ch{display:block;position:relative;outline:none!important;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--input-border-color);border-radius:var(--input-radius);background:var(--input-background-fill);padding:var(--input-padding);width:100%;color:var(--body-text-color);font-weight:var(--input-text-weight);font-size:var(--input-text-size);line-height:var(--line-sm)}input.svelte-4xt1ch:focus,textarea.svelte-4xt1ch:focus{box-shadow:var(--input-shadow-focus);border-color:var(--input-border-color-focus)}input.svelte-4xt1ch::placeholder,textarea.svelte-4xt1ch::placeholder{color:var(--input-placeholder-color)}button.svelte-4xt1ch{display:flex;position:absolute;top:var(--block-label-margin);right:var(--block-label-margin);align-items:center;box-shadow:var(--shadow-drop);border:1px solid var(--color-border-primary);border-top:none;border-right:none;border-radius:var(--block-label-right-radius);background:var(--block-label-background-fill);padding:5px;width:22px;height:22px;overflow:hidden;color:var(--block-label-color);font:var(--font-sans);font-size:var(--button-small-text-size)}.wrap.svelte-jigama{display:flex;flex-direction:column;width:100%}.head.svelte-jigama{display:flex;justify-content:space-between}input[type=number].svelte-jigama{display:block;position:relative;outline:none!important;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--input-border-color);border-radius:var(--input-radius);background:var(--input-background-fill);padding:var(--size-2) var(--size-2);height:var(--size-6);color:var(--body-text-color);font-size:var(--input-text-size);line-height:var(--line-sm);text-align:center}input[type=number].svelte-jigama:focus{box-shadow:var(--input-shadow-focus);border-color:var(--input-border-color-focus)}input.svelte-jigama::placeholder{color:var(--input-placeholder-color)}input[type=range].svelte-jigama{width:100%;accent-color:var(--slider-color)}input[disabled].svelte-jigama{cursor:not-allowed}input.svelte-56zyyb{display:block;position:relative;background:var(--background-fill-primary);line-height:var(--line-sm)}
|
static/Column-2853eb31.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
div.svelte-vt1mxs{display:flex;position:relative;flex-direction:column}div.svelte-vt1mxs>*,div.svelte-vt1mxs>.form>*{width:var(--size-full)}.gap.svelte-vt1mxs{gap:var(--layout-gap)}.hide.svelte-vt1mxs{display:none}.compact.svelte-vt1mxs>*,.compact.svelte-vt1mxs .box{border-radius:0}.compact.svelte-vt1mxs,.panel.svelte-vt1mxs{border:solid var(--panel-border-width) var(--panel-border-color);border-radius:var(--container-radius);background:var(--panel-background-fill);padding:var(--spacing-lg)}
|
static/DropdownArrow-5fa4dd09.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
.dropdown-arrow.svelte-p5edak{fill:var(--body-text-color);margin-right:var(--size-2);width:var(--size-5)}
|
static/Form-a4a7741e.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
div.svelte-awbtu4{display:flex;flex-direction:inherit;flex-wrap:wrap;gap:var(--form-gap-width);box-shadow:var(--block-shadow);border:var(--block-border-width) solid var(--border-color-primary);border-radius:var(--radius-lg);background:var(--border-color-primary);overflow:hidden}div.svelte-awbtu4 .block{box-shadow:none!important;border-width:0px!important;border-radius:0!important}.hidden.svelte-awbtu4{display:none}
|
static/Image-003ee87c.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
img.svelte-gqt00k{border-radius:var(--radius-lg);max-width:none}img.selected.svelte-gqt00k{border-color:var(--border-color-accent)}.table.svelte-gqt00k{margin:0 auto;border:2px solid var(--border-color-primary);border-radius:var(--radius-lg);width:var(--size-20);height:var(--size-20);object-fit:cover}.gallery.svelte-gqt00k{border:2px solid var(--border-color-primary);max-height:var(--size-20);object-fit:cover}
|
static/Model3D-98fc2b2c.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
.gallery.svelte-1ayixqk{padding:var(--size-1) var(--size-2)}
|
static/ModifyUpload-77b0d4b2.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
div.svelte-116rqfv{cursor:pointer;width:var(--size-full);height:var(--size-full)}.center.svelte-116rqfv{text-align:center}.flex.svelte-116rqfv{display:flex;justify-content:center;align-items:center}input.svelte-116rqfv{display:none}div.svelte-19sk1im{display:flex;top:var(--size-2);right:var(--size-2);justify-content:flex-end;gap:var(--spacing-sm);z-index:var(--layer-1)}.not-absolute.svelte-19sk1im{margin:var(--size-1)}
|
static/StaticImage-ede66243.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
canvas.svelte-yigbas{display:block;position:absolute;inset:0;margin:auto}.lr.svelte-yigbas{border-right:1px solid var(--border-color-primary);border-left:1px solid var(--border-color-primary)}.tb.svelte-yigbas{border-top:1px solid var(--border-color-primary);border-bottom:1px solid var(--border-color-primary)}canvas.svelte-yigbas:hover{cursor:none}.wrap.svelte-yigbas{position:relative;width:var(--size-full);height:var(--size-full);touch-action:none}.start-prompt.svelte-yigbas{display:flex;position:absolute;inset:0;justify-content:center;align-items:center;z-index:var(--layer-4);touch-action:none;pointer-events:none;color:var(--body-text-color-subdued)}.wrap.svelte-xbxfke{position:relative;width:var(--size-full);height:var(--size-full);min-height:var(--size-60)}video.svelte-xbxfke{width:var(--size-full);height:var(--size-full)}button.svelte-xbxfke{display:flex;position:absolute;right:0;bottom:var(--size-2);left:0;justify-content:center;align-items:center;margin:auto;box-shadow:var(--shadow-drop-lg);border-radius:var(--radius-xl);background-color:#000000e6;width:var(--size-10);height:var(--size-10)}@media (min-width: 768px){button.svelte-xbxfke{bottom:var(--size-4)}}@media (min-width: 1280px){button.svelte-xbxfke{bottom:var(--size-8)}}.icon.svelte-xbxfke{opacity:.8;width:50%;height:50%;color:#fff}.flip.svelte-xbxfke{transform:scaleX(-1)}div.svelte-s6ybro{display:flex;position:absolute;top:var(--size-2);right:var(--size-2);justify-content:flex-end;gap:var(--spacing-sm);z-index:var(--layer-5)}.wrap.svelte-p4aq0j.svelte-p4aq0j{display:flex;position:absolute;top:var(--size-10);right:var(--size-2);flex-direction:column;justify-content:flex-end;gap:var(--spacing-sm);z-index:var(--layer-5)}.brush.svelte-p4aq0j.svelte-p4aq0j{top:0;right:0}.brush.svelte-p4aq0j input.svelte-p4aq0j{position:absolute;top:3px;right:calc(100% + 5px)}.col.svelte-p4aq0j input.svelte-p4aq0j{position:absolute;right:calc(100% + 5px);bottom:-4px}.image-container.svelte-p3y7hu,img.svelte-p3y7hu{width:var(--size-full);height:var(--size-full)}img.svelte-p3y7hu{object-fit:contain}.selectable.svelte-p3y7hu{cursor:crosshair}.absolute-img.svelte-p3y7hu{position:absolute;opacity:0}.webcam.svelte-p3y7hu{transform:scaleX(-1)}img.svelte-ms5bsk{width:var(--size-full);height:var(--size-full);object-fit:contain}.selectable.svelte-ms5bsk{cursor:crosshair}.download.svelte-ms5bsk{position:absolute;top:6px;right:6px}
|
static/UploadText-33d53a1c.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
.wrap.svelte-xwlu1w{display:flex;flex-direction:column;justify-content:center;min-height:var(--size-60);color:var(--block-label-text-color);line-height:var(--line-md)}.or.svelte-xwlu1w{color:var(--body-text-color-subdued)}@media (min-width: 768px){.wrap.svelte-xwlu1w{font-size:var(--text-lg)}}
|
static/a.html
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
<html><head>
|
2 |
+
<meta http-equiv="content-type" content="text/html; charset=UTF-8"></head><body></body></html>
|
static/academicons.min.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
@font-face {font-family: 'Academicons';font-style: normal;font-weight: 400;font-display: block;src:url('../fonts/academicons.eot');src:url('../fonts/academicons.eot') format('embedded-opentype'), url('../fonts/academicons.ttf') format('truetype'), url('../fonts/academicons.woff') format('woff'), url('../fonts/academicons.svg') format('svg');}.ai {font-family: 'Academicons';font-weight: 400;-moz-osx-font-smoothing: grayscale;-webkit-font-smoothing: antialiased;display: inline-block;font-style: normal;font-variant: normal;text-rendering: auto;line-height: 1;}.ai-academia:before {content: "\e9af";}.ai-academia-square:before {content: "\e93d";}.ai-acclaim:before {content: "\e92e";}.ai-acclaim-square:before {content: "\e93a";}.ai-acm:before {content: "\e93c";}.ai-acm-square:before {content: "\e95d";}.ai-acmdl:before {content: "\e96a";}.ai-acmdl-square:before {content: "\e9d3";}.ai-ads:before {content: "\e9cb";}.ai-ads-square:before {content: "\e94a";}.ai-africarxiv:before {content: "\e91b";}.ai-africarxiv-square:before {content: "\e90b";}.ai-archive:before {content: "\e955";}.ai-archive-square:before {content: "\e956";}.ai-arxiv:before {content: "\e974";}.ai-arxiv-square:before {content: "\e9a6";}.ai-biorxiv:before {content: "\e9a2";}.ai-biorxiv-square:before {content: "\e98b";}.ai-ceur:before {content: "\e96d";}.ai-ceur-square:before {content: "\e92f";}.ai-ciencia-vitae:before {content: "\e912";}.ai-ciencia-vitae-square:before {content: "\e913";}.ai-clarivate:before {content: "\e924";}.ai-clarivate-square:before {content: "\e925";}.ai-closed-access:before {content: "\e942";}.ai-closed-access-square:before {content: "\e943";}.ai-conversation:before {content: "\e94c";}.ai-conversation-square:before {content: "\e915";}.ai-coursera:before {content: "\e95f";}.ai-coursera-square:before {content: "\e97f";}.ai-crossref:before {content: "\e918";}.ai-crossref-square:before {content: "\e919";}.ai-cv:before {content: "\e9a5";}.ai-cv-square:before {content: "\e90a";}.ai-datacite:before {content: "\e91c";}.ai-datacite-square:before {content: "\e91d";}.ai-dataverse:before {content: "\e9f7";}.ai-dataverse-square:before {content: "\e9e4";}.ai-dblp:before {content: "\e94f";}.ai-dblp-square:before {content: "\e93f";}.ai-depsy:before {content: "\e97a";}.ai-depsy-square:before {content: "\e94b";}.ai-doi:before {content: "\e97e";}.ai-doi-square:before {content: "\e98f";}.ai-dryad:before {content: "\e97c";}.ai-dryad-square:before {content: "\e98c";}.ai-elsevier:before {content: "\e961";}.ai-elsevier-square:before {content: "\e910";}.ai-figshare:before {content: "\e981";}.ai-figshare-square:before {content: "\e9e7";}.ai-google-scholar:before {content: "\e9d4";}.ai-google-scholar-square:before {content: "\e9f9";}.ai-hal:before {content: "\e92c";}.ai-hal-square:before {content: "\e92d";}.ai-hypothesis:before {content: "\e95a";}.ai-hypothesis-square:before {content: "\e95b";}.ai-ideas-repec:before {content: "\e9ed";}.ai-ideas-repec-square:before {content: "\e9f8";}.ai-ieee:before {content: "\e929";}.ai-ieee-square:before {content: "\e9b9";}.ai-impactstory:before {content: "\e9cf";}.ai-impactstory-square:before {content: "\e9aa";}.ai-inaturalist:before {content: "\e900";}.ai-inaturalist-square:before {content: "\e901";}.ai-inpn:before {content: "\e902";}.ai-inpn-square:before {content: "\e903";}.ai-inspire:before {content: "\e9e9";}.ai-inspire-square:before {content: "\e9fe";}.ai-isidore:before {content: "\e936";}.ai-isidore-square:before {content: "\e954";}.ai-isni:before {content: "\e957";}.ai-isni-square:before {content: "\e958";}.ai-jstor:before {content: "\e938";}.ai-jstor-square:before {content: "\e944";}.ai-lattes:before {content: "\e9b3";}.ai-lattes-square:before {content: "\e99c";}.ai-mathoverflow:before {content: "\e9f6";}.ai-mathoverflow-square:before {content: "\e97b";}.ai-mendeley:before {content: "\e9f0";}.ai-mendeley-square:before {content: "\e9f3";}.ai-moodle:before {content: "\e907";}.ai-moodle-square:before {content: "\e908";}.ai-mtmt:before {content: "\e950";}.ai-mtmt-square:before {content: "\e951";}.ai-nakala:before {content: "\e940";}.ai-nakala-square:before {content: "\e941";}.ai-obp:before {content: "\e92a";}.ai-obp-square:before {content: "\e92b";}.ai-open-access:before {content: "\e939";}.ai-open-access-square:before {content: "\e9f4";}.ai-open-data:before {content: "\e966";}.ai-open-data-square:before {content: "\e967";}.ai-open-materials:before {content: "\e968";}.ai-open-materials-square:before {content: "\e969";}.ai-openedition:before {content: "\e946";}.ai-openedition-square:before {content: "\e947";}.ai-orcid:before {content: "\e9d9";}.ai-orcid-square:before {content: "\e9c3";}.ai-osf:before {content: "\e9ef";}.ai-osf-square:before {content: "\e931";}.ai-overleaf:before {content: "\e914";}.ai-overleaf-square:before {content: "\e98d";}.ai-philpapers:before {content: "\e98a";}.ai-philpapers-square:before {content: "\e96f";}.ai-piazza:before {content: "\e99a";}.ai-piazza-square:before {content: "\e90c";}.ai-preregistered:before {content: "\e906";}.ai-preregistered-square:before {content: "\e96b";}.ai-protocols:before {content: "\e952";}.ai-protocols-square:before {content: "\e953";}.ai-psyarxiv:before {content: "\e90e";}.ai-psyarxiv-square:before {content: "\e90f";}.ai-publons:before {content: "\e937";}.ai-publons-square:before {content: "\e94e";}.ai-pubmed:before {content: "\e99f";}.ai-pubmed-square:before {content: "\e97d";}.ai-pubpeer:before {content: "\e922";}.ai-pubpeer-square:before {content: "\e923";}.ai-researcherid:before {content: "\e91a";}.ai-researcherid-square:before {content: "\e95c";}.ai-researchgate:before {content: "\e95e";}.ai-researchgate-square:before {content: "\e99e";}.ai-ror:before {content: "\e948";}.ai-ror-square:before {content: "\e949";}.ai-sci-hub:before {content: "\e959";}.ai-sci-hub-square:before {content: "\e905";}.ai-scirate:before {content: "\e98e";}.ai-scirate-square:before {content: "\e99d";}.ai-scopus:before {content: "\e91e";}.ai-scopus-square:before {content: "\e91f";}.ai-semantic-scholar:before {content: "\e96e";}.ai-semantic-scholar-square:before {content: "\e96c";}.ai-springer:before {content: "\e928";}.ai-springer-square:before {content: "\e99b";}.ai-ssrn:before {content: "\e916";}.ai-ssrn-square:before {content: "\e917";}.ai-stackoverflow:before {content: "\e920";}.ai-stackoverflow-square:before {content: "\e921";}.ai-viaf:before {content: "\e933";}.ai-viaf-square:before {content: "\e934";}.ai-wiley:before {content: "\e926";}.ai-wiley-square:before {content: "\e927";}.ai-zenodo:before {content: "\e911";}.ai-zotero:before {content: "\e962";}.ai-zotero-square:before {content: "\e932";}.ai-lg {font-size: 1.33333em;line-height: 0.75em;vertical-align: -.0667em;}.ai-xs {font-size: .75em;}.ai-sm {font-size: .875em;}.ai-1x {font-size: 1em;}.ai-2x {font-size: 2em;}.ai-3x {font-size: 3em;}.ai-4x {font-size: 4em;}.ai-5x {font-size: 5em;}.ai-6x {font-size: 6em;}.ai-7x {font-size: 7em;}.ai-8x {font-size: 8em;}.ai-9x {font-size: 9em;}.ai-10x {font-size: 10em;}.ai-fw {text-align: center;width: 1.25em;}.ai-ul {list-style-type: none;margin-left: 2.5em;padding-left: 0;}.ai-ul > li {position: relative;}.ai-li {left: -2em;position: absolute;text-align: center;width: 2em;line-height: inherit;}.ai-border {border: solid 0.08em #eee;border-radius: .1em;padding: .2em .25em .15em;}.ai-pull-left {float: left;}.ai-pull-right {float: right;}.ai.ai-pull-left {margin-right: .3em;}.ai.ai-pull-right {margin-right: .3em;}.ai-stack {display: inline-block;height: 2em;line-height: 2em;position: relative;vertical-align: middle;width: 2.5em;}.ai-stack-1x, .ai-stack-2x {left: 0;position: absolute;text-align: center;width: 100%;}.ai-stack-1x {line-height: inherit;}.ai-stack-2x {font-size: 2em;}.ai-inverse {color: #fff;}
|
static/all.min.css
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
* Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com
|
3 |
+
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
4 |
+
*/
|
5 |
+
.fa,.fab,.fad,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-bacteria:before{content:"\e059"}.fa-bacterium:before{content:"\e05a"}.fa-bahai:before{content:"\f666"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-box-tissue:before{content:"\e05b"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buy-n-large:before{content:"\f8a6"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caravan:before{content:"\f8ff"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudflare:before{content:"\e07d"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-alt:before{content:"\f422"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dailymotion:before{content:"\e052"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-deezer:before{content:"\e077"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-disease:before{content:"\f7fa"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edge-legacy:before{content:"\e078"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-alt:before{content:"\f424"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-faucet:before{content:"\e005"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-firefox-browser:before{content:"\e007"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-pay:before{content:"\e079"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guilded:before{content:"\e07e"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-medical:before{content:"\e05c"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-holding-water:before{content:"\f4c1"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-sparkles:before{content:"\e05d"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-hands-wash:before{content:"\e05e"}.fa-handshake:before{content:"\f2b5"}.fa-handshake-alt-slash:before{content:"\e05f"}.fa-handshake-slash:before{content:"\e060"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-hat-wizard:before{content:"\f6e8"}.fa-hdd:before{content:"\f0a0"}.fa-head-side-cough:before{content:"\e061"}.fa-head-side-cough-slash:before{content:"\e062"}.fa-head-side-mask:before{content:"\e063"}.fa-head-side-virus:before{content:"\e064"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hive:before{content:"\e07f"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hospital-user:before{content:"\f80d"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-house-user:before{content:"\e065"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-ideal:before{content:"\e013"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-innosoft:before{content:"\e080"}.fa-instagram:before{content:"\f16d"}.fa-instagram-square:before{content:"\e055"}.fa-instalod:before{content:"\e081"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-house:before{content:"\e066"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lungs:before{content:"\f604"}.fa-lungs-virus:before{content:"\e067"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-mdb:before{content:"\f8ca"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microblog:before{content:"\e01a"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mixer:before{content:"\e056"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse:before{content:"\f8cc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-octopus-deploy:before{content:"\e082"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-orcid:before{content:"\f8d2"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-arrows:before{content:"\e068"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-perbyte:before{content:"\e083"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-square:before{content:"\e01e"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-plane-slash:before{content:"\e069"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pump-medical:before{content:"\e06a"}.fa-pump-soap:before{content:"\e06b"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-record-vinyl:before{content:"\f8d9"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-rust:before{content:"\e07a"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-shield-virus:before{content:"\e06c"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopify:before{content:"\e057"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sink:before{content:"\e06d"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-soap:before{content:"\e06e"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-stopwatch-20:before{content:"\e06f"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-store-alt-slash:before{content:"\e070"}.fa-store-slash:before{content:"\e071"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swift:before{content:"\f8e1"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-tiktok:before{content:"\e07b"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toilet-paper-slash:before{content:"\e072"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-trailer:before{content:"\e041"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbraco:before{content:"\f8e8"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-uncharted:before{content:"\e084"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\e049"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-unsplash:before{content:"\e07c"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-users-slash:before{content:"\e073"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-vest:before{content:"\e085"}.fa-vest-patches:before{content:"\e086"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-virus:before{content:"\e074"}.fa-virus-slash:before{content:"\e075"}.fa-viruses:before{content:"\e076"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-watchman-monitoring:before{content:"\e087"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wodu:before{content:"\e088"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.fab,.far{font-weight:400}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.far,.fas{font-family:"Font Awesome 5 Free"}.fa,.fas{font-weight:900}
|
static/all.min.js
ADDED
The diff for this file is too large to render.
See raw diff
|
|
static/bootstrap.min.css
ADDED
The diff for this file is too large to render.
See raw diff
|
|
static/bulma.min.css
ADDED
The diff for this file is too large to render.
See raw diff
|
|
static/css.css
ADDED
@@ -0,0 +1,259 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* See: https://fonts.google.com/license/googlerestricted
|
3 |
+
*/
|
4 |
+
/* latin-ext */
|
5 |
+
@font-face {
|
6 |
+
font-family: 'Castoro';
|
7 |
+
font-style: normal;
|
8 |
+
font-weight: 400;
|
9 |
+
src: url(https://fonts.gstatic.com/s/castoro/v19/1q2GY5yMCld3-O4cLYFOzdYe.woff2) format('woff2');
|
10 |
+
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
11 |
+
}
|
12 |
+
/* latin */
|
13 |
+
@font-face {
|
14 |
+
font-family: 'Castoro';
|
15 |
+
font-style: normal;
|
16 |
+
font-weight: 400;
|
17 |
+
src: url(https://fonts.gstatic.com/s/castoro/v19/1q2GY5yMCld3-O4cLY9OzQ.woff2) format('woff2');
|
18 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
19 |
+
}
|
20 |
+
/* armenian */
|
21 |
+
@font-face {
|
22 |
+
font-family: 'Google Sans';
|
23 |
+
font-style: normal;
|
24 |
+
font-weight: 400;
|
25 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl1pynSEg.woff2) format('woff2');
|
26 |
+
unicode-range: U+0308, U+0530-058F, U+2010, U+2024, U+25CC, U+FB13-FB17;
|
27 |
+
}
|
28 |
+
/* bengali */
|
29 |
+
@font-face {
|
30 |
+
font-family: 'Google Sans';
|
31 |
+
font-style: normal;
|
32 |
+
font-weight: 400;
|
33 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl3pynSEg.woff2) format('woff2');
|
34 |
+
unicode-range: U+0964-0965, U+0980-09FE, U+1CF7, U+1CFA, U+200C-200D, U+20B9, U+25CC;
|
35 |
+
}
|
36 |
+
/* cyrillic-ext */
|
37 |
+
@font-face {
|
38 |
+
font-family: 'Google Sans';
|
39 |
+
font-style: normal;
|
40 |
+
font-weight: 400;
|
41 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlopynSEg.woff2) format('woff2');
|
42 |
+
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
43 |
+
}
|
44 |
+
/* cyrillic */
|
45 |
+
@font-face {
|
46 |
+
font-family: 'Google Sans';
|
47 |
+
font-style: normal;
|
48 |
+
font-weight: 400;
|
49 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlhpynSEg.woff2) format('woff2');
|
50 |
+
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
51 |
+
}
|
52 |
+
/* devanagari */
|
53 |
+
@font-face {
|
54 |
+
font-family: 'Google Sans';
|
55 |
+
font-style: normal;
|
56 |
+
font-weight: 400;
|
57 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlkpynSEg.woff2) format('woff2');
|
58 |
+
unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FF;
|
59 |
+
}
|
60 |
+
/* ethiopic */
|
61 |
+
@font-face {
|
62 |
+
font-family: 'Google Sans';
|
63 |
+
font-style: normal;
|
64 |
+
font-weight: 400;
|
65 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl0pynSEg.woff2) format('woff2');
|
66 |
+
unicode-range: U+1200-1399, U+2D80-2DDE, U+AB01-AB2E, U+1E7E0-1E7E6, U+1E7E8-1E7EB, U+1E7ED-1E7EE, U+1E7F0-1E7FE;
|
67 |
+
}
|
68 |
+
/* georgian */
|
69 |
+
@font-face {
|
70 |
+
font-family: 'Google Sans';
|
71 |
+
font-style: normal;
|
72 |
+
font-weight: 400;
|
73 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl6pynSEg.woff2) format('woff2');
|
74 |
+
unicode-range: U+0589, U+10A0-10FF, U+1C90-1CBA, U+1CBD-1CBF, U+2D00-2D2F;
|
75 |
+
}
|
76 |
+
/* greek */
|
77 |
+
@font-face {
|
78 |
+
font-family: 'Google Sans';
|
79 |
+
font-style: normal;
|
80 |
+
font-weight: 400;
|
81 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlmpynSEg.woff2) format('woff2');
|
82 |
+
unicode-range: U+0370-03FF;
|
83 |
+
}
|
84 |
+
/* gujarati */
|
85 |
+
@font-face {
|
86 |
+
font-family: 'Google Sans';
|
87 |
+
font-style: normal;
|
88 |
+
font-weight: 400;
|
89 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl-pynSEg.woff2) format('woff2');
|
90 |
+
unicode-range: U+0964-0965, U+0A80-0AFF, U+200C-200D, U+20B9, U+25CC, U+A830-A839;
|
91 |
+
}
|
92 |
+
/* gurmukhi */
|
93 |
+
@font-face {
|
94 |
+
font-family: 'Google Sans';
|
95 |
+
font-style: normal;
|
96 |
+
font-weight: 400;
|
97 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlGpynSEg.woff2) format('woff2');
|
98 |
+
unicode-range: U+0964-0965, U+0A01-0A76, U+200C-200D, U+20B9, U+25CC, U+262C, U+A830-A839;
|
99 |
+
}
|
100 |
+
/* hebrew */
|
101 |
+
@font-face {
|
102 |
+
font-family: 'Google Sans';
|
103 |
+
font-style: normal;
|
104 |
+
font-weight: 400;
|
105 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlnpynSEg.woff2) format('woff2');
|
106 |
+
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
107 |
+
}
|
108 |
+
/* khmer */
|
109 |
+
@font-face {
|
110 |
+
font-family: 'Google Sans';
|
111 |
+
font-style: normal;
|
112 |
+
font-weight: 400;
|
113 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlupynSEg.woff2) format('woff2');
|
114 |
+
unicode-range: U+1780-17FF, U+19E0-19FF, U+200C, U+25CC;
|
115 |
+
}
|
116 |
+
/* lao */
|
117 |
+
@font-face {
|
118 |
+
font-family: 'Google Sans';
|
119 |
+
font-style: normal;
|
120 |
+
font-weight: 400;
|
121 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlspynSEg.woff2) format('woff2');
|
122 |
+
unicode-range: U+0E81-0EDF, U+25CC;
|
123 |
+
}
|
124 |
+
/* oriya */
|
125 |
+
@font-face {
|
126 |
+
font-family: 'Google Sans';
|
127 |
+
font-style: normal;
|
128 |
+
font-weight: 400;
|
129 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl8pynSEg.woff2) format('woff2');
|
130 |
+
unicode-range: U+0964-0965, U+0B01-0B77, U+200C-200D, U+20B9, U+25CC;
|
131 |
+
}
|
132 |
+
/* sinhala */
|
133 |
+
@font-face {
|
134 |
+
font-family: 'Google Sans';
|
135 |
+
font-style: normal;
|
136 |
+
font-weight: 400;
|
137 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl4pynSEg.woff2) format('woff2');
|
138 |
+
unicode-range: U+0964-0965, U+0D81-0DF4, U+200C-200D, U+25CC, U+111E1-111F4;
|
139 |
+
}
|
140 |
+
/* tamil */
|
141 |
+
@font-face {
|
142 |
+
font-family: 'Google Sans';
|
143 |
+
font-style: normal;
|
144 |
+
font-weight: 400;
|
145 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlzpynSEg.woff2) format('woff2');
|
146 |
+
unicode-range: U+0964-0965, U+0B82-0BFA, U+200C-200D, U+20B9, U+25CC;
|
147 |
+
}
|
148 |
+
/* telugu */
|
149 |
+
@font-face {
|
150 |
+
font-family: 'Google Sans';
|
151 |
+
font-style: normal;
|
152 |
+
font-weight: 400;
|
153 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl5pynSEg.woff2) format('woff2');
|
154 |
+
unicode-range: U+0951-0952, U+0964-0965, U+0C00-0C7F, U+1CDA, U+200C-200D, U+25CC;
|
155 |
+
}
|
156 |
+
/* thai */
|
157 |
+
@font-face {
|
158 |
+
font-family: 'Google Sans';
|
159 |
+
font-style: normal;
|
160 |
+
font-weight: 400;
|
161 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlxpynSEg.woff2) format('woff2');
|
162 |
+
unicode-range: U+0E01-0E5B, U+200C-200D, U+25CC;
|
163 |
+
}
|
164 |
+
/* vietnamese */
|
165 |
+
@font-face {
|
166 |
+
font-family: 'Google Sans';
|
167 |
+
font-style: normal;
|
168 |
+
font-weight: 400;
|
169 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlqpynSEg.woff2) format('woff2');
|
170 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
171 |
+
}
|
172 |
+
/* latin-ext */
|
173 |
+
@font-face {
|
174 |
+
font-family: 'Google Sans';
|
175 |
+
font-style: normal;
|
176 |
+
font-weight: 400;
|
177 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlrpynSEg.woff2) format('woff2');
|
178 |
+
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
179 |
+
}
|
180 |
+
/* latin */
|
181 |
+
@font-face {
|
182 |
+
font-family: 'Google Sans';
|
183 |
+
font-style: normal;
|
184 |
+
font-weight: 400;
|
185 |
+
src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJllpyk.woff2) format('woff2');
|
186 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
187 |
+
}
|
188 |
+
/* cyrillic-ext */
|
189 |
+
@font-face {
|
190 |
+
font-family: 'Noto Sans';
|
191 |
+
font-style: normal;
|
192 |
+
font-weight: 400;
|
193 |
+
font-stretch: 100%;
|
194 |
+
src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9X6VLKzA.woff2) format('woff2');
|
195 |
+
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
196 |
+
}
|
197 |
+
/* cyrillic */
|
198 |
+
@font-face {
|
199 |
+
font-family: 'Noto Sans';
|
200 |
+
font-style: normal;
|
201 |
+
font-weight: 400;
|
202 |
+
font-stretch: 100%;
|
203 |
+
src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9e6VLKzA.woff2) format('woff2');
|
204 |
+
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
205 |
+
}
|
206 |
+
/* devanagari */
|
207 |
+
@font-face {
|
208 |
+
font-family: 'Noto Sans';
|
209 |
+
font-style: normal;
|
210 |
+
font-weight: 400;
|
211 |
+
font-stretch: 100%;
|
212 |
+
src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9b6VLKzA.woff2) format('woff2');
|
213 |
+
unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FF;
|
214 |
+
}
|
215 |
+
/* greek-ext */
|
216 |
+
@font-face {
|
217 |
+
font-family: 'Noto Sans';
|
218 |
+
font-style: normal;
|
219 |
+
font-weight: 400;
|
220 |
+
font-stretch: 100%;
|
221 |
+
src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9W6VLKzA.woff2) format('woff2');
|
222 |
+
unicode-range: U+1F00-1FFF;
|
223 |
+
}
|
224 |
+
/* greek */
|
225 |
+
@font-face {
|
226 |
+
font-family: 'Noto Sans';
|
227 |
+
font-style: normal;
|
228 |
+
font-weight: 400;
|
229 |
+
font-stretch: 100%;
|
230 |
+
src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9Z6VLKzA.woff2) format('woff2');
|
231 |
+
unicode-range: U+0370-03FF;
|
232 |
+
}
|
233 |
+
/* vietnamese */
|
234 |
+
@font-face {
|
235 |
+
font-family: 'Noto Sans';
|
236 |
+
font-style: normal;
|
237 |
+
font-weight: 400;
|
238 |
+
font-stretch: 100%;
|
239 |
+
src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9V6VLKzA.woff2) format('woff2');
|
240 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
241 |
+
}
|
242 |
+
/* latin-ext */
|
243 |
+
@font-face {
|
244 |
+
font-family: 'Noto Sans';
|
245 |
+
font-style: normal;
|
246 |
+
font-weight: 400;
|
247 |
+
font-stretch: 100%;
|
248 |
+
src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9U6VLKzA.woff2) format('woff2');
|
249 |
+
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
250 |
+
}
|
251 |
+
/* latin */
|
252 |
+
@font-face {
|
253 |
+
font-family: 'Noto Sans';
|
254 |
+
font-style: normal;
|
255 |
+
font-weight: 400;
|
256 |
+
font-stretch: 100%;
|
257 |
+
src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9a6VI.woff2) format('woff2');
|
258 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
259 |
+
}
|
static/css2.css
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* cyrillic-ext */
|
2 |
+
@font-face {
|
3 |
+
font-family: 'Source Sans Pro';
|
4 |
+
font-style: normal;
|
5 |
+
font-weight: 400;
|
6 |
+
font-display: swap;
|
7 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNa7lqDY.woff2) format('woff2');
|
8 |
+
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
9 |
+
}
|
10 |
+
/* cyrillic */
|
11 |
+
@font-face {
|
12 |
+
font-family: 'Source Sans Pro';
|
13 |
+
font-style: normal;
|
14 |
+
font-weight: 400;
|
15 |
+
font-display: swap;
|
16 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qPK7lqDY.woff2) format('woff2');
|
17 |
+
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
18 |
+
}
|
19 |
+
/* greek-ext */
|
20 |
+
@font-face {
|
21 |
+
font-family: 'Source Sans Pro';
|
22 |
+
font-style: normal;
|
23 |
+
font-weight: 400;
|
24 |
+
font-display: swap;
|
25 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNK7lqDY.woff2) format('woff2');
|
26 |
+
unicode-range: U+1F00-1FFF;
|
27 |
+
}
|
28 |
+
/* greek */
|
29 |
+
@font-face {
|
30 |
+
font-family: 'Source Sans Pro';
|
31 |
+
font-style: normal;
|
32 |
+
font-weight: 400;
|
33 |
+
font-display: swap;
|
34 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qO67lqDY.woff2) format('woff2');
|
35 |
+
unicode-range: U+0370-03FF;
|
36 |
+
}
|
37 |
+
/* vietnamese */
|
38 |
+
@font-face {
|
39 |
+
font-family: 'Source Sans Pro';
|
40 |
+
font-style: normal;
|
41 |
+
font-weight: 400;
|
42 |
+
font-display: swap;
|
43 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qN67lqDY.woff2) format('woff2');
|
44 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
45 |
+
}
|
46 |
+
/* latin-ext */
|
47 |
+
@font-face {
|
48 |
+
font-family: 'Source Sans Pro';
|
49 |
+
font-style: normal;
|
50 |
+
font-weight: 400;
|
51 |
+
font-display: swap;
|
52 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNq7lqDY.woff2) format('woff2');
|
53 |
+
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
54 |
+
}
|
55 |
+
/* latin */
|
56 |
+
@font-face {
|
57 |
+
font-family: 'Source Sans Pro';
|
58 |
+
font-style: normal;
|
59 |
+
font-weight: 400;
|
60 |
+
font-display: swap;
|
61 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2) format('woff2');
|
62 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
63 |
+
}
|
64 |
+
/* cyrillic-ext */
|
65 |
+
@font-face {
|
66 |
+
font-family: 'Source Sans Pro';
|
67 |
+
font-style: normal;
|
68 |
+
font-weight: 600;
|
69 |
+
font-display: swap;
|
70 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwmhduz8A.woff2) format('woff2');
|
71 |
+
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
72 |
+
}
|
73 |
+
/* cyrillic */
|
74 |
+
@font-face {
|
75 |
+
font-family: 'Source Sans Pro';
|
76 |
+
font-style: normal;
|
77 |
+
font-weight: 600;
|
78 |
+
font-display: swap;
|
79 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwkxduz8A.woff2) format('woff2');
|
80 |
+
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
81 |
+
}
|
82 |
+
/* greek-ext */
|
83 |
+
@font-face {
|
84 |
+
font-family: 'Source Sans Pro';
|
85 |
+
font-style: normal;
|
86 |
+
font-weight: 600;
|
87 |
+
font-display: swap;
|
88 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwmxduz8A.woff2) format('woff2');
|
89 |
+
unicode-range: U+1F00-1FFF;
|
90 |
+
}
|
91 |
+
/* greek */
|
92 |
+
@font-face {
|
93 |
+
font-family: 'Source Sans Pro';
|
94 |
+
font-style: normal;
|
95 |
+
font-weight: 600;
|
96 |
+
font-display: swap;
|
97 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwlBduz8A.woff2) format('woff2');
|
98 |
+
unicode-range: U+0370-03FF;
|
99 |
+
}
|
100 |
+
/* vietnamese */
|
101 |
+
@font-face {
|
102 |
+
font-family: 'Source Sans Pro';
|
103 |
+
font-style: normal;
|
104 |
+
font-weight: 600;
|
105 |
+
font-display: swap;
|
106 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwmBduz8A.woff2) format('woff2');
|
107 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
108 |
+
}
|
109 |
+
/* latin-ext */
|
110 |
+
@font-face {
|
111 |
+
font-family: 'Source Sans Pro';
|
112 |
+
font-style: normal;
|
113 |
+
font-weight: 600;
|
114 |
+
font-display: swap;
|
115 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwmRduz8A.woff2) format('woff2');
|
116 |
+
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
117 |
+
}
|
118 |
+
/* latin */
|
119 |
+
@font-face {
|
120 |
+
font-family: 'Source Sans Pro';
|
121 |
+
font-style: normal;
|
122 |
+
font-weight: 600;
|
123 |
+
font-display: swap;
|
124 |
+
src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwlxdu.woff2) format('woff2');
|
125 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
126 |
+
}
|
static/css2_002.css
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* cyrillic-ext */
|
2 |
+
@font-face {
|
3 |
+
font-family: 'IBM Plex Mono';
|
4 |
+
font-style: normal;
|
5 |
+
font-weight: 400;
|
6 |
+
font-display: swap;
|
7 |
+
src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F63fjptAgt5VM-kVkqdyU8n1iIq129k.woff2) format('woff2');
|
8 |
+
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
9 |
+
}
|
10 |
+
/* cyrillic */
|
11 |
+
@font-face {
|
12 |
+
font-family: 'IBM Plex Mono';
|
13 |
+
font-style: normal;
|
14 |
+
font-weight: 400;
|
15 |
+
font-display: swap;
|
16 |
+
src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F63fjptAgt5VM-kVkqdyU8n1isq129k.woff2) format('woff2');
|
17 |
+
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
18 |
+
}
|
19 |
+
/* vietnamese */
|
20 |
+
@font-face {
|
21 |
+
font-family: 'IBM Plex Mono';
|
22 |
+
font-style: normal;
|
23 |
+
font-weight: 400;
|
24 |
+
font-display: swap;
|
25 |
+
src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F63fjptAgt5VM-kVkqdyU8n1iAq129k.woff2) format('woff2');
|
26 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
27 |
+
}
|
28 |
+
/* latin-ext */
|
29 |
+
@font-face {
|
30 |
+
font-family: 'IBM Plex Mono';
|
31 |
+
font-style: normal;
|
32 |
+
font-weight: 400;
|
33 |
+
font-display: swap;
|
34 |
+
src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F63fjptAgt5VM-kVkqdyU8n1iEq129k.woff2) format('woff2');
|
35 |
+
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
36 |
+
}
|
37 |
+
/* latin */
|
38 |
+
@font-face {
|
39 |
+
font-family: 'IBM Plex Mono';
|
40 |
+
font-style: normal;
|
41 |
+
font-weight: 400;
|
42 |
+
font-display: swap;
|
43 |
+
src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F63fjptAgt5VM-kVkqdyU8n1i8q1w.woff2) format('woff2');
|
44 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
45 |
+
}
|
46 |
+
/* cyrillic-ext */
|
47 |
+
@font-face {
|
48 |
+
font-family: 'IBM Plex Mono';
|
49 |
+
font-style: normal;
|
50 |
+
font-weight: 600;
|
51 |
+
font-display: swap;
|
52 |
+
src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F6qfjptAgt5VM-kVkqdyU8n3vAOwl1FgtIU.woff2) format('woff2');
|
53 |
+
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
54 |
+
}
|
55 |
+
/* cyrillic */
|
56 |
+
@font-face {
|
57 |
+
font-family: 'IBM Plex Mono';
|
58 |
+
font-style: normal;
|
59 |
+
font-weight: 600;
|
60 |
+
font-display: swap;
|
61 |
+
src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F6qfjptAgt5VM-kVkqdyU8n3vAOwlRFgtIU.woff2) format('woff2');
|
62 |
+
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
63 |
+
}
|
64 |
+
/* vietnamese */
|
65 |
+
@font-face {
|
66 |
+
font-family: 'IBM Plex Mono';
|
67 |
+
font-style: normal;
|
68 |
+
font-weight: 600;
|
69 |
+
font-display: swap;
|
70 |
+
src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F6qfjptAgt5VM-kVkqdyU8n3vAOwl9FgtIU.woff2) format('woff2');
|
71 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
72 |
+
}
|
73 |
+
/* latin-ext */
|
74 |
+
@font-face {
|
75 |
+
font-family: 'IBM Plex Mono';
|
76 |
+
font-style: normal;
|
77 |
+
font-weight: 600;
|
78 |
+
font-display: swap;
|
79 |
+
src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F6qfjptAgt5VM-kVkqdyU8n3vAOwl5FgtIU.woff2) format('woff2');
|
80 |
+
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
81 |
+
}
|
82 |
+
/* latin */
|
83 |
+
@font-face {
|
84 |
+
font-family: 'IBM Plex Mono';
|
85 |
+
font-style: normal;
|
86 |
+
font-weight: 600;
|
87 |
+
font-display: swap;
|
88 |
+
src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F6qfjptAgt5VM-kVkqdyU8n3vAOwlBFgg.woff2) format('woff2');
|
89 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
90 |
+
}
|
static/gradio.js
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
|
3 |
+
function make_script(src) {
|
4 |
+
const script = document.createElement('script');
|
5 |
+
script.type = 'module';
|
6 |
+
script.setAttribute("crossorigin", "");
|
7 |
+
script.src = src;
|
8 |
+
document.head.appendChild(script);
|
9 |
+
}
|
10 |
+
make_script("https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-9405f928.js");
|
static/icon.css
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* fallback */
|
2 |
+
@font-face {
|
3 |
+
font-family: 'Material Icons';
|
4 |
+
font-style: normal;
|
5 |
+
font-weight: 400;
|
6 |
+
src: url(https://fonts.gstatic.com/s/materialicons/v140/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2) format('woff2');
|
7 |
+
}
|
8 |
+
|
9 |
+
.material-icons {
|
10 |
+
font-family: 'Material Icons';
|
11 |
+
font-weight: normal;
|
12 |
+
font-style: normal;
|
13 |
+
font-size: 24px;
|
14 |
+
line-height: 1;
|
15 |
+
letter-spacing: normal;
|
16 |
+
text-transform: none;
|
17 |
+
display: inline-block;
|
18 |
+
white-space: nowrap;
|
19 |
+
word-wrap: normal;
|
20 |
+
direction: ltr;
|
21 |
+
-moz-font-feature-settings: 'liga';
|
22 |
+
-moz-osx-font-smoothing: grayscale;
|
23 |
+
}
|
static/index-3ca142e0.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
.spacer.svelte-1kspdo{display:inline-block;width:0;height:0}.json-node.svelte-1kspdo{display:inline;color:var(--body-text-color);line-height:var(--line-sm);font-family:var(--font-mono)}.expand-array.svelte-1kspdo{border:1px solid var(--border-color-primary);border-radius:var(--radius-sm);background:var(--background-fill-secondary);padding:0 var(--size-1);color:var(--body-text-color)}.expand-array.svelte-1kspdo:hover{background:var(--background-fill-primary)}.children.svelte-1kspdo{padding-left:var(--size-4)}.json-item.svelte-1kspdo{display:inline}.null.svelte-1kspdo{color:var(--body-text-color-subdued)}.string.svelte-1kspdo{color:var(--color-green-500)}.number.svelte-1kspdo{color:var(--color-blue-500)}.bool.svelte-1kspdo{color:var(--color-red-500)}.json-holder.svelte-1trjy9a{padding:var(--size-2)}button.svelte-1trjy9a{display:flex;position:absolute;top:var(--block-label-margin);right:var(--block-label-margin);align-items:center;box-shadow:var(--shadow-drop);border:1px solid var(--border-color-primary);border-top:none;border-right:none;border-radius:var(--block-label-right-radius);background:var(--block-label-background-fill);padding:5px;width:22px;height:22px;overflow:hidden;color:var(--block-label-text-color);font:var(--font);font-size:var(--button-small-text-size)}
|
static/index-4a8edf2e.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
video.svelte-1tntsc1{flex:none;border:2px solid var(--border-color-primary);border-radius:var(--radius-lg);max-width:none}video.svelte-1tntsc1:hover,video.selected.svelte-1tntsc1{border-color:var(--border-color-accent)}.table.svelte-1tntsc1{margin:0 auto;width:var(--size-20);height:var(--size-20);object-fit:cover}.gallery.svelte-1tntsc1{max-height:var(--size-20);object-fit:cover}div.svelte-rgtszb{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gallery.svelte-rgtszb{display:flex;align-items:center;cursor:pointer;padding:var(--size-1) var(--size-2);text-align:left}table.svelte-1cib1xd.svelte-1cib1xd{position:relative}td.svelte-1cib1xd.svelte-1cib1xd{border:1px solid var(--table-border-color);padding:var(--size-2);font-size:var(--text-sm);font-family:var(--font-mono)}.selected.svelte-1cib1xd td.svelte-1cib1xd{border-color:var(--border-color-accent)}.table.svelte-1cib1xd.svelte-1cib1xd{display:inline-block;margin:0 auto}.gallery.svelte-1cib1xd td.svelte-1cib1xd:first-child{border-left:none}.gallery.svelte-1cib1xd tr:first-child td.svelte-1cib1xd{border-top:none}.gallery.svelte-1cib1xd td.svelte-1cib1xd:last-child{border-right:none}.gallery.svelte-1cib1xd tr:last-child td.svelte-1cib1xd{border-bottom:none}.overlay.svelte-1cib1xd.svelte-1cib1xd{--gradient-to:transparent;position:absolute;bottom:0;background:linear-gradient(to bottom,transparent,var(--gradient-to));width:var(--size-full);height:50%}.odd.svelte-1cib1xd.svelte-1cib1xd{--gradient-to:var(--table-even-background-fill)}.even.svelte-1cib1xd.svelte-1cib1xd{--gradient-to:var(--table-odd-background-fill)}.button.svelte-1cib1xd.svelte-1cib1xd{--gradient-to:var(--background-fill-primary)}div.svelte-h6ogpl{width:var(--size-10);height:var(--size-10)}.table.svelte-h6ogpl{margin:0 auto}.gallery.svelte-1ayixqk{padding:var(--size-1) var(--size-2)}.gallery.svelte-zvfedn{padding:var(--size-2)}pre.svelte-agpzo2{text-align:left}.gallery.svelte-agpzo2{padding:var(--size-1) var(--size-2)}.wrap.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{display:inline-block;width:var(--size-full);max-width:var(--size-full);color:var(--body-text-color)}.hide.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{display:none}.label.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{display:flex;align-items:center;margin-bottom:var(--size-2);color:var(--block-label-text-color);font-weight:var(--block-label-text-weight);font-size:var(--block-label-text-size);line-height:var(--line-sm)}svg.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{margin-right:var(--size-1)}.gallery.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{display:flex;flex-wrap:wrap;gap:var(--spacing-lg)}.gallery-item.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{border:1px solid var(--border-color-primary);border-radius:var(--button-large-radius);overflow:hidden}.gallery-item.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno:hover{border-color:var(--border-color-accent);background:var(--table-row-focus)}.table-wrap.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{border:1px solid var(--border-color-primary);border-radius:var(--table-radius);width:var(--size-full);table-layout:auto;overflow-x:auto;line-height:var(--line-sm)}table.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{width:var(--size-full)}.tr-head.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{box-shadow:var(--shadow-drop-lg);border-bottom:1px solid var(--border-color-primary)}.tr-head.svelte-13hsdno>.svelte-13hsdno+.svelte-13hsdno{border-right-width:0px;border-left-width:1px;border-color:var(--border-color-primary)}th.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{padding:var(--size-2);white-space:nowrap}.tr-body.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{cursor:pointer;border-bottom:1px solid var(--border-color-primary);background:var(--table-even-background-fill)}.tr-body.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno:last-child{border:none}.tr-body.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno:nth-child(odd){background:var(--table-odd-background-fill)}.tr-body.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno:hover{background:var(--table-row-focus)}.tr-body.svelte-13hsdno>.svelte-13hsdno+.svelte-13hsdno{border-right-width:0px;border-left-width:1px;border-color:var(--border-color-primary)}.tr-body.svelte-13hsdno:hover>.svelte-13hsdno+.svelte-13hsdno{border-color:var(--border-color-accent)}td.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{padding:var(--size-2);text-align:center}.paginate.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{display:flex;justify-content:center;align-items:center;gap:var(--spacing-sm);margin-top:var(--size-2);color:var(--block-label-text-color);font-size:var(--text-sm)}button.current-page.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{font-weight:var(--weight-bold)}
|
static/index-8f1feca1.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
span.svelte-s1r2yt{font-weight:var(--section-header-text-weight);font-size:var(--section-header-text-size)}.label-wrap.svelte-s1r2yt{display:flex;justify-content:space-between;cursor:pointer;width:var(--size-full)}.label-wrap.open.svelte-s1r2yt{margin-bottom:var(--size-2)}.icon.svelte-s1r2yt{transition:.15s}
|