Spaces:
Running
Running
Upload 11 files
Browse files- .gitattributes +30 -35
- .gitignore +5 -0
- README.md +40 -14
- app.py +1103 -0
- classifyTags.py +151 -0
- images/1girl.png +3 -0
- images/image1.png +3 -0
- images/image2.png +3 -0
- pre-requirements.txt +1 -0
- requirements.txt +24 -0
- themes/[email protected] +1 -0
.gitattributes
CHANGED
@@ -1,35 +1,30 @@
|
|
1 |
-
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
-
*.
|
5 |
-
*.
|
6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
-
*.
|
12 |
-
*.
|
13 |
-
*.
|
14 |
-
*.
|
15 |
-
*.
|
16 |
-
*.
|
17 |
-
*.
|
18 |
-
*.
|
19 |
-
*.
|
20 |
-
|
21 |
-
*.
|
22 |
-
*.
|
23 |
-
*.
|
24 |
-
*.
|
25 |
-
*.
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
+
*.bin.* filter=lfs diff=lfs merge=lfs -text
|
5 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
12 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
13 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
14 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
15 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
16 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
17 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
18 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
19 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
20 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
21 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
22 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
23 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
24 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
25 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
26 |
+
*.zstandard filter=lfs diff=lfs merge=lfs -text
|
27 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
28 |
+
1girl.png filter=lfs diff=lfs merge=lfs -text
|
29 |
+
images/image1.png filter=lfs diff=lfs merge=lfs -text
|
30 |
+
images/image2.png filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
.gitignore
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
images
|
2 |
+
.vs
|
3 |
+
venv
|
4 |
+
tmp
|
5 |
+
*.pyc
|
README.md
CHANGED
@@ -1,14 +1,40 @@
|
|
1 |
-
---
|
2 |
-
title: Multi
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
-
sdk: gradio
|
7 |
-
sdk_version: 5.23.3
|
8 |
-
app_file: app.py
|
9 |
-
pinned:
|
10 |
-
|
11 |
-
|
12 |
-
---
|
13 |
-
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
title: Multi-Tagger
|
3 |
+
emoji: 💬
|
4 |
+
colorFrom: purple
|
5 |
+
colorTo: indigo
|
6 |
+
sdk: gradio
|
7 |
+
sdk_version: 5.23.3
|
8 |
+
app_file: app.py
|
9 |
+
pinned: true
|
10 |
+
short_description: Image captioning
|
11 |
+
license: apache-2.0
|
12 |
+
---
|
13 |
+
|
14 |
+
# Configuration
|
15 |
+
|
16 |
+
`title`: _string_
|
17 |
+
Display title for the Space
|
18 |
+
|
19 |
+
`emoji`: _string_
|
20 |
+
Space emoji (emoji-only character allowed)
|
21 |
+
|
22 |
+
`colorFrom`: _string_
|
23 |
+
Color for Thumbnail gradient (red, yellow, green, blue, indigo, purple, pink, gray)
|
24 |
+
|
25 |
+
`colorTo`: _string_
|
26 |
+
Color for Thumbnail gradient (red, yellow, green, blue, indigo, purple, pink, gray)
|
27 |
+
|
28 |
+
`sdk`: _string_
|
29 |
+
Can be either `gradio`, `streamlit`, or `static`
|
30 |
+
|
31 |
+
`sdk_version` : _string_
|
32 |
+
Only applicable for `streamlit` SDK.
|
33 |
+
See [doc](https://hf.co/docs/hub/spaces) for more info on supported versions.
|
34 |
+
|
35 |
+
`app_file`: _string_
|
36 |
+
Path to your main application file (which contains either `gradio` or `streamlit` Python code, or `static` html code).
|
37 |
+
Path is relative to the root of the repository.
|
38 |
+
|
39 |
+
`pinned`: _boolean_
|
40 |
+
Whether the Space stays on top of your list.
|
app.py
ADDED
@@ -0,0 +1,1103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
|
3 |
+
import io
|
4 |
+
import copy
|
5 |
+
import requests
|
6 |
+
import numpy as np
|
7 |
+
import spaces
|
8 |
+
import gradio as gr
|
9 |
+
from transformers import AutoProcessor, AutoModelForCausalLM
|
10 |
+
from transformers import AutoModelForCausalLM, AutoProcessor
|
11 |
+
from transformers.dynamic_module_utils import get_imports
|
12 |
+
from PIL import Image, ImageDraw, ImageFont
|
13 |
+
import matplotlib.pyplot as plt
|
14 |
+
import matplotlib.patches as patches
|
15 |
+
from unittest.mock import patch
|
16 |
+
|
17 |
+
import argparse
|
18 |
+
import huggingface_hub
|
19 |
+
import onnxruntime as rt
|
20 |
+
import pandas as pd
|
21 |
+
import traceback
|
22 |
+
import tempfile
|
23 |
+
import zipfile
|
24 |
+
import re
|
25 |
+
import ast
|
26 |
+
import time
|
27 |
+
from datetime import datetime, timezone
|
28 |
+
from collections import defaultdict
|
29 |
+
from classifyTags import classify_tags
|
30 |
+
# Add scheduler code here
|
31 |
+
from apscheduler.schedulers.background import BackgroundScheduler
|
32 |
+
|
33 |
+
os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
|
34 |
+
def fixed_get_imports(filename: str | os.PathLike) -> list[str]:
|
35 |
+
"""Work around for https://huggingface.co/microsoft/phi-1_5/discussions/72."""
|
36 |
+
if not str(filename).endswith("/modeling_florence2.py"):
|
37 |
+
return get_imports(filename)
|
38 |
+
imports = get_imports(filename)
|
39 |
+
if "flash_attn" in imports:
|
40 |
+
imports.remove("flash_attn")
|
41 |
+
return imports
|
42 |
+
|
43 |
+
@spaces.GPU
|
44 |
+
def get_device_type():
|
45 |
+
import torch
|
46 |
+
if torch.cuda.is_available():
|
47 |
+
return "cuda"
|
48 |
+
else:
|
49 |
+
if (torch.backends.mps.is_available() and torch.backends.mps.is_built()):
|
50 |
+
return "mps"
|
51 |
+
else:
|
52 |
+
return "cpu"
|
53 |
+
|
54 |
+
model_id = 'MiaoshouAI/Florence-2-base-PromptGen-v2.0'
|
55 |
+
|
56 |
+
import subprocess
|
57 |
+
device = get_device_type()
|
58 |
+
if (device == "cuda"):
|
59 |
+
subprocess.run('pip install flash-attn --no-build-isolation', env={'FLASH_ATTENTION_SKIP_CUDA_BUILD': "TRUE"}, shell=True)
|
60 |
+
model = AutoModelForCausalLM.from_pretrained("MiaoshouAI/Florence-2-base-PromptGen-v2.0", trust_remote_code=True)
|
61 |
+
processor = AutoProcessor.from_pretrained("MiaoshouAI/Florence-2-base-PromptGen-v2.0", trust_remote_code=True)
|
62 |
+
model.to(device)
|
63 |
+
else:
|
64 |
+
#https://huggingface.co/microsoft/Florence-2-base-ft/discussions/4
|
65 |
+
with patch("transformers.dynamic_module_utils.get_imports", fixed_get_imports):
|
66 |
+
model = AutoModelForCausalLM.from_pretrained("MiaoshouAI/Florence-2-base-PromptGen-v2.0", trust_remote_code=True)
|
67 |
+
processor = AutoProcessor.from_pretrained("MiaoshouAI/Florence-2-base-PromptGen-v2.0", trust_remote_code=True)
|
68 |
+
model.to(device)
|
69 |
+
|
70 |
+
TITLE = "Multi-Tagger"
|
71 |
+
DESCRIPTION = """
|
72 |
+
Multi-Tagger is a powerful and versatile application that integrates two cutting-edge models: Waifu Diffusion and Florence 2. This app is designed to provide comprehensive image analysis and captioning capabilities, making it a valuable tool for AI artists, researchers, and enthusiasts.
|
73 |
+
|
74 |
+
Features:
|
75 |
+
- Supports batch processing of multiple images.
|
76 |
+
- Tags images with multiple categories: general tags, character tags, and ratings.
|
77 |
+
- Tags are categorized into groups (e.g., general, characters, ratings).
|
78 |
+
- Displays categorized tags in a structured format.
|
79 |
+
- Integrates Llama3 models to reorganize the tags into a readable English article.
|
80 |
+
- Includes a separate tab for image captioning using Florence 2.
|
81 |
+
- Florence 2 supports CUDA, MPS or CPU if one of them is available.
|
82 |
+
- Supports various captioning tasks (e.g., Caption, Detailed Caption, Object Detection).
|
83 |
+
- Displays output text and images for tasks that generate visual outputs.
|
84 |
+
- The space will restart every 2 days to ensure stability and performance. It uses a background scheduler to handle the restart process.
|
85 |
+
|
86 |
+
Example image by [me.](https://huggingface.co/Werli)
|
87 |
+
"""
|
88 |
+
colormap = ['blue','orange','green','purple','brown','pink','gray','olive','cyan','red',
|
89 |
+
'lime','indigo','violet','aqua','magenta','coral','gold','tan','skyblue']
|
90 |
+
|
91 |
+
# Dataset v3 series of models:
|
92 |
+
SWINV2_MODEL_DSV3_REPO = "SmilingWolf/wd-swinv2-tagger-v3"
|
93 |
+
CONV_MODEL_DSV3_REPO = "SmilingWolf/wd-convnext-tagger-v3"
|
94 |
+
VIT_MODEL_DSV3_REPO = "SmilingWolf/wd-vit-tagger-v3"
|
95 |
+
VIT_LARGE_MODEL_DSV3_REPO = "SmilingWolf/wd-vit-large-tagger-v3"
|
96 |
+
EVA02_LARGE_MODEL_DSV3_REPO = "SmilingWolf/wd-eva02-large-tagger-v3"
|
97 |
+
|
98 |
+
# Dataset v2 series of models:
|
99 |
+
MOAT_MODEL_DSV2_REPO = "SmilingWolf/wd-v1-4-moat-tagger-v2"
|
100 |
+
SWIN_MODEL_DSV2_REPO = "SmilingWolf/wd-v1-4-swinv2-tagger-v2"
|
101 |
+
CONV_MODEL_DSV2_REPO = "SmilingWolf/wd-v1-4-convnext-tagger-v2"
|
102 |
+
CONV2_MODEL_DSV2_REPO = "SmilingWolf/wd-v1-4-convnextv2-tagger-v2"
|
103 |
+
VIT_MODEL_DSV2_REPO = "SmilingWolf/wd-v1-4-vit-tagger-v2"
|
104 |
+
|
105 |
+
# IdolSankaku series of models:
|
106 |
+
EVA02_LARGE_MODEL_IS_DSV1_REPO = "deepghs/idolsankaku-eva02-large-tagger-v1"
|
107 |
+
SWINV2_MODEL_IS_DSV1_REPO = "deepghs/idolsankaku-swinv2-tagger-v1"
|
108 |
+
|
109 |
+
# Files to download from the repos
|
110 |
+
MODEL_FILENAME = "model.onnx"
|
111 |
+
LABEL_FILENAME = "selected_tags.csv"
|
112 |
+
|
113 |
+
# LLAMA model
|
114 |
+
META_LLAMA_3_3B_REPO = "jncraton/Llama-3.2-3B-Instruct-ct2-int8"
|
115 |
+
META_LLAMA_3_8B_REPO = "avans06/Meta-Llama-3.2-8B-Instruct-ct2-int8_float16"
|
116 |
+
|
117 |
+
# https://github.com/toriato/stable-diffusion-webui-wd14-tagger/blob/a9eacb1eff904552d3012babfa28b57e1d3e295c/tagger/ui.py#L368
|
118 |
+
kaomojis = [
|
119 |
+
"0_0",
|
120 |
+
"(o)_(o)",
|
121 |
+
"+_+",
|
122 |
+
"+_-",
|
123 |
+
"._.",
|
124 |
+
"<o>_<o>",
|
125 |
+
"<|>_<|>",
|
126 |
+
"=_=",
|
127 |
+
">_<",
|
128 |
+
"3_3",
|
129 |
+
"6_9",
|
130 |
+
">_o",
|
131 |
+
"@_@",
|
132 |
+
"^_^",
|
133 |
+
"o_o",
|
134 |
+
"u_u",
|
135 |
+
"x_x",
|
136 |
+
"|_|",
|
137 |
+
"||_||",
|
138 |
+
]
|
139 |
+
def parse_args() -> argparse.Namespace:
|
140 |
+
parser = argparse.ArgumentParser()
|
141 |
+
parser.add_argument("--score-slider-step", type=float, default=0.05)
|
142 |
+
parser.add_argument("--score-general-threshold", type=float, default=0.35)
|
143 |
+
parser.add_argument("--score-character-threshold", type=float, default=0.85)
|
144 |
+
parser.add_argument("--share", action="store_true")
|
145 |
+
return parser.parse_args()
|
146 |
+
def load_labels(dataframe) -> list[str]:
|
147 |
+
name_series = dataframe["name"]
|
148 |
+
name_series = name_series.map(
|
149 |
+
lambda x: x.replace("_", " ") if x not in kaomojis else x
|
150 |
+
)
|
151 |
+
tag_names = name_series.tolist()
|
152 |
+
|
153 |
+
rating_indexes = list(np.where(dataframe["category"] == 9)[0])
|
154 |
+
general_indexes = list(np.where(dataframe["category"] == 0)[0])
|
155 |
+
character_indexes = list(np.where(dataframe["category"] == 4)[0])
|
156 |
+
return tag_names, rating_indexes, general_indexes, character_indexes
|
157 |
+
def mcut_threshold(probs):
|
158 |
+
"""
|
159 |
+
Maximum Cut Thresholding (MCut)
|
160 |
+
Largeron, C., Moulin, C., & Gery, M. (2012). MCut: A Thresholding Strategy
|
161 |
+
for Multi-label Classification. In 11th International Symposium, IDA 2012
|
162 |
+
(pp. 172-183).
|
163 |
+
"""
|
164 |
+
sorted_probs = probs[probs.argsort()[::-1]]
|
165 |
+
difs = sorted_probs[:-1] - sorted_probs[1:]
|
166 |
+
t = difs.argmax()
|
167 |
+
thresh = (sorted_probs[t] + sorted_probs[t + 1]) / 2
|
168 |
+
return thresh
|
169 |
+
class Timer:
|
170 |
+
def __init__(self):
|
171 |
+
self.start_time = time.perf_counter() # Record the start time
|
172 |
+
self.checkpoints = [("Start", self.start_time)] # Store checkpoints
|
173 |
+
|
174 |
+
def checkpoint(self, label="Checkpoint"):
|
175 |
+
"""Record a checkpoint with a given label."""
|
176 |
+
now = time.perf_counter()
|
177 |
+
self.checkpoints.append((label, now))
|
178 |
+
|
179 |
+
def report(self, is_clear_checkpoints = True):
|
180 |
+
# Determine the max label width for alignment
|
181 |
+
max_label_length = max(len(label) for label, _ in self.checkpoints)
|
182 |
+
|
183 |
+
prev_time = self.checkpoints[0][1]
|
184 |
+
for label, curr_time in self.checkpoints[1:]:
|
185 |
+
elapsed = curr_time - prev_time
|
186 |
+
print(f"{label.ljust(max_label_length)}: {elapsed:.3f} seconds")
|
187 |
+
prev_time = curr_time
|
188 |
+
|
189 |
+
if is_clear_checkpoints:
|
190 |
+
self.checkpoints.clear()
|
191 |
+
self.checkpoint() # Store checkpoints
|
192 |
+
|
193 |
+
def report_all(self):
|
194 |
+
"""Print all recorded checkpoints and total execution time with aligned formatting."""
|
195 |
+
print("\n> Execution Time Report:")
|
196 |
+
|
197 |
+
# Determine the max label width for alignment
|
198 |
+
max_label_length = max(len(label) for label, _ in self.checkpoints) if len(self.checkpoints) > 0 else 0
|
199 |
+
|
200 |
+
prev_time = self.start_time
|
201 |
+
for label, curr_time in self.checkpoints[1:]:
|
202 |
+
elapsed = curr_time - prev_time
|
203 |
+
print(f"{label.ljust(max_label_length)}: {elapsed:.3f} seconds")
|
204 |
+
prev_time = curr_time
|
205 |
+
|
206 |
+
total_time = self.checkpoints[-1][1] - self.start_time
|
207 |
+
print(f"{'Total Execution Time'.ljust(max_label_length)}: {total_time:.3f} seconds\n")
|
208 |
+
|
209 |
+
self.checkpoints.clear()
|
210 |
+
|
211 |
+
def restart(self):
|
212 |
+
self.start_time = time.perf_counter() # Record the start time
|
213 |
+
self.checkpoints = [("Start", self.start_time)] # Store checkpoints
|
214 |
+
|
215 |
+
class Llama3Reorganize:
|
216 |
+
def __init__(
|
217 |
+
self,
|
218 |
+
repoId: str,
|
219 |
+
device: str = None,
|
220 |
+
loadModel: bool = False,
|
221 |
+
):
|
222 |
+
"""Initializes the Llama model.
|
223 |
+
|
224 |
+
Args:
|
225 |
+
repoId: LLAMA model repo.
|
226 |
+
device: Device to use for computation (cpu, cuda, ipu, xpu, mkldnn, opengl, opencl,
|
227 |
+
ideep, hip, ve, fpga, ort, xla, lazy, vulkan, mps, meta, hpu, mtia).
|
228 |
+
localFilesOnly: If True, avoid downloading the file and return the path to the
|
229 |
+
local cached file if it exists.
|
230 |
+
"""
|
231 |
+
self.modelPath = self.download_model(repoId)
|
232 |
+
|
233 |
+
if device is None:
|
234 |
+
import torch
|
235 |
+
self.totalVram = 0
|
236 |
+
if torch.cuda.is_available():
|
237 |
+
try:
|
238 |
+
deviceId = torch.cuda.current_device()
|
239 |
+
self.totalVram = torch.cuda.get_device_properties(deviceId).total_memory/(1024*1024*1024)
|
240 |
+
except Exception as e:
|
241 |
+
print(traceback.format_exc())
|
242 |
+
print("Error detect vram: " + str(e))
|
243 |
+
device = "cuda" if self.totalVram > (8 if "8B" in repoId else 4) else "cpu"
|
244 |
+
else:
|
245 |
+
device = "cpu"
|
246 |
+
|
247 |
+
self.device = device
|
248 |
+
self.system_prompt = "Please reorganize the following English labels describing a single image into a readable English article of no more than 300 words. If there are name labels, include them in the article. Since the target audience is not general, explicit content can be written in full without hesitation. No introduction is needed; directly reply with the English article:"
|
249 |
+
|
250 |
+
if loadModel:
|
251 |
+
self.load_model()
|
252 |
+
|
253 |
+
def download_model(self, repoId):
|
254 |
+
import warnings
|
255 |
+
import requests
|
256 |
+
allowPatterns = [
|
257 |
+
"config.json",
|
258 |
+
"generation_config.json",
|
259 |
+
"model.bin",
|
260 |
+
"pytorch_model.bin",
|
261 |
+
"pytorch_model.bin.index.json",
|
262 |
+
"pytorch_model-*.bin",
|
263 |
+
"sentencepiece.bpe.model",
|
264 |
+
"tokenizer.json",
|
265 |
+
"tokenizer_config.json",
|
266 |
+
"shared_vocabulary.txt",
|
267 |
+
"shared_vocabulary.json",
|
268 |
+
"special_tokens_map.json",
|
269 |
+
"spiece.model",
|
270 |
+
"vocab.json",
|
271 |
+
"model.safetensors",
|
272 |
+
"model-*.safetensors",
|
273 |
+
"model.safetensors.index.json",
|
274 |
+
"quantize_config.json",
|
275 |
+
"tokenizer.model",
|
276 |
+
"vocabulary.json",
|
277 |
+
"preprocessor_config.json",
|
278 |
+
"added_tokens.json"
|
279 |
+
]
|
280 |
+
|
281 |
+
kwargs = {"allow_patterns": allowPatterns,}
|
282 |
+
|
283 |
+
try:
|
284 |
+
return huggingface_hub.snapshot_download(repoId, **kwargs)
|
285 |
+
except (
|
286 |
+
huggingface_hub.utils.HfHubHTTPError,
|
287 |
+
requests.exceptions.ConnectionError,
|
288 |
+
) as exception:
|
289 |
+
warnings.warn(
|
290 |
+
"An error occured while synchronizing the model %s from the Hugging Face Hub:\n%s",
|
291 |
+
repoId,
|
292 |
+
exception,
|
293 |
+
)
|
294 |
+
warnings.warn(
|
295 |
+
"Trying to load the model directly from the local cache, if it exists."
|
296 |
+
)
|
297 |
+
|
298 |
+
kwargs["local_files_only"] = True
|
299 |
+
return huggingface_hub.snapshot_download(repoId, **kwargs)
|
300 |
+
|
301 |
+
|
302 |
+
def load_model(self):
|
303 |
+
import ctranslate2
|
304 |
+
import transformers
|
305 |
+
try:
|
306 |
+
print('\n\nLoading model: %s\n\n' % self.modelPath)
|
307 |
+
kwargsTokenizer = {"pretrained_model_name_or_path": self.modelPath}
|
308 |
+
kwargsModel = {"device": self.device, "model_path": self.modelPath, "compute_type": "auto"}
|
309 |
+
self.roleSystem = {"role": "system", "content": self.system_prompt}
|
310 |
+
self.Model = ctranslate2.Generator(**kwargsModel)
|
311 |
+
|
312 |
+
self.Tokenizer = transformers.AutoTokenizer.from_pretrained(**kwargsTokenizer)
|
313 |
+
self.terminators = [self.Tokenizer.eos_token_id, self.Tokenizer.convert_tokens_to_ids("<|eot_id|>")]
|
314 |
+
|
315 |
+
except Exception as e:
|
316 |
+
self.release_vram()
|
317 |
+
raise e
|
318 |
+
|
319 |
+
|
320 |
+
def release_vram(self):
|
321 |
+
try:
|
322 |
+
import torch
|
323 |
+
if torch.cuda.is_available():
|
324 |
+
if getattr(self, "Model", None) is not None and getattr(self.Model, "unload_model", None) is not None:
|
325 |
+
self.Model.unload_model()
|
326 |
+
|
327 |
+
if getattr(self, "Tokenizer", None) is not None:
|
328 |
+
del self.Tokenizer
|
329 |
+
if getattr(self, "Model", None) is not None:
|
330 |
+
del self.Model
|
331 |
+
import gc
|
332 |
+
gc.collect()
|
333 |
+
try:
|
334 |
+
torch.cuda.empty_cache()
|
335 |
+
except Exception as e:
|
336 |
+
print(traceback.format_exc())
|
337 |
+
print("\tcuda empty cache, error: " + str(e))
|
338 |
+
print("release vram end.")
|
339 |
+
except Exception as e:
|
340 |
+
print(traceback.format_exc())
|
341 |
+
print("Error release vram: " + str(e))
|
342 |
+
|
343 |
+
def reorganize(self, text: str, max_length: int = 400):
|
344 |
+
output = None
|
345 |
+
result = None
|
346 |
+
try:
|
347 |
+
input_ids = self.Tokenizer.apply_chat_template([self.roleSystem, {"role": "user", "content": text + "\n\nHere's the reorganized English article:"}], tokenize=False, add_generation_prompt=True)
|
348 |
+
source = self.Tokenizer.convert_ids_to_tokens(self.Tokenizer.encode(input_ids))
|
349 |
+
output = self.Model.generate_batch([source], max_length=max_length, max_batch_size=2, no_repeat_ngram_size=3, beam_size=2, sampling_temperature=0.7, sampling_topp=0.9, include_prompt_in_result=False, end_token=self.terminators)
|
350 |
+
target = output[0]
|
351 |
+
result = self.Tokenizer.decode(target.sequences_ids[0])
|
352 |
+
|
353 |
+
if len(result) > 2:
|
354 |
+
if result[0] == "\"" and result[len(result) - 1] == "\"":
|
355 |
+
result = result[1:-1]
|
356 |
+
elif result[0] == "'" and result[len(result) - 1] == "'":
|
357 |
+
result = result[1:-1]
|
358 |
+
elif result[0] == "「" and result[len(result) - 1] == "」":
|
359 |
+
result = result[1:-1]
|
360 |
+
elif result[0] == "『" and result[len(result) - 1] == "』":
|
361 |
+
result = result[1:-1]
|
362 |
+
except Exception as e:
|
363 |
+
print(traceback.format_exc())
|
364 |
+
print("Error reorganize text: " + str(e))
|
365 |
+
|
366 |
+
return result
|
367 |
+
|
368 |
+
|
369 |
+
class Predictor:
|
370 |
+
def __init__(self):
|
371 |
+
self.model_target_size = None
|
372 |
+
self.last_loaded_repo = None
|
373 |
+
def download_model(self, model_repo):
|
374 |
+
csv_path = huggingface_hub.hf_hub_download(
|
375 |
+
model_repo,
|
376 |
+
LABEL_FILENAME,
|
377 |
+
)
|
378 |
+
model_path = huggingface_hub.hf_hub_download(
|
379 |
+
model_repo,
|
380 |
+
MODEL_FILENAME,
|
381 |
+
)
|
382 |
+
return csv_path, model_path
|
383 |
+
def load_model(self, model_repo):
|
384 |
+
if model_repo == self.last_loaded_repo:
|
385 |
+
return
|
386 |
+
|
387 |
+
csv_path, model_path = self.download_model(model_repo)
|
388 |
+
|
389 |
+
tags_df = pd.read_csv(csv_path)
|
390 |
+
sep_tags = load_labels(tags_df)
|
391 |
+
|
392 |
+
self.tag_names = sep_tags[0]
|
393 |
+
self.rating_indexes = sep_tags[1]
|
394 |
+
self.general_indexes = sep_tags[2]
|
395 |
+
self.character_indexes = sep_tags[3]
|
396 |
+
|
397 |
+
model = rt.InferenceSession(model_path)
|
398 |
+
_, height, width, _ = model.get_inputs()[0].shape
|
399 |
+
self.model_target_size = height
|
400 |
+
|
401 |
+
self.last_loaded_repo = model_repo
|
402 |
+
self.model = model
|
403 |
+
def prepare_image(self, path):
|
404 |
+
image = Image.open(path)
|
405 |
+
image = image.convert("RGBA")
|
406 |
+
target_size = self.model_target_size
|
407 |
+
|
408 |
+
canvas = Image.new("RGBA", image.size, (255, 255, 255))
|
409 |
+
canvas.alpha_composite(image)
|
410 |
+
image = canvas.convert("RGB")
|
411 |
+
|
412 |
+
# Pad image to square
|
413 |
+
image_shape = image.size
|
414 |
+
max_dim = max(image_shape)
|
415 |
+
pad_left = (max_dim - image_shape[0]) // 2
|
416 |
+
pad_top = (max_dim - image_shape[1]) // 2
|
417 |
+
|
418 |
+
padded_image = Image.new("RGB", (max_dim, max_dim), (255, 255, 255))
|
419 |
+
padded_image.paste(image, (pad_left, pad_top))
|
420 |
+
|
421 |
+
# Resize
|
422 |
+
if max_dim != target_size:
|
423 |
+
padded_image = padded_image.resize(
|
424 |
+
(target_size, target_size),
|
425 |
+
Image.BICUBIC,
|
426 |
+
)
|
427 |
+
# Convert to numpy array
|
428 |
+
image_array = np.asarray(padded_image, dtype=np.float32)
|
429 |
+
|
430 |
+
# Convert PIL-native RGB to BGR
|
431 |
+
image_array = image_array[:, :, ::-1]
|
432 |
+
|
433 |
+
return np.expand_dims(image_array, axis=0)
|
434 |
+
|
435 |
+
def create_file(self, text: str, directory: str, fileName: str) -> str:
|
436 |
+
# Write the text to a file
|
437 |
+
with open(os.path.join(directory, fileName), 'w+', encoding="utf-8") as file:
|
438 |
+
file.write(text)
|
439 |
+
|
440 |
+
return file.name
|
441 |
+
|
442 |
+
def predict(
|
443 |
+
self,
|
444 |
+
gallery,
|
445 |
+
model_repo,
|
446 |
+
general_thresh,
|
447 |
+
general_mcut_enabled,
|
448 |
+
character_thresh,
|
449 |
+
character_mcut_enabled,
|
450 |
+
characters_merge_enabled,
|
451 |
+
llama3_reorganize_model_repo,
|
452 |
+
additional_tags_prepend,
|
453 |
+
additional_tags_append,
|
454 |
+
tag_results,
|
455 |
+
progress=gr.Progress()
|
456 |
+
):
|
457 |
+
gallery_len = len(gallery)
|
458 |
+
print(f"Predict load model: {model_repo}, gallery length: {gallery_len}")
|
459 |
+
|
460 |
+
timer = Timer() # Create a timer
|
461 |
+
progressRatio = 0.5 if llama3_reorganize_model_repo else 1
|
462 |
+
progressTotal = gallery_len + 1
|
463 |
+
current_progress = 0
|
464 |
+
|
465 |
+
self.load_model(model_repo)
|
466 |
+
current_progress += progressRatio/progressTotal;
|
467 |
+
progress(current_progress, desc="Initialize wd model finished")
|
468 |
+
timer.checkpoint(f"Initialize wd model")
|
469 |
+
|
470 |
+
# Result
|
471 |
+
txt_infos = []
|
472 |
+
output_dir = tempfile.mkdtemp()
|
473 |
+
if not os.path.exists(output_dir):
|
474 |
+
os.makedirs(output_dir)
|
475 |
+
|
476 |
+
sorted_general_strings = ""
|
477 |
+
rating = None
|
478 |
+
character_res = None
|
479 |
+
general_res = None
|
480 |
+
|
481 |
+
if llama3_reorganize_model_repo:
|
482 |
+
print(f"Llama3 reorganize load model {llama3_reorganize_model_repo}")
|
483 |
+
llama3_reorganize = Llama3Reorganize(llama3_reorganize_model_repo, loadModel=True)
|
484 |
+
current_progress += progressRatio/progressTotal;
|
485 |
+
progress(current_progress, desc="Initialize llama3 model finished")
|
486 |
+
timer.checkpoint(f"Initialize llama3 model")
|
487 |
+
|
488 |
+
timer.report()
|
489 |
+
|
490 |
+
prepend_list = [tag.strip() for tag in additional_tags_prepend.split(",") if tag.strip()]
|
491 |
+
append_list = [tag.strip() for tag in additional_tags_append.split(",") if tag.strip()]
|
492 |
+
if prepend_list and append_list:
|
493 |
+
append_list = [item for item in append_list if item not in prepend_list]
|
494 |
+
|
495 |
+
# Dictionary to track counters for each filename
|
496 |
+
name_counters = defaultdict(int)
|
497 |
+
# New code to create categorized output string
|
498 |
+
categorized_output_strings = []
|
499 |
+
for idx, value in enumerate(gallery):
|
500 |
+
try:
|
501 |
+
image_path = value[0]
|
502 |
+
image_name = os.path.splitext(os.path.basename(image_path))[0]
|
503 |
+
|
504 |
+
# Increment the counter for the current name
|
505 |
+
name_counters[image_name] += 1
|
506 |
+
|
507 |
+
if name_counters[image_name] > 1:
|
508 |
+
image_name = f"{image_name}_{name_counters[image_name]:02d}"
|
509 |
+
|
510 |
+
image = self.prepare_image(image_path)
|
511 |
+
|
512 |
+
input_name = self.model.get_inputs()[0].name
|
513 |
+
label_name = self.model.get_outputs()[0].name
|
514 |
+
print(f"Gallery {idx:02d}: Starting run wd model...")
|
515 |
+
preds = self.model.run([label_name], {input_name: image})[0]
|
516 |
+
|
517 |
+
labels = list(zip(self.tag_names, preds[0].astype(float)))
|
518 |
+
|
519 |
+
# First 4 labels are actually ratings: pick one with argmax
|
520 |
+
ratings_names = [labels[i] for i in self.rating_indexes]
|
521 |
+
rating = dict(ratings_names)
|
522 |
+
|
523 |
+
# Then we have general tags: pick any where prediction confidence > threshold
|
524 |
+
general_names = [labels[i] for i in self.general_indexes]
|
525 |
+
|
526 |
+
if general_mcut_enabled:
|
527 |
+
general_probs = np.array([x[1] for x in general_names])
|
528 |
+
general_thresh = mcut_threshold(general_probs)
|
529 |
+
|
530 |
+
general_res = [x for x in general_names if x[1] > general_thresh]
|
531 |
+
general_res = dict(general_res)
|
532 |
+
|
533 |
+
# Everything else is characters: pick any where prediction confidence > threshold
|
534 |
+
character_names = [labels[i] for i in self.character_indexes]
|
535 |
+
|
536 |
+
if character_mcut_enabled:
|
537 |
+
character_probs = np.array([x[1] for x in character_names])
|
538 |
+
character_thresh = mcut_threshold(character_probs)
|
539 |
+
character_thresh = max(0.15, character_thresh)
|
540 |
+
|
541 |
+
character_res = [x for x in character_names if x[1] > character_thresh]
|
542 |
+
character_res = dict(character_res)
|
543 |
+
character_list = list(character_res.keys())
|
544 |
+
|
545 |
+
sorted_general_list = sorted(
|
546 |
+
general_res.items(),
|
547 |
+
key=lambda x: x[1],
|
548 |
+
reverse=True,
|
549 |
+
)
|
550 |
+
sorted_general_list = [x[0] for x in sorted_general_list]
|
551 |
+
#Remove values from character_list that already exist in sorted_general_list
|
552 |
+
character_list = [item for item in character_list if item not in sorted_general_list]
|
553 |
+
#Remove values from sorted_general_list that already exist in prepend_list or append_list
|
554 |
+
if prepend_list:
|
555 |
+
sorted_general_list = [item for item in sorted_general_list if item not in prepend_list]
|
556 |
+
if append_list:
|
557 |
+
sorted_general_list = [item for item in sorted_general_list if item not in append_list]
|
558 |
+
|
559 |
+
sorted_general_list = prepend_list + sorted_general_list + append_list
|
560 |
+
|
561 |
+
sorted_general_strings = ", ".join((character_list if characters_merge_enabled else []) + sorted_general_list).replace("(", "\(").replace(")", "\)")
|
562 |
+
|
563 |
+
classified_tags, unclassified_tags = classify_tags(sorted_general_list)
|
564 |
+
|
565 |
+
# Create a single string of all categorized tags
|
566 |
+
categorized_output_string = ', '.join([', '.join(tags) for tags in classified_tags.values()])
|
567 |
+
categorized_output_strings.append(categorized_output_string)
|
568 |
+
|
569 |
+
current_progress += progressRatio/progressTotal;
|
570 |
+
progress(current_progress, desc=f"image{idx:02d}, predict finished")
|
571 |
+
timer.checkpoint(f"image{idx:02d}, predict finished")
|
572 |
+
|
573 |
+
if llama3_reorganize_model_repo:
|
574 |
+
print(f"Starting reorganize with llama3...")
|
575 |
+
reorganize_strings = llama3_reorganize.reorganize(sorted_general_strings)
|
576 |
+
reorganize_strings = re.sub(r" *Title: *", "", reorganize_strings)
|
577 |
+
reorganize_strings = re.sub(r"\n+", ",", reorganize_strings)
|
578 |
+
reorganize_strings = re.sub(r",,+", ",", reorganize_strings)
|
579 |
+
sorted_general_strings += "," + reorganize_strings
|
580 |
+
|
581 |
+
current_progress += progressRatio/progressTotal;
|
582 |
+
progress(current_progress, desc=f"image{idx:02d}, llama3 reorganize finished")
|
583 |
+
timer.checkpoint(f"image{idx:02d}, llama3 reorganize finished")
|
584 |
+
|
585 |
+
txt_file = self.create_file(sorted_general_strings, output_dir, image_name + ".txt")
|
586 |
+
txt_infos.append({"path":txt_file, "name": image_name + ".txt"})
|
587 |
+
|
588 |
+
tag_results[image_path] = { "strings": sorted_general_strings, "classified_tags": classified_tags, "rating": rating, "character_res": character_res, "general_res": general_res, "unclassified_tags": unclassified_tags }
|
589 |
+
timer.report()
|
590 |
+
except Exception as e:
|
591 |
+
print(traceback.format_exc())
|
592 |
+
print("Error predict: " + str(e))
|
593 |
+
# Result
|
594 |
+
download = []
|
595 |
+
if txt_infos is not None and len(txt_infos) > 0:
|
596 |
+
downloadZipPath = os.path.join(output_dir, "images-tagger-" + datetime.now().strftime("%Y%m%d-%H%M%S") + ".zip")
|
597 |
+
with zipfile.ZipFile(downloadZipPath, 'w', zipfile.ZIP_DEFLATED) as taggers_zip:
|
598 |
+
for info in txt_infos:
|
599 |
+
# Get file name from lookup
|
600 |
+
taggers_zip.write(info["path"], arcname=info["name"])
|
601 |
+
download.append(downloadZipPath)
|
602 |
+
|
603 |
+
if llama3_reorganize_model_repo:
|
604 |
+
llama3_reorganize.release_vram()
|
605 |
+
del llama3_reorganize
|
606 |
+
|
607 |
+
progress(1, desc=f"Predict completed")
|
608 |
+
timer.report_all() # Print all recorded times
|
609 |
+
print("Predict is complete.")
|
610 |
+
|
611 |
+
# Collect all categorized output strings into a single string
|
612 |
+
final_categorized_output = ', '.join(categorized_output_strings)
|
613 |
+
|
614 |
+
return download, sorted_general_strings, classified_tags, rating, character_res, general_res, unclassified_tags, tag_results, final_categorized_output
|
615 |
+
# END
|
616 |
+
|
617 |
+
def get_selection_from_gallery(gallery: list, tag_results: dict, selected_state: gr.SelectData):
|
618 |
+
if not selected_state:
|
619 |
+
return selected_state
|
620 |
+
|
621 |
+
tag_result = { "strings": "", "classified_tags": "{}", "rating": "", "character_res": "", "general_res": "", "unclassified_tags": "{}" }
|
622 |
+
if selected_state.value["image"]["path"] in tag_results:
|
623 |
+
tag_result = tag_results[selected_state.value["image"]["path"]]
|
624 |
+
|
625 |
+
return (selected_state.value["image"]["path"], selected_state.value["caption"]), tag_result["strings"], tag_result["classified_tags"], tag_result["rating"], tag_result["character_res"], tag_result["general_res"], tag_result["unclassified_tags"]
|
626 |
+
|
627 |
+
def append_gallery(gallery: list, image: str):
|
628 |
+
if gallery is None:
|
629 |
+
gallery = []
|
630 |
+
if not image:
|
631 |
+
return gallery, None
|
632 |
+
|
633 |
+
gallery.append(image)
|
634 |
+
|
635 |
+
return gallery, None
|
636 |
+
|
637 |
+
|
638 |
+
def extend_gallery(gallery: list, images):
|
639 |
+
if gallery is None:
|
640 |
+
gallery = []
|
641 |
+
if not images:
|
642 |
+
return gallery
|
643 |
+
|
644 |
+
# Combine the new images with the existing gallery images
|
645 |
+
gallery.extend(images)
|
646 |
+
|
647 |
+
return gallery
|
648 |
+
|
649 |
+
def remove_image_from_gallery(gallery: list, selected_image: str):
|
650 |
+
if not gallery or not selected_image:
|
651 |
+
return gallery
|
652 |
+
|
653 |
+
selected_image = ast.literal_eval(selected_image) #Use ast.literal_eval to parse text into a tuple.
|
654 |
+
# Remove the selected image from the gallery
|
655 |
+
if selected_image in gallery:
|
656 |
+
gallery.remove(selected_image)
|
657 |
+
return gallery
|
658 |
+
|
659 |
+
# END
|
660 |
+
|
661 |
+
def fig_to_pil(fig):
|
662 |
+
buf = io.BytesIO()
|
663 |
+
fig.savefig(buf, format='png')
|
664 |
+
buf.seek(0)
|
665 |
+
return Image.open(buf)
|
666 |
+
|
667 |
+
@spaces.GPU
|
668 |
+
def run_example(task_prompt, image, text_input=None):
|
669 |
+
if text_input is None:
|
670 |
+
prompt = task_prompt
|
671 |
+
else:
|
672 |
+
prompt = task_prompt + text_input
|
673 |
+
inputs = processor(text=prompt, images=image, return_tensors="pt").to(device)
|
674 |
+
generated_ids = model.generate(
|
675 |
+
input_ids=inputs["input_ids"],
|
676 |
+
pixel_values=inputs["pixel_values"],
|
677 |
+
max_new_tokens=1024,
|
678 |
+
early_stopping=False,
|
679 |
+
do_sample=False,
|
680 |
+
num_beams=3,
|
681 |
+
)
|
682 |
+
generated_text = processor.batch_decode(generated_ids, skip_special_tokens=False)[0]
|
683 |
+
parsed_answer = processor.post_process_generation(
|
684 |
+
generated_text,
|
685 |
+
task=task_prompt,
|
686 |
+
image_size=(image.width, image.height)
|
687 |
+
)
|
688 |
+
return parsed_answer
|
689 |
+
|
690 |
+
def plot_bbox(image, data):
|
691 |
+
fig, ax = plt.subplots()
|
692 |
+
ax.imshow(image)
|
693 |
+
for bbox, label in zip(data['bboxes'], data['labels']):
|
694 |
+
x1, y1, x2, y2 = bbox
|
695 |
+
rect = patches.Rectangle((x1, y1), x2-x1, y2-y1, linewidth=1, edgecolor='r', facecolor='none')
|
696 |
+
ax.add_patch(rect)
|
697 |
+
plt.text(x1, y1, label, color='white', fontsize=8, bbox=dict(facecolor='red', alpha=0.5))
|
698 |
+
ax.axis('off')
|
699 |
+
return fig
|
700 |
+
|
701 |
+
def draw_polygons(image, prediction, fill_mask=False):
|
702 |
+
draw = ImageDraw.Draw(image)
|
703 |
+
scale = 1
|
704 |
+
for polygons, label in zip(prediction['polygons'], prediction['labels']):
|
705 |
+
color = random.choice(colormap)
|
706 |
+
fill_color = random.choice(colormap) if fill_mask else None
|
707 |
+
for _polygon in polygons:
|
708 |
+
_polygon = np.array(_polygon).reshape(-1, 2)
|
709 |
+
if len(_polygon) < 3:
|
710 |
+
print('Invalid polygon:', _polygon)
|
711 |
+
continue
|
712 |
+
_polygon = (_polygon * scale).reshape(-1).tolist()
|
713 |
+
if fill_mask:
|
714 |
+
draw.polygon(_polygon, outline=color, fill=fill_color)
|
715 |
+
else:
|
716 |
+
draw.polygon(_polygon, outline=color)
|
717 |
+
draw.text((_polygon[0] + 8, _polygon[1] + 2), label, fill=color)
|
718 |
+
return image
|
719 |
+
|
720 |
+
def convert_to_od_format(data):
|
721 |
+
bboxes = data.get('bboxes', [])
|
722 |
+
labels = data.get('bboxes_labels', [])
|
723 |
+
od_results = {
|
724 |
+
'bboxes': bboxes,
|
725 |
+
'labels': labels
|
726 |
+
}
|
727 |
+
return od_results
|
728 |
+
|
729 |
+
def draw_ocr_bboxes(image, prediction):
|
730 |
+
scale = 1
|
731 |
+
draw = ImageDraw.Draw(image)
|
732 |
+
bboxes, labels = prediction['quad_boxes'], prediction['labels']
|
733 |
+
for box, label in zip(bboxes, labels):
|
734 |
+
color = random.choice(colormap)
|
735 |
+
new_box = (np.array(box) * scale).tolist()
|
736 |
+
draw.polygon(new_box, width=3, outline=color)
|
737 |
+
draw.text((new_box[0]+8, new_box[1]+2),
|
738 |
+
"{}".format(label),
|
739 |
+
align="right",
|
740 |
+
fill=color)
|
741 |
+
return image
|
742 |
+
|
743 |
+
def convert_to_od_format(data):
|
744 |
+
bboxes = data.get('bboxes', [])
|
745 |
+
labels = data.get('bboxes_labels', [])
|
746 |
+
od_results = {
|
747 |
+
'bboxes': bboxes,
|
748 |
+
'labels': labels
|
749 |
+
}
|
750 |
+
return od_results
|
751 |
+
|
752 |
+
def draw_ocr_bboxes(image, prediction):
|
753 |
+
scale = 1
|
754 |
+
draw = ImageDraw.Draw(image)
|
755 |
+
bboxes, labels = prediction['quad_boxes'], prediction['labels']
|
756 |
+
for box, label in zip(bboxes, labels):
|
757 |
+
color = random.choice(colormap)
|
758 |
+
new_box = (np.array(box) * scale).tolist()
|
759 |
+
draw.polygon(new_box, width=3, outline=color)
|
760 |
+
draw.text((new_box[0]+8, new_box[1]+2),
|
761 |
+
"{}".format(label),
|
762 |
+
align="right",
|
763 |
+
fill=color)
|
764 |
+
return image
|
765 |
+
def process_image(image, task_prompt, text_input=None):
|
766 |
+
# Test
|
767 |
+
if isinstance(image, str): # If image is a file path
|
768 |
+
image = Image.open(image) # Load image from file path
|
769 |
+
else: # If image is a NumPy array
|
770 |
+
image = Image.fromarray(image) # Convert NumPy array to PIL Image
|
771 |
+
if task_prompt == 'Caption':
|
772 |
+
task_prompt = '<CAPTION>'
|
773 |
+
results = run_example(task_prompt, image)
|
774 |
+
return results[task_prompt], None
|
775 |
+
elif task_prompt == 'Detailed Caption':
|
776 |
+
task_prompt = '<DETAILED_CAPTION>'
|
777 |
+
results = run_example(task_prompt, image)
|
778 |
+
return results[task_prompt], None
|
779 |
+
elif task_prompt == 'More Detailed Caption':
|
780 |
+
task_prompt = '<MORE_DETAILED_CAPTION>'
|
781 |
+
results = run_example(task_prompt, image)
|
782 |
+
return results[task_prompt], plot_bbox(image, results['<CAPTION_TO_PHRASE_GROUNDING>'])
|
783 |
+
elif task_prompt == 'Caption + Grounding':
|
784 |
+
task_prompt = '<CAPTION>'
|
785 |
+
results = run_example(task_prompt, image)
|
786 |
+
text_input = results[task_prompt]
|
787 |
+
task_prompt = '<CAPTION_TO_PHRASE_GROUNDING>'
|
788 |
+
results = run_example(task_prompt, image, text_input)
|
789 |
+
results['<CAPTION>'] = text_input
|
790 |
+
fig = plot_bbox(image, results['<CAPTION_TO_PHRASE_GROUNDING>'])
|
791 |
+
return results, fig_to_pil(fig)
|
792 |
+
elif task_prompt == 'Detailed Caption + Grounding':
|
793 |
+
task_prompt = '<DETAILED_CAPTION>'
|
794 |
+
results = run_example(task_prompt, image)
|
795 |
+
text_input = results[task_prompt]
|
796 |
+
task_prompt = '<CAPTION_TO_PHRASE_GROUNDING>'
|
797 |
+
results = run_example(task_prompt, image, text_input)
|
798 |
+
results['<DETAILED_CAPTION>'] = text_input
|
799 |
+
fig = plot_bbox(image, results['<CAPTION_TO_PHRASE_GROUNDING>'])
|
800 |
+
return results, fig_to_pil(fig)
|
801 |
+
elif task_prompt == 'More Detailed Caption + Grounding':
|
802 |
+
task_prompt = '<MORE_DETAILED_CAPTION>'
|
803 |
+
results = run_example(task_prompt, image)
|
804 |
+
text_input = results[task_prompt]
|
805 |
+
task_prompt = '<CAPTION_TO_PHRASE_GROUNDING>'
|
806 |
+
results = run_example(task_prompt, image, text_input)
|
807 |
+
results['<MORE_DETAILED_CAPTION>'] = text_input
|
808 |
+
fig = plot_bbox(image, results['<CAPTION_TO_PHRASE_GROUNDING>'])
|
809 |
+
return results, fig_to_pil(fig)
|
810 |
+
elif task_prompt == 'Object Detection':
|
811 |
+
task_prompt = '<OD>'
|
812 |
+
results = run_example(task_prompt, image)
|
813 |
+
fig = plot_bbox(image, results['<OD>'])
|
814 |
+
return results, fig_to_pil(fig)
|
815 |
+
elif task_prompt == 'Dense Region Caption':
|
816 |
+
task_prompt = '<DENSE_REGION_CAPTION>'
|
817 |
+
results = run_example(task_prompt, image)
|
818 |
+
fig = plot_bbox(image, results['<DENSE_REGION_CAPTION>'])
|
819 |
+
return results, fig_to_pil(fig)
|
820 |
+
elif task_prompt == 'Region Proposal':
|
821 |
+
task_prompt = '<REGION_PROPOSAL>'
|
822 |
+
results = run_example(task_prompt, image)
|
823 |
+
fig = plot_bbox(image, results['<REGION_PROPOSAL>'])
|
824 |
+
return results, fig_to_pil(fig)
|
825 |
+
elif task_prompt == 'Caption to Phrase Grounding':
|
826 |
+
task_prompt = '<CAPTION_TO_PHRASE_GROUNDING>'
|
827 |
+
results = run_example(task_prompt, image, text_input)
|
828 |
+
fig = plot_bbox(image, results['<CAPTION_TO_PHRASE_GROUNDING>'])
|
829 |
+
return results, fig_to_pil(fig)
|
830 |
+
elif task_prompt == 'Referring Expression Segmentation':
|
831 |
+
task_prompt = '<REFERRING_EXPRESSION_SEGMENTATION>'
|
832 |
+
results = run_example(task_prompt, image, text_input)
|
833 |
+
output_image = copy.deepcopy(image)
|
834 |
+
output_image = draw_polygons(output_image, results['<REFERRING_EXPRESSION_SEGMENTATION>'], fill_mask=True)
|
835 |
+
return results, output_image
|
836 |
+
elif task_prompt == 'Region to Segmentation':
|
837 |
+
task_prompt = '<REGION_TO_SEGMENTATION>'
|
838 |
+
results = run_example(task_prompt, image, text_input)
|
839 |
+
output_image = copy.deepcopy(image)
|
840 |
+
output_image = draw_polygons(output_image, results['<REGION_TO_SEGMENTATION>'], fill_mask=True)
|
841 |
+
return results, output_image
|
842 |
+
elif task_prompt == 'Open Vocabulary Detection':
|
843 |
+
task_prompt = '<OPEN_VOCABULARY_DETECTION>'
|
844 |
+
results = run_example(task_prompt, image, text_input)
|
845 |
+
bbox_results = convert_to_od_format(results['<OPEN_VOCABULARY_DETECTION>'])
|
846 |
+
fig = plot_bbox(image, bbox_results)
|
847 |
+
return results, fig_to_pil(fig)
|
848 |
+
elif task_prompt == 'Region to Category':
|
849 |
+
task_prompt = '<REGION_TO_CATEGORY>'
|
850 |
+
results = run_example(task_prompt, image, text_input)
|
851 |
+
return results, None
|
852 |
+
elif task_prompt == 'Region to Description':
|
853 |
+
task_prompt = '<REGION_TO_DESCRIPTION>'
|
854 |
+
results = run_example(task_prompt, image, text_input)
|
855 |
+
return results, None
|
856 |
+
elif task_prompt == 'OCR':
|
857 |
+
task_prompt = '<OCR>'
|
858 |
+
results = run_example(task_prompt, image)
|
859 |
+
return results, None
|
860 |
+
elif task_prompt == 'OCR with Region':
|
861 |
+
task_prompt = '<OCR_WITH_REGION>'
|
862 |
+
results = run_example(task_prompt, image)
|
863 |
+
output_image = copy.deepcopy(image)
|
864 |
+
output_image = draw_ocr_bboxes(output_image, results['<OCR_WITH_REGION>'])
|
865 |
+
return results, output_image
|
866 |
+
else:
|
867 |
+
return "", None # Return empty string and None for unknown task prompts
|
868 |
+
##############
|
869 |
+
# Custom CSS to set the height of the gr.Dropdown menu
|
870 |
+
css = """
|
871 |
+
div.progress-level div.progress-level-inner {
|
872 |
+
text-align: left !important;
|
873 |
+
width: 55.5% !important;
|
874 |
+
#output {
|
875 |
+
height: 500px;
|
876 |
+
overflow: auto;
|
877 |
+
border: 1px solid #ccc;
|
878 |
+
}
|
879 |
+
"""
|
880 |
+
single_task_list =[
|
881 |
+
'Caption', 'Detailed Caption', 'More Detailed Caption', 'Object Detection',
|
882 |
+
'Dense Region Caption', 'Region Proposal', 'Caption to Phrase Grounding',
|
883 |
+
'Referring Expression Segmentation', 'Region to Segmentation',
|
884 |
+
'Open Vocabulary Detection', 'Region to Category', 'Region to Description',
|
885 |
+
'OCR', 'OCR with Region'
|
886 |
+
]
|
887 |
+
cascaded_task_list =[
|
888 |
+
'Caption + Grounding', 'Detailed Caption + Grounding', 'More Detailed Caption + Grounding'
|
889 |
+
]
|
890 |
+
def update_task_dropdown(choice):
|
891 |
+
if choice == 'Cascaded task':
|
892 |
+
return gr.Dropdown(choices=cascaded_task_list, value='Caption + Grounding')
|
893 |
+
else:
|
894 |
+
return gr.Dropdown(choices=single_task_list, value='Caption')
|
895 |
+
|
896 |
+
args = parse_args()
|
897 |
+
|
898 |
+
predictor = Predictor()
|
899 |
+
|
900 |
+
dropdown_list = [
|
901 |
+
EVA02_LARGE_MODEL_DSV3_REPO,
|
902 |
+
SWINV2_MODEL_DSV3_REPO,
|
903 |
+
CONV_MODEL_DSV3_REPO,
|
904 |
+
VIT_MODEL_DSV3_REPO,
|
905 |
+
VIT_LARGE_MODEL_DSV3_REPO,
|
906 |
+
# ---
|
907 |
+
MOAT_MODEL_DSV2_REPO,
|
908 |
+
SWIN_MODEL_DSV2_REPO,
|
909 |
+
CONV_MODEL_DSV2_REPO,
|
910 |
+
CONV2_MODEL_DSV2_REPO,
|
911 |
+
VIT_MODEL_DSV2_REPO,
|
912 |
+
# ---
|
913 |
+
SWINV2_MODEL_IS_DSV1_REPO,
|
914 |
+
EVA02_LARGE_MODEL_IS_DSV1_REPO,
|
915 |
+
]
|
916 |
+
llama_list = [
|
917 |
+
META_LLAMA_3_3B_REPO,
|
918 |
+
META_LLAMA_3_8B_REPO,
|
919 |
+
]
|
920 |
+
|
921 |
+
# This is workaround will make the space restart every 2 days. (for test).
|
922 |
+
def _restart_space():
|
923 |
+
HF_TOKEN = os.getenv("HF_TOKEN")
|
924 |
+
if not HF_TOKEN:
|
925 |
+
raise ValueError("HF_TOKEN environment variable is not set.")
|
926 |
+
huggingface_hub.HfApi().restart_space(repo_id="Werli/Multi-Tagger", token=HF_TOKEN, factory_reboot=False)
|
927 |
+
scheduler = BackgroundScheduler()
|
928 |
+
# Add a job to restart the space every 2 days (172800 seconds)
|
929 |
+
restart_space_job = scheduler.add_job(_restart_space, "interval", seconds=172800)
|
930 |
+
# Start the scheduler
|
931 |
+
scheduler.start()
|
932 |
+
next_run_time_utc = restart_space_job.next_run_time.astimezone(timezone.utc)
|
933 |
+
NEXT_RESTART = f"Next Restart: {next_run_time_utc.strftime('%Y-%m-%d %H:%M:%S')} (UTC)"
|
934 |
+
|
935 |
+
# Using "reilnuud/polite" theme
|
936 |
+
with gr.Blocks(title=TITLE, css=css, theme="Werli/wd-tagger-images", fill_width=True) as demo:
|
937 |
+
gr.Markdown(value=f"<h1 style='text-align: center; margin-bottom: 1rem'>{TITLE}</h1>")
|
938 |
+
gr.Markdown(value=DESCRIPTION)
|
939 |
+
gr.Markdown(NEXT_RESTART)
|
940 |
+
with gr.Tab(label="Waifu Diffusion"):
|
941 |
+
with gr.Row():
|
942 |
+
with gr.Column():
|
943 |
+
submit = gr.Button(value="Submit", variant="primary", size="lg")
|
944 |
+
with gr.Column(variant="panel"):
|
945 |
+
# Create an Image component for uploading images
|
946 |
+
image_input = gr.Image(label="Upload an Image or clicking paste from clipboard button", type="filepath", sources=["upload", "clipboard"], height=150)
|
947 |
+
with gr.Row():
|
948 |
+
upload_button = gr.UploadButton("Upload multiple images", file_types=["image"], file_count="multiple", size="sm")
|
949 |
+
remove_button = gr.Button("Remove Selected Image", size="sm")
|
950 |
+
gallery = gr.Gallery(columns=5, rows=5, show_share_button=False, interactive=True, height="500px", label="Gallery that displaying a grid of images")
|
951 |
+
|
952 |
+
model_repo = gr.Dropdown(
|
953 |
+
dropdown_list,
|
954 |
+
value=EVA02_LARGE_MODEL_DSV3_REPO,
|
955 |
+
label="Model",
|
956 |
+
)
|
957 |
+
with gr.Row():
|
958 |
+
general_thresh = gr.Slider(
|
959 |
+
0,
|
960 |
+
1,
|
961 |
+
step=args.score_slider_step,
|
962 |
+
value=args.score_general_threshold,
|
963 |
+
label="General Tags Threshold",
|
964 |
+
scale=3,
|
965 |
+
)
|
966 |
+
general_mcut_enabled = gr.Checkbox(
|
967 |
+
value=False,
|
968 |
+
label="Use MCut threshold",
|
969 |
+
scale=1,
|
970 |
+
)
|
971 |
+
with gr.Row():
|
972 |
+
character_thresh = gr.Slider(
|
973 |
+
0,
|
974 |
+
1,
|
975 |
+
step=args.score_slider_step,
|
976 |
+
value=args.score_character_threshold,
|
977 |
+
label="Character Tags Threshold",
|
978 |
+
scale=3,
|
979 |
+
)
|
980 |
+
character_mcut_enabled = gr.Checkbox(
|
981 |
+
value=False,
|
982 |
+
label="Use MCut threshold",
|
983 |
+
scale=1,
|
984 |
+
)
|
985 |
+
with gr.Row():
|
986 |
+
characters_merge_enabled = gr.Checkbox(
|
987 |
+
value=True,
|
988 |
+
label="Merge characters into the string output",
|
989 |
+
scale=1,
|
990 |
+
)
|
991 |
+
with gr.Row():
|
992 |
+
llama3_reorganize_model_repo = gr.Dropdown(
|
993 |
+
[None] + llama_list,
|
994 |
+
value=None,
|
995 |
+
label="Llama3 Model",
|
996 |
+
info="Use the Llama3 model to reorganize the article (Note: very slow)",
|
997 |
+
)
|
998 |
+
with gr.Row():
|
999 |
+
additional_tags_prepend = gr.Text(label="Prepend Additional tags (comma split)")
|
1000 |
+
additional_tags_append = gr.Text(label="Append Additional tags (comma split)")
|
1001 |
+
with gr.Row():
|
1002 |
+
clear = gr.ClearButton(
|
1003 |
+
components=[
|
1004 |
+
gallery,
|
1005 |
+
model_repo,
|
1006 |
+
general_thresh,
|
1007 |
+
general_mcut_enabled,
|
1008 |
+
character_thresh,
|
1009 |
+
character_mcut_enabled,
|
1010 |
+
characters_merge_enabled,
|
1011 |
+
llama3_reorganize_model_repo,
|
1012 |
+
additional_tags_prepend,
|
1013 |
+
additional_tags_append,
|
1014 |
+
],
|
1015 |
+
variant="secondary",
|
1016 |
+
size="lg",
|
1017 |
+
)
|
1018 |
+
with gr.Column(variant="panel"):
|
1019 |
+
download_file = gr.File(label="Output (Download)")
|
1020 |
+
sorted_general_strings = gr.Textbox(label="Output (string)", show_label=True, show_copy_button=True)
|
1021 |
+
categorized_output = gr.Textbox(label="Categorized Output (string)", show_label=True, show_copy_button=True)
|
1022 |
+
categorized = gr.JSON(label="Categorized (tags)")
|
1023 |
+
rating = gr.Label(label="Rating")
|
1024 |
+
character_res = gr.Label(label="Output (characters)")
|
1025 |
+
general_res = gr.Label(label="Output (tags)")
|
1026 |
+
unclassified = gr.JSON(label="Unclassified (tags)")
|
1027 |
+
clear.add(
|
1028 |
+
[
|
1029 |
+
download_file,
|
1030 |
+
sorted_general_strings,
|
1031 |
+
categorized,
|
1032 |
+
rating,
|
1033 |
+
character_res,
|
1034 |
+
general_res,
|
1035 |
+
unclassified,
|
1036 |
+
]
|
1037 |
+
)
|
1038 |
+
tag_results = gr.State({})
|
1039 |
+
# Define the event listener to add the uploaded image to the gallery
|
1040 |
+
image_input.change(append_gallery, inputs=[gallery, image_input], outputs=[gallery, image_input])
|
1041 |
+
# When the upload button is clicked, add the new images to the gallery
|
1042 |
+
upload_button.upload(extend_gallery, inputs=[gallery, upload_button], outputs=gallery)
|
1043 |
+
# Event to update the selected image when an image is clicked in the gallery
|
1044 |
+
selected_image = gr.Textbox(label="Selected Image", visible=False)
|
1045 |
+
gallery.select(get_selection_from_gallery, inputs=[gallery, tag_results], outputs=[selected_image, sorted_general_strings, categorized, rating, character_res, general_res, unclassified])
|
1046 |
+
# Event to remove a selected image from the gallery
|
1047 |
+
remove_button.click(remove_image_from_gallery, inputs=[gallery, selected_image], outputs=gallery)
|
1048 |
+
submit.click(
|
1049 |
+
predictor.predict,
|
1050 |
+
inputs=[
|
1051 |
+
gallery,
|
1052 |
+
model_repo,
|
1053 |
+
general_thresh,
|
1054 |
+
general_mcut_enabled,
|
1055 |
+
character_thresh,
|
1056 |
+
character_mcut_enabled,
|
1057 |
+
characters_merge_enabled,
|
1058 |
+
llama3_reorganize_model_repo,
|
1059 |
+
additional_tags_prepend,
|
1060 |
+
additional_tags_append,
|
1061 |
+
tag_results,
|
1062 |
+
],
|
1063 |
+
outputs=[download_file, sorted_general_strings, categorized, rating, character_res, general_res, unclassified, tag_results, categorized_output,],
|
1064 |
+
)
|
1065 |
+
gr.Examples(
|
1066 |
+
[["images/1girl.png", VIT_LARGE_MODEL_DSV3_REPO, 0.35, False, 0.85, False]],
|
1067 |
+
inputs=[
|
1068 |
+
image_input,
|
1069 |
+
model_repo,
|
1070 |
+
general_thresh,
|
1071 |
+
general_mcut_enabled,
|
1072 |
+
character_thresh,
|
1073 |
+
character_mcut_enabled,
|
1074 |
+
],
|
1075 |
+
)
|
1076 |
+
with gr.Tab(label="Florence 2 Image Captioning"):
|
1077 |
+
with gr.Row():
|
1078 |
+
with gr.Column(variant="panel"):
|
1079 |
+
input_img = gr.Image(label="Input Picture")
|
1080 |
+
task_type = gr.Radio(choices=['Single task', 'Cascaded task'], label='Task type selector', value='Single task')
|
1081 |
+
task_prompt = gr.Dropdown(choices=single_task_list, label="Task Prompt", value="Caption")
|
1082 |
+
task_type.change(fn=update_task_dropdown, inputs=task_type, outputs=task_prompt)
|
1083 |
+
text_input = gr.Textbox(label="Text Input (optional)")
|
1084 |
+
submit_btn = gr.Button(value="Submit")
|
1085 |
+
with gr.Column(variant="panel"):
|
1086 |
+
#OUTPUT
|
1087 |
+
output_text = gr.Textbox(label="Output Text", show_label=True, show_copy_button=True, lines=8) # Here is the problem!
|
1088 |
+
output_img = gr.Image(label="Output Image")
|
1089 |
+
gr.Examples(
|
1090 |
+
examples=[
|
1091 |
+
["images/image1.png", 'Object Detection'],
|
1092 |
+
["images/image2.png", 'OCR with Region']
|
1093 |
+
],
|
1094 |
+
inputs=[input_img, task_prompt],
|
1095 |
+
outputs=[output_text, output_img],
|
1096 |
+
fn=process_image,
|
1097 |
+
cache_examples=False,
|
1098 |
+
label='Try examples'
|
1099 |
+
)
|
1100 |
+
submit_btn.click(process_image, [input_img, task_prompt, text_input], [output_text, output_img])
|
1101 |
+
|
1102 |
+
demo.queue(max_size=2)
|
1103 |
+
demo.launch(debug=True) # test
|
classifyTags.py
ADDED
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from collections import defaultdict
|
2 |
+
|
3 |
+
|
4 |
+
def classify_tags (tags: list[str], local_test: bool = False):
|
5 |
+
# Dictionary for automatic classification
|
6 |
+
classified_tags: defaultdict[str, str] = defaultdict(list)
|
7 |
+
fuzzy_match_tags: defaultdict[str, str] = defaultdict(list)
|
8 |
+
fuzzy_match_keylen = 0
|
9 |
+
fuzzy_match_category = ""
|
10 |
+
unclassified_tags: list[str] = []
|
11 |
+
|
12 |
+
|
13 |
+
# Logic for automatic grouping
|
14 |
+
for tag in tags:
|
15 |
+
classified = False
|
16 |
+
tag_new = tag.replace(" ", "_").replace("-", "_").replace("\\(", "(").replace("\\)", ")") # Replace spaces in source tags with underscores \"
|
17 |
+
|
18 |
+
keyword = ""
|
19 |
+
category = ""
|
20 |
+
if tag_new in reversed_categories:
|
21 |
+
category = reversed_categories[tag_new]
|
22 |
+
classified = True
|
23 |
+
else:
|
24 |
+
tag_parts = tag_new.split("_") # Split tags by "_" to ensure keyword matching is based on whole words
|
25 |
+
for keyword, category in reversed_categories.items():
|
26 |
+
keyword = keyword.replace("-", "_").strip("_")
|
27 |
+
verify = tag_new.replace(keyword, "")
|
28 |
+
# Check if the tag contains the keyword
|
29 |
+
if (tag_new == keyword or tag_new.lstrip("0123456789") == keyword or (keyword in tag_new and (verify.startswith("_") or verify.endswith("_")))):
|
30 |
+
classified = True
|
31 |
+
elif any(tag_part == keyword for tag_part in tag_parts):
|
32 |
+
classified = True
|
33 |
+
elif local_test and keyword in tag_new and len(keyword) > fuzzy_match_keylen:
|
34 |
+
fuzzy_match_keylen = len(keyword)
|
35 |
+
fuzzy_match_category = category
|
36 |
+
if classified:
|
37 |
+
break
|
38 |
+
|
39 |
+
if classified and tag not in classified_tags[category]: # Avoid duplicates
|
40 |
+
classified_tags[category].append(tag)
|
41 |
+
|
42 |
+
if not classified and fuzzy_match_keylen > 0 and tag not in fuzzy_match_tags[fuzzy_match_category]:
|
43 |
+
classified = True
|
44 |
+
fuzzy_match_tags[fuzzy_match_category].append(tag)
|
45 |
+
fuzzy_match_keylen = 0
|
46 |
+
fuzzy_match_category = ""
|
47 |
+
|
48 |
+
if not classified and tag not in unclassified_tags:
|
49 |
+
unclassified_tags.append(tag) # Unclassified tags
|
50 |
+
|
51 |
+
if local_test:
|
52 |
+
# Output the grouping result
|
53 |
+
for category, tags in classified_tags.items():
|
54 |
+
print(f"{category}:")
|
55 |
+
print(", ".join(tags))
|
56 |
+
print()
|
57 |
+
|
58 |
+
print()
|
59 |
+
print("Fuzzy match:")
|
60 |
+
for category, tags in fuzzy_match_tags.items():
|
61 |
+
print(f"{category}:")
|
62 |
+
print(", ".join(tags))
|
63 |
+
print()
|
64 |
+
print()
|
65 |
+
|
66 |
+
if len(unclassified_tags) > 0:
|
67 |
+
print(f"\nUnclassified tags: {len(unclassified_tags)}")
|
68 |
+
print(f"{unclassified_tags[:200]}") # Display some unclassified tags
|
69 |
+
|
70 |
+
return classified_tags, unclassified_tags
|
71 |
+
|
72 |
+
# Define grouping rules (categories and keywords)
|
73 |
+
categories = {
|
74 |
+
"explicit" : ["sex", "69", "paizuri", "cum", "precum", "areola_slip", "hetero", "erection", "oral", "fellatio", "yaoi", "ejaculation", "ejaculating", "masturbation", "handjob", "bulge", "rape", "doggystyle", "threesome", "missionary", "object_insertion", "nipple", "nipples", "pussy", "anus", "penis", "groin", "testicles", "testicle", "anal", "cameltoe", "areolae", "dildo", "clitoris", "top-down_bottom-up", "gag", "groping", "gagged", "gangbang", "orgasm", "femdom", "incest", "bukkake", "breast_out", "vaginal", "vagina", "public_indecency", "breast_sucking", "folded", "cunnilingus", "foreskin", "bestiality", "footjob", "uterus", "flaccid", "defloration", "butt_plug", "cowgirl_position", "reverse_cowgirl_position", "squatting_cowgirl_position", "reverse_upright_straddle", "irrumatio", "deepthroat", "pokephilia", "gaping", "orgy", "cleft_of_venus", "futanari", "futasub", "futa", "cumdrip", "fingering", "vibrator", "partially_visible_vulva", "penetration", "penetrated", "cumshot", "exhibitionism", "breast_milk", "grinding", "clitoral", "urethra", "phimosis", "cervix", "impregnation", "tribadism", "molestation", "pubic_hair", "clothed_female_nude_male", "clothed_male_nude_female", "clothed_female_nude_female", "clothed_male_nude_male", "sex_machine", "milking_machine", "ovum", "chikan", "pussy_juice_drip_through_clothes", "ejaculating_while_penetrated", "suspended_congress", "reverse_suspended_congress", "spread_pussy_under_clothes", "anilingus", "reach-around", "humping", "consensual_tentacles", "tentacle_pit", ],
|
75 |
+
#外観状態/外觀狀態
|
76 |
+
"Appearance Status" : ["backless", "bandaged_neck", "bleeding", "blood", "blush", "body_writing", "bodypaint", "bottomless", "breath", "bruise", "butt_crack", "cold", "covered_mouth", "crack", "cross-section", "crotchless", "crying", "curvy", "cuts", "dirty", "dripping", "drunk", "from_mouth", "glowing", "hairy", "halterneck", "hot", "injury", "latex", "leather", "levitation", "lipstick_mark", "_markings", "makeup", "mole", "moles", "no_bra", "nosebleed", "nude", "outfit", "pantylines", "peeing", "piercing", "piercings", "pregnant", "public_nudity", "reverse", "_skin", "_submerged", "saliva", "scar", "scratches", "see-through", "shadow", "shibari", "sideless", "skindentation", "sleeping","tan", "soap_bubbles", "steam", "steaming_body", "stitches", "sweat", "sweatdrop", "sweaty", "tanlines", "tattoo", "tattoo", "tears", "topless", "transparent", "trefoil", "trembling", "veins", "visible_air", "wardrobe_malfunction", "wet", "x-ray", "unconscious", "handprint", ],
|
77 |
+
#動作姿勢/動作姿勢
|
78 |
+
"Action Pose" : ["afloat", "afterimage", "against_fourth_wall", "against_wall", "aiming", "all_fours", "another's_mouth", "arm_", "arm_support", "arms_", "arms_behind_back", "asphyxiation", "attack", "back", "ballet", "bara", "bathing", "battle", "bdsm", "beckoning", "bent_over", "bite_mark", "biting", "bondage", "breast_suppress", "breathing", "burning", "bust_cup", "carry", "carrying", "caught", "chained", "cheek_squash", "chewing", "cigarette", "clapping", "closed_eye", "come_hither", "cooking", "covering", "cuddling", "dancing", "_docking", "destruction", "dorsiflexion", "dreaming", "dressing", "drinking", "driving", "dropping", "eating", "exercise", "expansion", "exposure", "facing", "failure", "fallen_down", "falling", "feeding", "fetal_position", "fighting", "finger_on_trigger", "finger_to_cheek", "finger_to_mouth", "firing", "fishing", "flashing", "fleeing", "flexible", "flexing", "floating", "flying", "fourth_wall", "freediving", "frogtie", "_grab", "girl_on_top", "giving", "grabbing", "grabbing_", "gymnastics", "_hold", "hadanugi_dousa", "hairdressing", "hand_", "hand_on", "hand_on_wall", "hands_", "headpat", "hiding", "holding", "hug", "hugging", "imagining", "in_container", "in_mouth", "in_palm", "jealous", "jumping", "kabedon", "kicking", "kiss", "kissing", "kneeling", "_lift", "lactation", "laundry", "licking", "lifted_by_self", "looking", "lowleg", "lying", "melting", "midair", "moaning", "_open", "on_back", "on_bed", "on_ground", "on_lap", "on_one_knee", "one_eye_closed", "open_", "over_mouth", "own_mouth", "_peek", "_pose", "_press", "_pull", "padding", "paint", "painting_(action)", "palms_together", "pee", "peeking", "pervert", "petting", "pigeon-toed", "piggyback", "pinching", "pinky_out", "pinned", "plantar_flexion", "planted", "playing", "pocky", "pointing", "poke", "poking", "pouring", "pov", "praying", "presenting", "profanity", "pulled_by_self", "pulling", "pump_action", "punching", "_rest", "raised", "reaching", "reading", "reclining", "reverse_grip", "riding", "running", "_slip", "salute", "screaming", "seiza", "selfie", "sewing", "shaking", "shoe_dangle", "shopping", "shouting", "showering", "shushing", "singing", "sitting", "slapping", "smell", "smelling", "smoking", "smother", "solo", "spanked", "spill", "spilling", "spinning", "splashing", "split", "squatting", "squeezed", "standing", "staring", "straddling", "strangling", "stretching", "surfing", "suspension", "swimming", "talking", "teardrop", "tearing_clothes", "throwing", "tied_up", "tiptoes", "toe_scrunch", "toothbrush", "trigger_discipline", "tripping", "tsundere", "turning_head", "twitching", "two-handed", "tying", "_up", "unbuttoned", "undressed", "undressing", "unsheathed", "unsheathing", "unzipped", "unzipping", "upright_straddle", "v", "V", "vore", "_wielding","wading", "walk-in", "walking", "wariza", "waving", "wedgie", "wrestling", "writing", "yawning", "yokozuwari", "_conscious", "massage", "struggling", "shrugging", "drugged", "tentacles_under_clothes", "archery", "cleaning", "tempura", "facepalm", "sadism", ],
|
79 |
+
#頭部装飾/頭部服飾
|
80 |
+
"Headwear" : ["antennae", "antlers", "aura", "bandaged_head", "bandana", "bandeau", "beanie", "beanie", "beret", "bespectacled", "blindfold", "bonnet", "_cap", "circlet", "crown", "_drill", "_drills", "diadem", "_eyewear", "ear_covers", "ear_ornament", "ear_tag", "earbuds", "earclip", "earmuffs", "earphones", "earpiece", "earring", "earrings", "eyeliner", "eyepatch", "eyewear_on_head", "facial", "fedora", "glasses", "goggles", "_headwear", "hachimaki", "hair_bobbles", "hair_ornament", "hair_rings", "hair_tie", "hairband", "hairclip", "hairpin", "hairpods", "halo", "hat", "head-mounted_display", "head_wreath", "headband", "headdress", "headgear", "headphones", "headpiece", "headset", "helm", "helmet", "hood", "kabuto_(helmet)", "kanzashi", "_mask", "maid_headdress", "mask", "mask", "mechanical_ears", "mechanical_eye", "mechanical_horns", "mob_cap", "monocle", "neck_ruff", "nightcap", "on_head", "pince-nez", "qingdai_guanmao", "scarf_over_mouth", "scrunchie", "sunglasses", "tam_o'_shanter", "tate_eboshi", "tiara", "topknot", "turban", "veil", "visor", "wig", "mitre", "tricorne", "bicorne", ],
|
81 |
+
#手部装飾/手部服飾
|
82 |
+
"Handwear" : ["arm_warmers", "armband", "armlet", "bandaged_arm", "bandaged_fingers", "bandaged_hand", "bandaged_wrist", "bangle", "bracelet", "bracelets", "bracer", "cuffs", "elbow_pads", "_gauntlets", "_glove", "_gloves", "gauntlets", "gloves", "kote", "kurokote", "mechanical_arm", "mechanical_arms", "mechanical_hands", "mittens", "mitts", "nail_polish", "prosthetic_arm", "wrist_cuffs", "wrist_guards", "wristband", "yugake", ],
|
83 |
+
#ワンピース衣装/一件式服裝
|
84 |
+
"One-Piece Outfit" : ["bodystocking", "bodysuit", "dress", "furisode", "gown", "hanfu", "jumpsuit", "kimono", "leotard", "microdress", "one-piece", "overalls", "robe", "spacesuit", "sundress", "yukata", ],
|
85 |
+
#上半身衣装/上半身服裝
|
86 |
+
"Upper Body Clothing" : ["aiguillette", "apron", "armor", "ascot", "babydoll", "bikini", "blazer", "blouse", "bowtie", "bra", "breast_curtain", "breast_curtains", "breast_pocket", "breastplate", "bustier", "_collar", "camisole", "cape", "capelet", "cardigan", "center_opening", "chemise", "chest_jewel", "choker", "cloak", "coat", "coattails", "collar", "corset", "criss-cross_halter", "crop_top", "dougi", "feather_boa", "gakuran", "hagoromo", "hanten_(clothes)", "haori", "harem_pants", "harness", "hoodie", "jacket", "japanese_clothes", "kappougi", "kariginu", "lapels", "lingerie", "maid", "mechanical_wings", "mizu_happi", "muneate", "neckerchief", "necktie", "negligee", "nightgown", "pajamas", "pauldron", "pauldrons", "plunging_neckline", "raincoat", "rei_no_himo", "sailor_collar", "sarashi", "scarf", "serafuku", "shawl", "shirt", "shoulder_", "sleepwear", "sleeve", "sleeveless", "sleeves", "sode", "spaghetti_strap", "sportswear", "strapless", "suit", "sundress", "suspenders", "sweater", "swimsuit", "_top", "_torso", "t-shirt", "tabard", "tailcoat", "tank_top", "tasuki", "tie_clip", "tunic", "turtleneck", "tuxedo", "_uniform", "undershirt", "uniform", "v-neck", "vambraces", "vest", "waistcoat", ],
|
87 |
+
#下半身衣装/下半身服裝
|
88 |
+
"Lower Body Clothing" : ["bare_hips", "bloomers", "briefs", "buruma", "crotch_seam", "cutoffs", "denim", "faulds", "fundoshi", "g-string", "garter_straps", "hakama", "hip_vent", "jeans", "knee_pads", "loincloth", "mechanical_tail", "microskirt", "miniskirt", "overskirt", "panties", "pants", "pantsu", "panty_straps", "pelvic_curtain", "petticoat", "sarong", "shorts", "side_slit", "skirt", "sweatpants", "swim_trunks", "thong", "underwear", "waist_cape", ],
|
89 |
+
#足元・レッグウェア/腳與腿部服飾
|
90 |
+
"Foot & Legwear" : ["anklet", "bandaged_leg", "boot", "boots", "_footwear", "flats", "flip-flops", "geta", "greaves", "_heels", "kneehigh", "kneehighs", "_legwear", "leg_warmers", "leggings", "loafers", "mary_janes", "mechanical_legs", "okobo", "over-kneehighs", "pantyhose", "prosthetic_leg", "pumps", "_shoe", "_sock", "sandals", "shoes", "skates", "slippers", "sneakers", "socks", "spikes", "tabi", "tengu-geta", "thigh_strap", "thighhighs", "uwabaki", "zouri", "legband", "ankleband", ],
|
91 |
+
#その他の装飾/其他服飾
|
92 |
+
"Other Accessories" : ["alternate_", "anklet", "badge", "beads", "belt", "belts", "bow", "brooch", "buckle", "button", "buttons", "_clothes", "_costume", "_cutout", "casual", "charm", "clothes_writing", "clothing_aside", "costume", "cow_print", "cross", "d-pad", "double-breasted", "drawstring", "epaulettes", "fabric", "fishnets", "floral_print", "formal", "frills", "_garter", "gem", "holster", "jewelry", "_knot", "lace", "lanyard", "leash", "magatama", "mechanical_parts", "medal", "medallion", "naked_bandage", "necklace", "_ornament", "(ornament)", "o-ring", "obi", "obiage", "obijime", "_pin", "_print", "padlock", "patterned_clothing", "pendant", "piercing", "plaid", "pocket", "polka_dot", "pom_pom_(clothes)", "pom_pom_(clothes)", "pouch", "ribbon", "_stripe", "_stripes", "sash", "shackles", "shimenawa", "shrug_(clothing)", "skin_tight", "spandex", "strap", "sweatband", "_trim", "tassel", "zettai_ryouiki", "zipper", ],
|
93 |
+
#表情/表情
|
94 |
+
"Facial Expression" : ["ahegao", "anger_vein", "angry", "annoyed", "confused", "drooling", "embarrassed", "expressionless", "eye_contact", "_face", "frown", "fucked_silly", "furrowed_brow", "glaring", "gloom_(expression)", "grimace", "grin", "happy", "jitome", "laughing", "_mouth", "nervous", "notice_lines", "o_o", "parted_lips", "pout", "puff_of_air", "restrained", "sad", "sanpaku", "scared", "scowl", "serious", "shaded_face", "shy", "sigh", "sleepy", "smile", "smirk", "smug", "snot", "spoken_ellipsis", "spoken_exclamation_mark", "spoken_interrobang", "spoken_question_mark", "squiggle", "surprised", "tareme", "tearing_up", "thinking", "tongue", "tongue_out", "torogao", "tsurime", "turn_pale", "wide-eyed", "wince", "worried", "heartbeat", ],
|
95 |
+
#絵文字/表情符號
|
96 |
+
"Facial Emoji" : ["!!", "!", "!?", "+++", "+_+", "...", "...?", "._.", "03:00", "0_0", ":/", ":3", ":<", ":>", ":>=", ":d", ":i", ":o", ":p", ":q", ":t", ":x", ":|", ";(", ";)", ";3", ";d", ";o", ";p", ";q", "=_=", ">:(", ">:)", ">_<", ">_o", ">o<", "?", "??", "@_@", "\m/", "\n/", "\o/", "\||/", "^^^", "^_^", "c:", "d:", "o_o", "o3o", "u_u", "w", "x", "x_x", "xd", "zzz", "|_|", ],
|
97 |
+
#頭部/頭部
|
98 |
+
"Head" : ["afro", "ahoge", "animal_ear_fluff", "_bangs", "_bun", "bald", "beard", "blunt_bangs", "blunt_ends", "bob_cut", "bowl_cut", "braid", "braids", "buzz_cut", "circle_cut", "colored_tips", "cowlick", "dot_nose", "dreadlocks", "_ear", "_ears", "_eye", "_eyes", "enpera", "eyeball", "eyebrow", "eyebrow_cut", "eyebrows", "eyelashes", "eyeshadow", "faceless", "facepaint", "facial_mark", "fang", "forehead", "freckles", "goatee", "_hair", "_horn", "_horns", "hair_", "hair_bun", "hair_flaps", "hair_intakes", "hair_tubes", "half_updo", "head_tilt", "heterochromia", "hime_cut", "hime_cut", "horns", "in_eye", "inverted_bob", "kemonomimi_mode", "lips", "mascara", "mohawk", "mouth_", "mustache", "nose", "one-eyed", "one_eye", "one_side_up", "_pupils", "parted_bangs", "pompadour", "ponytail", "ringlets", "_sclera", "sideburns", "sidecut", "sidelock", "sidelocks", "skull", "snout", "stubble", "swept_bangs", "tails", "teeth", "third_eye", "twintails", "two_side_up", "undercut", "updo", "v-shaped_eyebrows", "whiskers", "tentacle_hair", ],
|
99 |
+
#手部/手部
|
100 |
+
"Hands" : ["_arm", "_arms", "claws", "_finger", "_fingers", "fingernails", "_hand", "_nail", "_nails", "palms", "rings", "thumbs_up", ],
|
101 |
+
#上半身/上半身
|
102 |
+
"Upper Body" : ["abs", "armpit", "armpits", "backboob", "belly", "biceps", "breast_rest", "breasts", "button_gap", "cleavage", "collarbone", "dimples_of_venus", "downblouse", "flat_chest", "linea_alba", "median_furrow", "midriff", "nape", "navel", "pectorals", "ribs", "_shoulder", "_shoulders", "shoulder_blades", "sideboob", "sidetail", "spine", "stomach", "strap_gap", "toned", "underboob", "underbust", ],
|
103 |
+
#下半身/下半身
|
104 |
+
"Lower Body" : ["ankles", "ass", "barefoot", "crotch", "feet", "highleg", "hip_bones", "hooves", "kneepits", "knees", "legs", "soles", "tail", "thigh_gap", "thighlet", "thighs", "toenail", "toenails", "toes", "wide_hips", ],
|
105 |
+
#生物/生物
|
106 |
+
"Creature" : ["(animal)", "anglerfish", "animal", "bear", "bee", "bird", "bug", "butterfly", "cat", "chick", "chicken", "chinese_zodiac", "clownfish", "coral", "crab", "creature", "crow", "dog", "dove", "dragon", "duck", "eagle", "fish", "fish", "fox", "fox", "frog", "frog", "goldfish", "hamster", "horse", "jellyfish", "ladybug", "lion", "mouse", "octopus", "owl", "panda", "penguin", "pig", "pigeon", "rabbit", "rooster", "seagull", "shark", "sheep", "shrimp", "snail", "snake", "squid", "starfish", "tanuki", "tentacles", "tiger", "turtle", "weasel", "whale", "wolf", "parrot", "sparrow", "unicorn", ],
|
107 |
+
#植物/植物
|
108 |
+
"Plant" : ["bamboo", "bouquet", "branch", "bush", "cherry_blossoms", "clover", "daisy", "(flower)", "flower", "flower", "gourd", "hibiscus", "holly", "hydrangea", "leaf", "lily_pad", "lotus", "moss", "palm_leaf", "palm_tree", "petals", "plant", "plum_blossoms", "rose", "spider_lily", "sunflower", "thorns", "tree", "tulip", "vines", "wisteria", "acorn", ],
|
109 |
+
#食べ物/食物
|
110 |
+
"Food" : ["apple", "baguette", "banana", "baozi", "beans", "bento", "berry", "blueberry", "bread", "broccoli", "burger", "cabbage", "cake", "candy", "carrot", "cheese", "cherry", "chili_pepper", "chocolate", "coconut", "cookie", "corn", "cream", "crepe", "cucumber", "cucumber", "cupcake", "curry", "dango", "dessert", "doughnut", "egg", "eggplant", "_(food)", "_(fruit)", "food", "french_fries", "fruit", "grapes", "ice_cream", "icing", "lemon", "lettuce", "lollipop", "macaron", "mandarin_orange", "meat", "melon", "mochi", "mushroom", "noodles", "omelet", "omurice", "onigiri", "onion", "pancake", "parfait", "pasties", "pastry", "peach", "pineapple", "pizza", "popsicle", "potato", "pudding", "pumpkin", "radish", "ramen", "raspberry", "rice", "roasted_sweet_potato", "sandwich", "sausage", "seaweed", "skewer", "spitroast", "spring_onion", "strawberry", "sushi", "sweet_potato", "sweets", "taiyaki", "takoyaki", "tamagoyaki", "tempurakanbea", "toast", "tomato", "vegetable", "wagashi", "wagashi", "watermelon", "jam", "popcorn", ],
|
111 |
+
#飲み物/飲品
|
112 |
+
"Beverage" : ["alcohol", "beer", "coffee", "cola", "drink", "juice", "juice_box", "milk", "sake", "soda", "tea", "whiskey", "wine", "cocktail", ],
|
113 |
+
#音楽/音樂
|
114 |
+
"Music" : ["band", "baton_(conducting)", "beamed", "cello", "concert", "drum", "drumsticks", "eighth_note", "flute", "guitar", "harp", "horn", "(instrument)", "idol", "instrument", "k-pop", "lyre", "(music)", "megaphone", "microphone", "music", "musical_note", "phonograph", "piano", "plectrum", "quarter_note", "recorder", "sixteenth_note", "sound_effects", "trumpet", "utaite", "violin", "whistle", ],
|
115 |
+
#武器・装備/武器・裝備
|
116 |
+
"Weapons & Equipment" : ["ammunition", "arrow_(projectile)", "axe", "bandolier", "baseball_bat", "beretta_92", "bolt_action", "bomb", "bullet", "bullpup", "cannon", "chainsaw", "crossbow", "dagger", "energy_sword", "explosive", "fighter_jet", "gohei", "grenade", "gun", "hammer", "handgun", "holstered", "jet", "katana", "knife", "kunai", "lance", "mallet", "nata_(tool)", "polearm", "quiver", "rapier", "revolver", "rifle", "rocket_launcher", "scabbard", "scope", "scythe", "sheath", "sheathed", "shield", "shotgun", "shuriken", "spear", "staff", "suppressor", "sword", "tank", "tantou", "torpedo", "trident", "(weapon)", "wand", "weapon", "whip", "yumi_(bow)", "h&k_hk416", "rocket_launcher", "heckler_&_koch", ],
|
117 |
+
#乗り物/交通器具
|
118 |
+
"Vehicles" : ["aircraft", "airplane", "bicycle", "boat", "car", "caterpillar_tracks", "flight_deck", "helicopter", "motor_vehicle", "motorcycle", "ship", "spacecraft", "spoiler_(automobile)", "train", "truck", "watercraft", "wheel", "wheelbarrow", "wheelchair", "inflatable_raft", ],
|
119 |
+
#建物/建物
|
120 |
+
"Buildings" : ["apartment", "aquarium", "architecture", "balcony", "building", "cafe", "castle", "church", "gym", "hallway", "hospital", "house", "library", "(place)", "porch", "restaurant", "restroom", "rooftop", "shop", "skyscraper", "stadium", "stage", "temple", "toilet", "tower", "train_station", "veranda", ],
|
121 |
+
#室内/室內
|
122 |
+
"Indoor" : ["bath", "bathroom", "bathtub", "bed", "bed_sheet", "bedroom", "blanket", "bookshelf", "carpet", "ceiling", "chair", "chalkboard", "classroom", "counter", "cupboard", "curtains", "cushion", "dakimakura", "desk", "door", "doorway", "drawer", "_floor", "floor", "futon", "indoors", "interior", "kitchen", "kotatsu", "locker", "mirror", "pillow", "room", "rug", "school_desk", "shelf", "shouji", "sink", "sliding_doors", "stairs", "stool", "storeroom", "table", "tatami", "throne", "window", "windowsill", "bathhouse", "chest_of_drawers", ],
|
123 |
+
#屋外/室外
|
124 |
+
"Outdoor" : ["alley", "arch", "beach", "bridge", "bus_stop", "bush", "cave", "(city)", "city", "cliff", "crescent", "crosswalk", "day", "desert", "fence", "ferris_wheel", "field", "forest", "grass", "graveyard", "hill", "lake", "lamppost", "moon", "mountain", "night", "ocean", "onsen", "outdoors", "path", "pool", "poolside", "railing", "railroad", "river", "road", "rock", "sand", "shore", "sky", "smokestack", "snow", "snowball", "snowman", "street", "sun", "sunlight", "sunset", "tent", "torii", "town", "tree", "turret", "utility_pole", "valley", "village", "waterfall", ],
|
125 |
+
#物品/物品
|
126 |
+
"Objects" : ["anchor", "android", "armchair", "(bottle)", "backpack", "bag", "ball", "balloon", "bandages", "bandaid", "bandaids", "banknote", "banner", "barcode", "barrel", "baseball", "basket", "basketball", "beachball", "bell", "bench", "binoculars", "board_game", "bone", "book", "bottle", "bowl", "box", "box_art", "briefcase", "broom", "bucket", "(chess)", "(computer)", "(computing)", "(container)", "cage", "calligraphy_brush", "camera", "can", "candle", "candlestand", "cane", "card", "cartridge", "cellphone", "chain", "chandelier", "chess", "chess_piece", "choko_(cup)", "chopsticks", "cigar", "clipboard", "clock", "clothesline", "coin", "comb", "computer", "condom", "controller", "cosmetics", "couch", "cowbell", "crazy_straw", "cup", "cutting_board", "dice", "digital_media_player", "doll", "drawing_tablet", "drinking_straw", "easel", "electric_fan", "emblem", "envelope", "eraser", "feathers", "figure", "fire", "fishing_rod", "flag", "flask", "folding_fan", "fork", "frying_pan", "(gemstone)", "game_console", "gears", "gemstone", "gift", "glass", "glowstick", "gold", "handbag", "handcuffs", "handheld_game_console", "hose", "id_card", "innertube", "iphone", "jack-o'-lantern", "jar", "joystick", "key", "keychain", "kiseru", "ladder", "ladle", "lamp", "lantern", "laptop", "letter", "letterboxed", "lifebuoy", "lipstick", "liquid", "lock", "lotion", "_machine", "map", "marker", "model_kit", "money", "monitor", "mop", "mug", "needle", "newspaper", "nintendo", "nintendo_switch", "notebook", "(object)", "ofuda", "orb", "origami", "(playing_card)", "pack", "paddle", "paintbrush", "pan", "paper", "parasol", "patch", "pc", "pen", "pencil", "pencil", "pendant_watch", "phone", "pill", "pinwheel", "plate", "playstation", "pocket_watch", "pointer", "poke_ball", "pole", "quill", "racket", "randoseru", "remote_control", "ring", "rope", "sack", "saddle", "sakazuki", "satchel", "saucer", "scissors", "scroll", "seashell", "seatbelt", "shell", "shide", "shopping_cart", "shovel", "shower_head", "silk", "sketchbook", "smartphone", "soap", "sparkler", "spatula", "speaker", "spoon", "statue", "stethoscope", "stick", "sticker", "stopwatch", "string", "stuffed_", "stylus", "suction_cups", "suitcase", "surfboard", "syringe", "talisman", "tanzaku", "tape", "teacup", "teapot", "teddy_bear", "television", "test_tube", "tiles", "tokkuri", "tombstone", "torch", "towel", "toy", "traffic_cone", "tray", "treasure_chest", "uchiwa", "umbrella", "vase", "vial", "video_game", "viewfinder", "volleyball", "wallet", "watch", "watch", "whisk", "whiteboard", "wreath", "wrench", "wristwatch", "yunomi", "ace_of_hearts", "inkwell", "compass", "ipod", "sunscreen", "rocket", "cobblestone", ],
|
127 |
+
#キャラクター設定/角色設定
|
128 |
+
"Character Design" : ["+boys", "+girls", "1other", "39", "_boys", "_challenge", "_connection", "_female", "_fur", "_girls", "_interface", "_male", "_man", "_person", "abyssal_ship", "age_difference", "aged_down", "aged_up", "albino", "alien", "alternate_muscle_size", "ambiguous_gender", "amputee", "androgynous", "angel", "animalization", "ass-to-ass", "assault_visor", "au_ra", "baby", "bartender", "beak", "bishounen", "borrowed_character", "boxers", "boy", "breast_envy", "breathing_fire", "bride", "broken", "brother_and_sister", "brothers", "camouflage", "cheating_(relationship)", "cheerleader", "chibi", "child", "clone", "command_spell", "comparison", "contemporary", "corpse", "corruption", "cosplay", "couple", "creature_and_personification", "crossdressing", "crossover", "cyberpunk", "cyborg", "cyclops", "damaged", "dancer", "danmaku", "darkness", "death", "defeat", "demon", "disembodied_", "draph", "drone", "duel", "dwarf", "egyptian", "electricity", "elezen", "elf", "enmaided", "erune", "everyone", "evolutionary_line", "expressions", "fairy", "family", "fangs", "fantasy", "fashion", "fat", "father_and_daughter", "father_and_son", "fewer_digits", "fins", "flashback", "fluffy", "fumo_(doll)", "furry", "fusion", "fuuin_no_tsue", "gameplay_mechanics", "genderswap", "ghost", "giant", "giantess", "gibson_les_paul", "girl", "goblin", "groom", "guro", "gyaru", "habit", "harem", "harpy", "harvin", "heads_together", "health_bar", "height_difference", "hitodama", "horror_(theme)", "humanization", "husband_and_wife", "hydrokinesis", "hypnosis", "hyur", "idol", "insignia", "instant_loss", "interracial", "interspecies", "japari_bun", "jeweled_branch_of_hourai", "jiangshi", "jirai_kei", "joints", "karakasa_obake", "keyhole", "kitsune", "knight", "kodona", "kogal", "kyuubi", "lamia", "left-handed", "loli", "lolita", "look-alike", "machinery", "magic", "male_focus", "manly", "matching_outfits", "mature_female", "mecha", "mermaid", "meta", "miko", "milestone_celebration", "military", "mind_control", "miniboy", "minigirl", "miqo'te", "monster", "monsterification", "mother_and_daughter", "mother_and_son", "multiple_others", "muscular", "nanodesu_(phrase)", "narrow_waist", "nekomata", "netorare", "ninja", "no_humans", "nontraditional", "nun", "nurse", "object_namesake", "obliques", "office_lady", "old", "on_body", "onee-shota", "oni", "orc", "others", "otoko_no_ko", "oversized_object", "paint_splatter", "pantyshot", "pawpads", "persona", "personality", "personification", "pet_play", "petite", "pirate", "playboy_bunny", "player_2", "plugsuit", "plump", "poi", "pokemon", "police", "policewoman", "pom_pom_(cheerleading)", "princess", "prosthesis", "pun", "puppet", "race_queen", "radio_antenna", "real_life_insert", "redesign", "reverse_trap", "rigging", "robot", "rod_of_remorse", "sailor", "salaryman", "samurai", "sangvis_ferri", "scales", "scene_reference", "school", "sheikah", "shota", "shrine", "siblings", "side-by-side", "sidesaddle", "sisters", "size_difference", "skeleton", "skinny", "slave", "slime_(substance)", "soldier", "spiked_shell", "spokencharacter", "steampunk", "streetwear", "striker_unit", "strongman", "submerged", "suggestive", "super_saiyan", "superhero", "surreal", "take_your_pick", "tall", "talons", "taur", "teacher", "team_rocket", "three-dimensional_maneuver_gear", "time_paradox", "tomboy", "traditional_youkai", "transformation", "trick_or_treat", "tusks", "twins", "ufo", "under_covers", "v-fin", "v-fin", "vampire", "virtual_youtuber", "waitress", "watching_television", "wedding", "what", "when_you_see_it", "wife_and_wife", "wing", "wings", "witch", "world_war_ii", "yandere", "year_of", "yes", "yin_yang", "yordle", "you're_doing_it_wrong", "you_gonna_get_raped", "yukkuri_shiteitte_ne", "yuri", "zombie", "(alice_in_wonderland)", "(arknights)", "(blue_archive)", "(cosplay)", "(creature)", "(emblem)", "(evangelion)", "(fate)", "(fate/stay_night)", "(ff11)", "(fire_emblem)", "(genshin_impact)", "(grimm)", "(houseki_no_kuni)", "(hyouka)", "(idolmaster)", "(jojo)", "(kancolle)", "(kantai_collection)", "(kill_la_kill)", "(league_of_legends)", "(legends)", "(lyomsnpmp)", "(machimazo)", "(madoka_magica)", "(mecha)", "(meme)", "(nier:automata)", "(organ)", "(overwatch)", "(pokemon)", "(project_moon)", "(project_sekai)", "(sao)", "(senran_kagura)", "(splatoon)", "(touhou)", "(tsukumo_sana)", "(youkai_watch)", "(yu-gi-oh!_gx)", "(zelda)", "sextuplets", "imperial_japanese_army", "extra_faces", ],
|
129 |
+
#構図/構圖
|
130 |
+
"Composition" : ["abstract", "anime_coloring", "animification", "back-to-back", "bad_anatomy", "blurry", "border", "bound", "cameo", "cheek-to-cheek", "chromatic_aberration", "close-up", "collage", "color_guide", "colorful", "comic", "contrapposto", "cover", "cowboy_shot", "crosshatching", "depth_of_field", "dominatrix", "dutch_angle", "_focus", "face-to-face", "fake_screenshot", "film_grain", "fisheye", "flat_color", "foreshortening", "from_above", "from_behind", "from_below", "from_side", "full_body", "glitch", "greyscale", "halftone", "head_only", "heads-up_display", "high_contrast", "horizon", "_inset", "inset", "jaggy_lines", "1koma", "2koma", "3koma", "4koma", "5koma", "leaning", "leaning_forward", "leaning_to_the_side", "left-to-right_manga", "lens_flare", "limited_palette", "lineart", "lineup", "lower_body", "(medium)", "marker_(medium)", "meme", "mixed_media", "monochrome", "multiple_views", "muted_color", "oekaki", "on_side", "out_of_frame", "outline", "painting", "parody", "partially_colored", "partially_underwater_shot", "perspective", "photorealistic", "picture_frame", "pillarboxed", "portrait", "poster_(object)", "product_placement", "profile", "realistic", "recording", "retro_artstyle", "(style)", "_style", "sandwiched", "science_fiction", "sepia", "shikishi", "side-by-side", "sideways", "sideways_glance", "silhouette", "sketch", "spot_color", "still_life", "straight-on", "symmetry", "(texture)", "tachi-e", "taking_picture", "tegaki", "too_many", "traditional_media", "turnaround", "underwater", "upper_body", "upside-down", "upskirt", "variations", "wide_shot", "_design", "symbolism", "rounded_corners", "surrounded", ],
|
131 |
+
#季節/季節
|
132 |
+
"Season" : ["akeome", "anniversary", "autumn", "birthday", "christmas", "_day", "festival", "halloween", "kotoyoro", "nengajou", "new_year", "spring_(season)", "summer", "tanabata", "valentine", "winter", ],
|
133 |
+
#背景/背景
|
134 |
+
"Background" : ["_background", "backlighting", "bloom", "bokeh", "brick_wall", "bubble", "cable", "caustics", "cityscape", "cloud", "confetti", "constellation", "contrail", "crowd", "crystal", "dark", "debris", "dusk", "dust", "egasumi", "embers", "emphasis_lines", "energy", "evening", "explosion", "fireworks", "fog", "footprints", "glint", "graffiti", "ice", "industrial_pipe", "landscape", "light", "light_particles", "light_rays", "lightning", "lights", "moonlight", "motion_blur", "motion_lines", "mountainous_horizon", "nature", "(planet)", "pagoda", "people", "pillar", "planet", "power_lines", "puddle", "rain", "rainbow", "reflection", "ripples", "rubble", "ruins", "scenery", "shade", "shooting_star", "sidelighting", "smoke", "snowflakes", "snowing", "space", "sparkle", "sparks", "speed_lines", "spider_web", "spotlight", "star_(sky)", "stone_wall", "sunbeam", "sunburst", "sunrise", "_theme", "tile_wall", "twilight", "wall_clock", "wall_of_text", "water", "waves", "wind", "wire", "wooden_wall", "lighthouse", ],
|
135 |
+
# パターン/圖案
|
136 |
+
"Patterns" : ["arrow", "bass_clef", "blank_censor", "circle", "cube", "heart", "hexagon", "hexagram", "light_censor", "(pattern)", "pattern", "pentagram", "roman_numeral", "(shape)", "(symbol)", "shape", "sign", "symbol", "tally", "treble_clef", "triangle", "tube", "yagasuri", ],
|
137 |
+
#検閲/審查
|
138 |
+
"Censorship" : ["blur_censor", "_censor", "_censoring", "censored", "character_censor", "convenient", "hair_censor", "heart_censor", "identity_censor", "maebari", "novelty_censor", "soap_censor", "steam_censor", "tail_censor", "uncensored", ],
|
139 |
+
#その他/其他
|
140 |
+
"Others" : ["2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "artist", "artist_name", "artistic_error", "asian", "(company)", "character_name", "content_rating", "copyright", "cover_page", "dated", "english_text", "japan", "layer", "logo", "name", "numbered", "page_number", "pixiv_id", "ranguage", "reference_sheet", "signature", "speech_bubble", "subtitled", "text", "thank_you", "typo", "username", "wallpaper", "watermark", "web_address", "screwdriver", ],
|
141 |
+
}
|
142 |
+
|
143 |
+
# Use dictionary comprehension to reverse key-value pairs
|
144 |
+
reversed_categories = {value: key for key, values in categories.items() for value in values}
|
145 |
+
|
146 |
+
|
147 |
+
tags = []
|
148 |
+
|
149 |
+
if __name__ == "__main__":
|
150 |
+
classify_tags (tags, True)
|
151 |
+
|
images/1girl.png
ADDED
![]() |
Git LFS Details
|
images/image1.png
ADDED
![]() |
Git LFS Details
|
images/image2.png
ADDED
![]() |
Git LFS Details
|
pre-requirements.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
pip>=23.0.0
|
requirements.txt
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
huggingface-hub
|
2 |
+
apscheduler
|
3 |
+
|
4 |
+
--extra-index-url https://download.pytorch.org/whl/cu124
|
5 |
+
torch==2.5.0+cu124; sys_platform != 'darwin'
|
6 |
+
torchvision==0.20.0+cu124; sys_platform != 'darwin'
|
7 |
+
torch==2.5.0; sys_platform == 'darwin'
|
8 |
+
torchvision==0.20.0; sys_platform == 'darwin'
|
9 |
+
|
10 |
+
gradio
|
11 |
+
transformers
|
12 |
+
spaces
|
13 |
+
pillow
|
14 |
+
requests
|
15 |
+
numpy
|
16 |
+
timm
|
17 |
+
einops
|
18 |
+
optimum
|
19 |
+
accelerate
|
20 |
+
opencv-python
|
21 |
+
onnxruntime>=1.12.0
|
22 |
+
pandas==2.1.2
|
23 |
+
ctranslate2>=4.4.0
|
24 |
+
matplotlib
|
themes/[email protected]
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"theme": {"_font": [{"__gradio_font__": true, "name": "Rubik", "class": "google"}, {"__gradio_font__": true, "name": "ui-sans-serif", "class": "font"}, {"__gradio_font__": true, "name": "system-ui", "class": "font"}, {"__gradio_font__": true, "name": "sans-serif", "class": "font"}], "_font_mono": [{"__gradio_font__": true, "name": "Inconsolata", "class": "google"}, {"__gradio_font__": true, "name": "ui-monospace", "class": "font"}, {"__gradio_font__": true, "name": "Consolas", "class": "font"}, {"__gradio_font__": true, "name": "monospace", "class": "font"}], "_stylesheets": ["https://fonts.googleapis.com/css2?family=Rubik:wght@400;500&display=swap", "https://fonts.googleapis.com/css2?family=Inconsolata:wght@400;500&display=swap"], "background_fill_primary": "white", "background_fill_primary_dark": "*neutral_950", "background_fill_secondary": "*neutral_50", "background_fill_secondary_dark": "*neutral_900", "block_background_fill": "*background_fill_primary", "block_background_fill_dark": "*neutral_800", "block_border_color": "*border_color_primary", "block_border_color_dark": "*border_color_primary", "block_border_width": "1px", "block_border_width_dark": "1px", "block_info_text_color": "*body_text_color_subdued", "block_info_text_color_dark": "*body_text_color_subdued", "block_info_text_size": "*text_sm", "block_info_text_weight": "400", "block_label_background_fill": "*background_fill_primary", "block_label_background_fill_dark": "*background_fill_secondary", "block_label_border_color": "*border_color_primary", "block_label_border_color_dark": "*border_color_primary", "block_label_border_width": "1px", "block_label_border_width_dark": "1px", "block_label_margin": "0", "block_label_padding": "*spacing_sm *spacing_lg", "block_label_radius": "calc(*radius_lg - 1px) 0 calc(*radius_lg - 1px) 0", "block_label_right_radius": "0 calc(*radius_lg - 1px) 0 calc(*radius_lg - 1px)", "block_label_shadow": "*block_shadow", "block_label_text_color": "*neutral_500", "block_label_text_color_dark": "*neutral_200", "block_label_text_size": "*text_sm", "block_label_text_weight": "400", "block_padding": "*spacing_xl calc(*spacing_xl + 2px)", "block_radius": "*radius_lg", "block_shadow": "none", "block_shadow_dark": "none", "block_title_background_fill": "none", "block_title_background_fill_dark": "none", "block_title_border_color": "none", "block_title_border_color_dark": "none", "block_title_border_width": "0px", "block_title_border_width_dark": "0px", "block_title_padding": "0", "block_title_radius": "none", "block_title_text_color": "*neutral_500", "block_title_text_color_dark": "*neutral_200", "block_title_text_size": "*text_md", "block_title_text_weight": "400", "body_background_fill": "*background_fill_primary", "body_background_fill_dark": "*background_fill_primary", "body_text_color": "*neutral_700", "body_text_color_dark": "*neutral_200", "body_text_color_subdued": "*neutral_400", "body_text_color_subdued_dark": "*neutral_500", "body_text_size": "*text_md", "body_text_weight": "400", "border_color_accent": "*primary_300", "border_color_accent_dark": "*neutral_600", "border_color_primary": "*neutral_200", "border_color_primary_dark": "*neutral_700", "button_border_width": "*input_border_width", "button_border_width_dark": "*input_border_width", "button_cancel_background_fill": "*button_secondary_background_fill", "button_cancel_background_fill_dark": "*button_secondary_background_fill", "button_cancel_background_fill_hover": "*button_cancel_background_fill", "button_cancel_background_fill_hover_dark": "*button_cancel_background_fill", "button_cancel_border_color": "*button_secondary_border_color", "button_cancel_border_color_dark": "*button_secondary_border_color", "button_cancel_border_color_hover": "*button_cancel_border_color", "button_cancel_border_color_hover_dark": "*button_cancel_border_color", "button_cancel_text_color": "*button_secondary_text_color", "button_cancel_text_color_dark": "*button_secondary_text_color", "button_cancel_text_color_hover": "*button_cancel_text_color", "button_cancel_text_color_hover_dark": "*button_cancel_text_color", "button_large_padding": "*spacing_lg calc(2 * *spacing_lg)", "button_large_radius": "*radius_lg", "button_large_text_size": "*text_lg", "button_large_text_weight": "500", "button_primary_background_fill": "*primary_200", "button_primary_background_fill_dark": "*primary_700", "button_primary_background_fill_hover": "*button_primary_background_fill", "button_primary_background_fill_hover_dark": "*button_primary_background_fill", "button_primary_border_color": "*primary_200", "button_primary_border_color_dark": "*primary_600", "button_primary_border_color_hover": "*button_primary_border_color", "button_primary_border_color_hover_dark": "*button_primary_border_color", "button_primary_text_color": "*primary_600", "button_primary_text_color_dark": "white", "button_primary_text_color_hover": "*button_primary_text_color", "button_primary_text_color_hover_dark": "*button_primary_text_color", "button_secondary_background_fill": "*neutral_200", "button_secondary_background_fill_dark": "*neutral_600", "button_secondary_background_fill_hover": "*button_secondary_background_fill", "button_secondary_background_fill_hover_dark": "*button_secondary_background_fill", "button_secondary_border_color": "*neutral_200", "button_secondary_border_color_dark": "*neutral_600", "button_secondary_border_color_hover": "*button_secondary_border_color", "button_secondary_border_color_hover_dark": "*button_secondary_border_color", "button_secondary_text_color": "*neutral_700", "button_secondary_text_color_dark": "white", "button_secondary_text_color_hover": "*button_secondary_text_color", "button_secondary_text_color_hover_dark": "*button_secondary_text_color", "button_shadow": "none", "button_shadow_active": "none", "button_shadow_hover": "none", "button_small_padding": "*spacing_sm calc(2 * *spacing_sm)", "button_small_radius": "*radius_lg", "button_small_text_size": "*text_md", "button_small_text_weight": "400", "button_transition": "background-color 0.2s ease", "checkbox_background_color": "*background_fill_primary", "checkbox_background_color_dark": "*neutral_800", "checkbox_background_color_focus": "*checkbox_background_color", "checkbox_background_color_focus_dark": "*checkbox_background_color", "checkbox_background_color_hover": "*checkbox_background_color", "checkbox_background_color_hover_dark": "*checkbox_background_color", "checkbox_background_color_selected": "*secondary_600", "checkbox_background_color_selected_dark": "*secondary_600", "checkbox_border_color": "*neutral_300", "checkbox_border_color_dark": "*neutral_700", "checkbox_border_color_focus": "*secondary_500", "checkbox_border_color_focus_dark": "*secondary_500", "checkbox_border_color_hover": "*neutral_300", "checkbox_border_color_hover_dark": "*neutral_600", "checkbox_border_color_selected": "*secondary_600", "checkbox_border_color_selected_dark": "*secondary_600", "checkbox_border_radius": "*radius_sm", "checkbox_border_width": "*input_border_width", "checkbox_border_width_dark": "*input_border_width", "checkbox_check": "url(\"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e\")", "checkbox_label_background_fill": "*button_secondary_background_fill", "checkbox_label_background_fill_dark": "*button_secondary_background_fill", "checkbox_label_background_fill_hover": "*button_secondary_background_fill_hover", "checkbox_label_background_fill_hover_dark": "*button_secondary_background_fill_hover", "checkbox_label_background_fill_selected": "*checkbox_label_background_fill", "checkbox_label_background_fill_selected_dark": "*checkbox_label_background_fill", "checkbox_label_border_color": "*border_color_primary", "checkbox_label_border_color_dark": "*border_color_primary", "checkbox_label_border_color_hover": "*checkbox_label_border_color", "checkbox_label_border_color_hover_dark": "*checkbox_label_border_color", "checkbox_label_border_width": "*input_border_width", "checkbox_label_border_width_dark": "*input_border_width", "checkbox_label_gap": "*spacing_lg", "checkbox_label_padding": "*spacing_md calc(2 * *spacing_md)", "checkbox_label_shadow": "none", "checkbox_label_text_color": "*body_text_color", "checkbox_label_text_color_dark": "*body_text_color", "checkbox_label_text_color_selected": "*checkbox_label_text_color", "checkbox_label_text_color_selected_dark": "*checkbox_label_text_color", "checkbox_label_text_size": "*text_md", "checkbox_label_text_weight": "400", "checkbox_shadow": "*input_shadow", "color_accent": "*primary_500", "color_accent_soft": "*primary_50", "color_accent_soft_dark": "*neutral_700", "container_radius": "*radius_lg", "embed_radius": "*radius_md", "error_background_fill": "#fee2e2", "error_background_fill_dark": "*background_fill_primary", "error_border_color": "#fecaca", "error_border_color_dark": "*border_color_primary", "error_border_width": "1px", "error_border_width_dark": "1px", "error_text_color": "#ef4444", "error_text_color_dark": "#ef4444", "font": "'Rubik', 'ui-sans-serif', 'system-ui', sans-serif", "font_mono": "'Inconsolata', 'ui-monospace', 'Consolas', monospace", "form_gap_width": "0px", "input_background_fill": "*neutral_100", "input_background_fill_dark": "*neutral_700", "input_background_fill_focus": "*secondary_500", "input_background_fill_focus_dark": "*secondary_600", "input_background_fill_hover": "*input_background_fill", "input_background_fill_hover_dark": "*input_background_fill", "input_border_color": "*border_color_primary", "input_border_color_dark": "*border_color_primary", "input_border_color_focus": "*secondary_300", "input_border_color_focus_dark": "*neutral_700", "input_border_color_hover": "*input_border_color", "input_border_color_hover_dark": "*input_border_color", "input_border_width": "0px", "input_border_width_dark": "0px", "input_padding": "*spacing_xl", "input_placeholder_color": "*neutral_400", "input_placeholder_color_dark": "*neutral_500", "input_radius": "*radius_lg", "input_shadow": "none", "input_shadow_dark": "none", "input_shadow_focus": "*input_shadow", "input_shadow_focus_dark": "*input_shadow", "input_text_size": "*text_md", "input_text_weight": "400", "layout_gap": "*spacing_xxl", "link_text_color": "*secondary_600", "link_text_color_active": "*secondary_600", "link_text_color_active_dark": "*secondary_500", "link_text_color_dark": "*secondary_500", "link_text_color_hover": "*secondary_700", "link_text_color_hover_dark": "*secondary_400", "link_text_color_visited": "*secondary_500", "link_text_color_visited_dark": "*secondary_600", "loader_color": "*color_accent", "loader_color_dark": "*color_accent", "name": "base", "neutral_100": "#f5f5f4", "neutral_200": "#e7e5e4", "neutral_300": "#d6d3d1", "neutral_400": "#a8a29e", "neutral_50": "#fafaf9", "neutral_500": "#78716c", "neutral_600": "#57534e", "neutral_700": "#44403c", "neutral_800": "#292524", "neutral_900": "#1c1917", "neutral_950": "#0f0e0d", "panel_background_fill": "*background_fill_secondary", "panel_background_fill_dark": "*background_fill_secondary", "panel_border_color": "*border_color_primary", "panel_border_color_dark": "*border_color_primary", "panel_border_width": "0", "panel_border_width_dark": "0", "primary_100": "#e0f2fe", "primary_200": "#bae6fd", "primary_300": "#7dd3fc", "primary_400": "#38bdf8", "primary_50": "#f0f9ff", "primary_500": "#0ea5e9", "primary_600": "#0284c7", "primary_700": "#0369a1", "primary_800": "#075985", "primary_900": "#0c4a6e", "primary_950": "#0b4165", "prose_header_text_weight": "500", "prose_text_size": "*text_md", "prose_text_weight": "400", "radio_circle": "url(\"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e\")", "radius_lg": "3px", "radius_md": "3px", "radius_sm": "3px", "radius_xl": "3px", "radius_xs": "3px", "radius_xxl": "3px", "radius_xxs": "3px", "secondary_100": "#e0f2fe", "secondary_200": "#bae6fd", "secondary_300": "#7dd3fc", "secondary_400": "#38bdf8", "secondary_50": "#f0f9ff", "secondary_500": "#0ea5e9", "secondary_600": "#0284c7", "secondary_700": "#0369a1", "secondary_800": "#075985", "secondary_900": "#0c4a6e", "secondary_950": "#0b4165", "section_header_text_size": "*text_md", "section_header_text_weight": "400", "shadow_drop": "rgba(0,0,0,0.05) 0px 1px 2px 0px", "shadow_drop_lg": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)", "shadow_inset": "rgba(0,0,0,0.05) 0px 2px 4px 0px inset", "shadow_spread": "3px", "shadow_spread_dark": "1px", "slider_color": "*primary_600", "slider_color_dark": "*primary_600", "spacing_lg": "8px", "spacing_md": "6px", "spacing_sm": "4px", "spacing_xl": "10px", "spacing_xs": "2px", "spacing_xxl": "16px", "spacing_xxs": "1px", "stat_background_fill": "*primary_300", "stat_background_fill_dark": "*primary_500", "table_border_color": "*neutral_300", "table_border_color_dark": "*neutral_700", "table_even_background_fill": "white", "table_even_background_fill_dark": "*neutral_950", "table_odd_background_fill": "*neutral_50", "table_odd_background_fill_dark": "*neutral_900", "table_radius": "*radius_lg", "table_row_focus": "*color_accent_soft", "table_row_focus_dark": "*color_accent_soft", "text_lg": "16px", "text_md": "14px", "text_sm": "12px", "text_xl": "22px", "text_xs": "10px", "text_xxl": "26px", "text_xxs": "9px"}, "version": "0.0.1"}
|