InvokeAI 2.2.4.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- backend/__init__.py +0 -0
- backend/invoke_ai_web_server.py +1724 -0
- backend/modules/__init__.py +0 -0
- backend/modules/create_cmd_parser.py +55 -0
- backend/modules/get_canvas_generation_mode.py +117 -0
- backend/modules/parameters.py +71 -0
- backend/modules/parse_seed_weights.py +47 -0
- configs/INITIAL_MODELS.yaml +80 -0
- configs/models.yaml.example +29 -0
- configs/sd-concepts.txt +803 -0
- configs/stable-diffusion/v1-finetune.yaml +110 -0
- configs/stable-diffusion/v1-finetune_style.yaml +103 -0
- configs/stable-diffusion/v1-inference.yaml +79 -0
- configs/stable-diffusion/v1-inpainting-inference.yaml +79 -0
- configs/stable-diffusion/v1-m1-finetune.yaml +110 -0
- docs/assets/invoke-web-server-1.png +0 -0
- docs/assets/invoke_ai_banner.png +0 -0
- invokeai-2.2.4.5.data/data/assets/caution.png +0 -0
- invokeai-2.2.4.5.data/data/configs/INITIAL_MODELS.yaml +80 -0
- invokeai-2.2.4.5.data/data/configs/models.yaml.example +29 -0
- invokeai-2.2.4.5.data/data/configs/sd-concepts.txt +803 -0
- invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-finetune.yaml +110 -0
- invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-finetune_style.yaml +103 -0
- invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-inference.yaml +79 -0
- invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-inpainting-inference.yaml +79 -0
- invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-m1-finetune.yaml +110 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/Inter-Bold.790c108b.ttf +0 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/Inter.b9a8e5e2.ttf +0 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/favicon.0d253ced.ico +0 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/index-legacy-b741077f.js +48 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/index.0dadf5d0.css +1 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/index.21ff81eb.js +625 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/logo.13003d72.png +0 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/polyfills-legacy-dde3a68a.js +4 -0
- invokeai-2.2.4.5.data/data/frontend/dist/assets/polyfills.1ff60148.js +1 -0
- invokeai-2.2.4.5.data/data/frontend/dist/index.html +23 -0
- invokeai-2.2.4.5.data/data/scripts/configure_invokeai.py +797 -0
- invokeai-2.2.4.5.data/data/scripts/create_root.py +43 -0
- invokeai-2.2.4.5.data/data/scripts/dream.py +10 -0
- invokeai-2.2.4.5.data/data/scripts/images2prompt.py +30 -0
- invokeai-2.2.4.5.data/data/scripts/invoke.py +5 -0
- invokeai-2.2.4.5.data/data/scripts/legacy_api.py +681 -0
- invokeai-2.2.4.5.data/data/scripts/load_models.py +12 -0
- invokeai-2.2.4.5.data/data/scripts/merge_embeddings.py +124 -0
- invokeai-2.2.4.5.data/data/scripts/preload_models.py +12 -0
- invokeai-2.2.4.5.data/data/scripts/sd-metadata.py +22 -0
- invokeai-2.2.4.5.dist-info/LICENSE +21 -0
- invokeai-2.2.4.5.dist-info/LICENSE-ModelWeights.txt +294 -0
- invokeai-2.2.4.5.dist-info/METADATA +288 -0
- invokeai-2.2.4.5.dist-info/RECORD +169 -0
- invokeai-2.2.4.5.dist-info/WHEEL +5 -0
- invokeai-2.2.4.5.dist-info/entry_points.txt +4 -0
- invokeai-2.2.4.5.dist-info/top_level.txt +6 -0
- invokeai-2.2.4.5.dist-info/zip-safe +1 -0
- ldm/__init__.py +0 -0
- ldm/data/__init__.py +0 -0
- ldm/data/base.py +31 -0
- ldm/data/imagenet.py +466 -0
- ldm/data/lsun.py +126 -0
- ldm/data/personalized.py +202 -0
- ldm/data/personalized_style.py +169 -0
- ldm/generate.py +1159 -0
- ldm/invoke/CLI.py +960 -0
- ldm/invoke/__init__.py +3 -0
- ldm/invoke/args.py +1257 -0
- ldm/invoke/concepts_lib.py +169 -0
- ldm/invoke/conditioning.py +289 -0
- ldm/invoke/devices.py +27 -0
- ldm/invoke/generator/__init__.py +4 -0
- ldm/invoke/generator/base.py +335 -0
- ldm/invoke/generator/embiggen.py +501 -0
- ldm/invoke/generator/img2img.py +97 -0
- ldm/invoke/generator/inpaint.py +358 -0
- ldm/invoke/generator/omnibus.py +175 -0
- ldm/invoke/generator/txt2img.py +88 -0
- ldm/invoke/generator/txt2img2img.py +182 -0
- ldm/invoke/globals.py +31 -0
- ldm/invoke/image_util.py +70 -0
- ldm/invoke/log.py +66 -0
- ldm/invoke/model_cache.py +449 -0
- ldm/invoke/patchmatch.py +44 -0
- ldm/invoke/pngwriter.py +113 -0
- ldm/invoke/prompt_parser.py +655 -0
- ldm/invoke/readline.py +442 -0
- ldm/invoke/restoration/__init__.py +4 -0
- ldm/invoke/restoration/base.py +38 -0
- ldm/invoke/restoration/codeformer.py +103 -0
- ldm/invoke/restoration/codeformer_arch.py +276 -0
- ldm/invoke/restoration/gfpgan.py +84 -0
- ldm/invoke/restoration/outcrop.py +108 -0
- ldm/invoke/restoration/outpaint.py +92 -0
- ldm/invoke/restoration/realesrgan.py +90 -0
- ldm/invoke/restoration/vqgan_arch.py +435 -0
- ldm/invoke/seamless.py +30 -0
- ldm/invoke/server.py +282 -0
- ldm/invoke/server_legacy.py +246 -0
- ldm/invoke/txt2mask.py +136 -0
- ldm/lr_scheduler.py +143 -0
- ldm/models/__init__.py +0 -0
- ldm/models/autoencoder.py +596 -0
- ldm/models/diffusion/__init__.py +0 -0
- ldm/models/diffusion/classifier.py +355 -0
- ldm/models/diffusion/cross_attention_control.py +443 -0
- ldm/models/diffusion/cross_attention_map_saving.py +95 -0
- ldm/models/diffusion/ddim.py +111 -0
- ldm/models/diffusion/ddpm.py +2263 -0
- ldm/models/diffusion/ksampler.py +312 -0
- ldm/models/diffusion/plms.py +146 -0
- ldm/models/diffusion/sampler.py +450 -0
- ldm/models/diffusion/shared_invokeai_diffusion.py +244 -0
- ldm/modules/__init__.py +0 -0
- ldm/modules/attention.py +274 -0
- ldm/modules/diffusionmodules/__init__.py +0 -0
- ldm/modules/diffusionmodules/model.py +894 -0
- ldm/modules/diffusionmodules/openaimodel.py +1036 -0
- ldm/modules/diffusionmodules/util.py +314 -0
- ldm/modules/distributions/__init__.py +0 -0
- ldm/modules/distributions/distributions.py +104 -0
- ldm/modules/ema.py +88 -0
- ldm/modules/embedding_manager.py +413 -0
- ldm/modules/encoders/__init__.py +0 -0
- ldm/modules/encoders/modules.py +772 -0
- ldm/modules/image_degradation/__init__.py +6 -0
- ldm/modules/image_degradation/bsrgan.py +846 -0
- ldm/modules/image_degradation/bsrgan_light.py +751 -0
- ldm/modules/image_degradation/utils_image.py +1024 -0
- ldm/modules/losses/__init__.py +1 -0
- ldm/modules/losses/contperceptual.py +175 -0
- ldm/modules/losses/vqperceptual.py +240 -0
- ldm/modules/x_transformer.py +752 -0
- ldm/simplet2i.py +13 -0
- ldm/util.py +264 -0
- scripts/configure_invokeai.py +797 -0
- scripts/create_root.py +43 -0
- scripts/dream.py +10 -0
- scripts/images2prompt.py +30 -0
- scripts/invoke.py +5 -0
- scripts/legacy_api.py +681 -0
- scripts/load_models.py +12 -0
- scripts/merge_embeddings.py +124 -0
- scripts/orig_scripts/img2img.py +296 -0
- scripts/orig_scripts/inpaint.py +98 -0
- scripts/orig_scripts/knn2img.py +397 -0
- scripts/orig_scripts/sample_diffusion.py +313 -0
- scripts/orig_scripts/train_searcher.py +147 -0
- scripts/orig_scripts/txt2img.py +324 -0
- scripts/preload_models.py +12 -0
- scripts/sd-metadata.py +22 -0
- vendored/clip/clip/__init__.py +1 -0
- vendored/clip/clip/bpe_simple_vocab_16e6.txt.gz +0 -0
- vendored/clip/clip/clip.py +237 -0
- vendored/clip/clip/model.py +436 -0
- vendored/clip/clip/simple_tokenizer.py +132 -0
- vendored/clip/hubconf.py +42 -0
- vendored/clip/setup.py +21 -0
- vendored/clip/tests/test_consistency.py +25 -0
- vendored/clipseg/datasets/coco_wrapper.py +99 -0
- vendored/clipseg/datasets/pascal_zeroshot.py +60 -0
- vendored/clipseg/datasets/pfe_dataset.py +129 -0
- vendored/clipseg/datasets/phrasecut.py +380 -0
- vendored/clipseg/datasets/utils.py +68 -0
- vendored/clipseg/evaluation_utils.py +292 -0
- vendored/clipseg/general_utils.py +272 -0
- vendored/clipseg/metrics.py +271 -0
- vendored/clipseg/models/clipseg.py +538 -0
- vendored/clipseg/models/vitseg.py +286 -0
- vendored/clipseg/score.py +453 -0
- vendored/clipseg/setup.py +30 -0
- vendored/clipseg/training.py +266 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
from torch.functional import Tensor
|
|
2
|
+
|
|
3
|
+
import torch
|
|
4
|
+
import inspect
|
|
5
|
+
import json
|
|
6
|
+
import yaml
|
|
7
|
+
import time
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
from general_utils import log
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
from os.path import expanduser, join, isfile, realpath
|
|
14
|
+
|
|
15
|
+
from torch.utils.data import DataLoader
|
|
16
|
+
|
|
17
|
+
from metrics import FixedIntervalMetrics
|
|
18
|
+
|
|
19
|
+
from general_utils import load_model, log, score_config_from_cli_args, AttributeDict, get_attribute, filter_args
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
DATASET_CACHE = dict()
|
|
23
|
+
|
|
24
|
+
def load_model(checkpoint_id, weights_file=None, strict=True, model_args='from_config', with_config=False, ignore_weights=False):
|
|
25
|
+
|
|
26
|
+
config = json.load(open(join('logs', checkpoint_id, 'config.json')))
|
|
27
|
+
|
|
28
|
+
if model_args != 'from_config' and type(model_args) != dict:
|
|
29
|
+
raise ValueError('model_args must either be "from_config" or a dictionary of values')
|
|
30
|
+
|
|
31
|
+
model_cls = get_attribute(config['model'])
|
|
32
|
+
|
|
33
|
+
# load model
|
|
34
|
+
if model_args == 'from_config':
|
|
35
|
+
_, model_args, _ = filter_args(config, inspect.signature(model_cls).parameters)
|
|
36
|
+
|
|
37
|
+
model = model_cls(**model_args)
|
|
38
|
+
|
|
39
|
+
if weights_file is None:
|
|
40
|
+
weights_file = realpath(join('logs', checkpoint_id, 'weights.pth'))
|
|
41
|
+
else:
|
|
42
|
+
weights_file = realpath(join('logs', checkpoint_id, weights_file))
|
|
43
|
+
|
|
44
|
+
if isfile(weights_file) and not ignore_weights:
|
|
45
|
+
weights = torch.load(weights_file)
|
|
46
|
+
for _, w in weights.items():
|
|
47
|
+
assert not torch.any(torch.isnan(w)), 'weights contain NaNs'
|
|
48
|
+
model.load_state_dict(weights, strict=strict)
|
|
49
|
+
else:
|
|
50
|
+
if not ignore_weights:
|
|
51
|
+
raise FileNotFoundError(f'model checkpoint {weights_file} was not found')
|
|
52
|
+
|
|
53
|
+
if with_config:
|
|
54
|
+
return model, config
|
|
55
|
+
|
|
56
|
+
return model
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def compute_shift2(model, datasets, seed=123, repetitions=1):
|
|
60
|
+
""" computes shift """
|
|
61
|
+
|
|
62
|
+
model.eval()
|
|
63
|
+
model.cuda()
|
|
64
|
+
|
|
65
|
+
import random
|
|
66
|
+
random.seed(seed)
|
|
67
|
+
|
|
68
|
+
preds, gts = [], []
|
|
69
|
+
for i_dataset, dataset in enumerate(datasets):
|
|
70
|
+
|
|
71
|
+
loader = DataLoader(dataset, batch_size=1, num_workers=0, shuffle=False, drop_last=False)
|
|
72
|
+
|
|
73
|
+
max_iterations = int(repetitions * len(dataset.dataset.data_list))
|
|
74
|
+
|
|
75
|
+
with torch.no_grad():
|
|
76
|
+
|
|
77
|
+
i, losses = 0, []
|
|
78
|
+
for i_all, (data_x, data_y) in enumerate(loader):
|
|
79
|
+
|
|
80
|
+
data_x = [v.cuda(non_blocking=True) if v is not None else v for v in data_x]
|
|
81
|
+
data_y = [v.cuda(non_blocking=True) if v is not None else v for v in data_y]
|
|
82
|
+
|
|
83
|
+
pred, = model(data_x[0], data_x[1], data_x[2])
|
|
84
|
+
preds += [pred.detach()]
|
|
85
|
+
gts += [data_y]
|
|
86
|
+
|
|
87
|
+
i += 1
|
|
88
|
+
if max_iterations and i >= max_iterations:
|
|
89
|
+
break
|
|
90
|
+
|
|
91
|
+
from metrics import FixedIntervalMetrics
|
|
92
|
+
n_values = 51
|
|
93
|
+
thresholds = np.linspace(0, 1, n_values)[1:-1]
|
|
94
|
+
metric = FixedIntervalMetrics(resize_pred=True, sigmoid=True, n_values=n_values)
|
|
95
|
+
|
|
96
|
+
for p, y in zip(preds, gts):
|
|
97
|
+
metric.add(p.unsqueeze(1), y)
|
|
98
|
+
|
|
99
|
+
best_idx = np.argmax(metric.value()['fgiou_scores'])
|
|
100
|
+
best_thresh = thresholds[best_idx]
|
|
101
|
+
|
|
102
|
+
return best_thresh
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def get_cached_pascal_pfe(split, config):
|
|
106
|
+
from datasets.pfe_dataset import PFEPascalWrapper
|
|
107
|
+
try:
|
|
108
|
+
dataset = DATASET_CACHE[(split, config.image_size, config.label_support, config.mask)]
|
|
109
|
+
except KeyError:
|
|
110
|
+
dataset = PFEPascalWrapper(mode='val', split=split, mask=config.mask, image_size=config.image_size, label_support=config.label_support)
|
|
111
|
+
DATASET_CACHE[(split, config.image_size, config.label_support, config.mask)] = dataset
|
|
112
|
+
return dataset
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def main():
|
|
118
|
+
config, train_checkpoint_id = score_config_from_cli_args()
|
|
119
|
+
|
|
120
|
+
metrics = score(config, train_checkpoint_id, None)
|
|
121
|
+
|
|
122
|
+
for dataset in metrics.keys():
|
|
123
|
+
for k in metrics[dataset]:
|
|
124
|
+
if type(metrics[dataset][k]) in {float, int}:
|
|
125
|
+
print(dataset, f'{k:<16} {metrics[dataset][k]:.3f}')
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def score(config, train_checkpoint_id, train_config):
|
|
129
|
+
|
|
130
|
+
config = AttributeDict(config)
|
|
131
|
+
|
|
132
|
+
print(config)
|
|
133
|
+
|
|
134
|
+
# use training dataset and loss
|
|
135
|
+
train_config = AttributeDict(json.load(open(f'logs/{train_checkpoint_id}/config.json')))
|
|
136
|
+
|
|
137
|
+
cp_str = f'_{config.iteration_cp}' if config.iteration_cp is not None else ''
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
model_cls = get_attribute(train_config['model'])
|
|
141
|
+
|
|
142
|
+
_, model_args, _ = filter_args(train_config, inspect.signature(model_cls).parameters)
|
|
143
|
+
|
|
144
|
+
model_args = {**model_args, **{k: config[k] for k in ['process_cond', 'fix_shift'] if k in config}}
|
|
145
|
+
|
|
146
|
+
strict_models = {'ConditionBase4', 'PFENetWrapper'}
|
|
147
|
+
model = load_model(train_checkpoint_id, strict=model_cls.__name__ in strict_models, model_args=model_args,
|
|
148
|
+
weights_file=f'weights{cp_str}.pth', )
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
model.eval()
|
|
152
|
+
model.cuda()
|
|
153
|
+
|
|
154
|
+
metric_args = dict()
|
|
155
|
+
|
|
156
|
+
if 'threshold' in config:
|
|
157
|
+
if config.metric.split('.')[-1] == 'SkLearnMetrics':
|
|
158
|
+
metric_args['threshold'] = config.threshold
|
|
159
|
+
|
|
160
|
+
if 'resize_to' in config:
|
|
161
|
+
metric_args['resize_to'] = config.resize_to
|
|
162
|
+
|
|
163
|
+
if 'sigmoid' in config:
|
|
164
|
+
metric_args['sigmoid'] = config.sigmoid
|
|
165
|
+
|
|
166
|
+
if 'custom_threshold' in config:
|
|
167
|
+
metric_args['custom_threshold'] = config.custom_threshold
|
|
168
|
+
|
|
169
|
+
if config.test_dataset == 'pascal':
|
|
170
|
+
|
|
171
|
+
loss_fn = get_attribute(train_config.loss)
|
|
172
|
+
# assume that if no split is specified in train_config, test on all splits,
|
|
173
|
+
|
|
174
|
+
if 'splits' in config:
|
|
175
|
+
splits = config.splits
|
|
176
|
+
else:
|
|
177
|
+
if 'split' in train_config and type(train_config.split) == int:
|
|
178
|
+
# unless train_config has a split set, in that case assume train mode in training
|
|
179
|
+
splits = [train_config.split]
|
|
180
|
+
assert train_config.mode == 'train'
|
|
181
|
+
else:
|
|
182
|
+
splits = [0,1,2,3]
|
|
183
|
+
|
|
184
|
+
log.info('Test on these splits', splits)
|
|
185
|
+
|
|
186
|
+
scores = dict()
|
|
187
|
+
for split in splits:
|
|
188
|
+
|
|
189
|
+
shift = config.shift if 'shift' in config else 0
|
|
190
|
+
|
|
191
|
+
# automatic shift
|
|
192
|
+
if shift == 'auto':
|
|
193
|
+
shift_compute_t = time.time()
|
|
194
|
+
shift = compute_shift2(model, [get_cached_pascal_pfe(s, config) for s in range(4) if s != split], repetitions=config.compute_shift_fac)
|
|
195
|
+
log.info(f'Best threshold is {shift}, computed on splits: {[s for s in range(4) if s != split]}, took {time.time() - shift_compute_t:.1f}s')
|
|
196
|
+
|
|
197
|
+
dataset = get_cached_pascal_pfe(split, config)
|
|
198
|
+
|
|
199
|
+
eval_start_t = time.time()
|
|
200
|
+
|
|
201
|
+
loader = DataLoader(dataset, batch_size=1, num_workers=0, shuffle=False, drop_last=False)
|
|
202
|
+
|
|
203
|
+
assert config.batch_size is None or config.batch_size == 1, 'When PFE Dataset is used, batch size must be 1'
|
|
204
|
+
|
|
205
|
+
metric = FixedIntervalMetrics(resize_pred=True, sigmoid=True, custom_threshold=shift, **metric_args)
|
|
206
|
+
|
|
207
|
+
with torch.no_grad():
|
|
208
|
+
|
|
209
|
+
i, losses = 0, []
|
|
210
|
+
for i_all, (data_x, data_y) in enumerate(loader):
|
|
211
|
+
|
|
212
|
+
data_x = [v.cuda(non_blocking=True) if isinstance(v, torch.Tensor) else v for v in data_x]
|
|
213
|
+
data_y = [v.cuda(non_blocking=True) if isinstance(v, torch.Tensor) else v for v in data_y]
|
|
214
|
+
|
|
215
|
+
if config.mask == 'separate': # for old CondBase model
|
|
216
|
+
pred, = model(data_x[0], data_x[1], data_x[2])
|
|
217
|
+
else:
|
|
218
|
+
# assert config.mask in {'text', 'highlight'}
|
|
219
|
+
pred, _, _, _ = model(data_x[0], data_x[1], return_features=True)
|
|
220
|
+
|
|
221
|
+
# loss = loss_fn(pred, data_y[0])
|
|
222
|
+
metric.add(pred.unsqueeze(1) + shift, data_y)
|
|
223
|
+
|
|
224
|
+
# losses += [float(loss)]
|
|
225
|
+
|
|
226
|
+
i += 1
|
|
227
|
+
if config.max_iterations and i >= config.max_iterations:
|
|
228
|
+
break
|
|
229
|
+
|
|
230
|
+
#scores[split] = {m: s for m, s in zip(metric.names(), metric.value())}
|
|
231
|
+
|
|
232
|
+
log.info(f'Dataset length: {len(dataset)}, took {time.time() - eval_start_t:.1f}s to evaluate.')
|
|
233
|
+
|
|
234
|
+
print(metric.value()['mean_iou_scores'])
|
|
235
|
+
|
|
236
|
+
scores[split] = metric.scores()
|
|
237
|
+
|
|
238
|
+
log.info(f'Completed split {split}')
|
|
239
|
+
|
|
240
|
+
key_prefix = config['name'] if 'name' in config else 'pas'
|
|
241
|
+
|
|
242
|
+
all_keys = set.intersection(*[set(v.keys()) for v in scores.values()])
|
|
243
|
+
|
|
244
|
+
valid_keys = [k for k in all_keys if all(v[k] is not None and isinstance(v[k], (int, float, np.float)) for v in scores.values())]
|
|
245
|
+
|
|
246
|
+
return {key_prefix: {k: np.mean([s[k] for s in scores.values()]) for k in valid_keys}}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
if config.test_dataset == 'coco':
|
|
250
|
+
from datasets.coco_wrapper import COCOWrapper
|
|
251
|
+
|
|
252
|
+
coco_dataset = COCOWrapper('test', fold=train_config.fold, image_size=train_config.image_size, mask=config.mask,
|
|
253
|
+
with_class_label=True)
|
|
254
|
+
|
|
255
|
+
log.info('Dataset length', len(coco_dataset))
|
|
256
|
+
loader = DataLoader(coco_dataset, batch_size=config.batch_size, num_workers=2, shuffle=False, drop_last=False)
|
|
257
|
+
|
|
258
|
+
metric = get_attribute(config.metric)(resize_pred=True, **metric_args)
|
|
259
|
+
|
|
260
|
+
shift = config.shift if 'shift' in config else 0
|
|
261
|
+
|
|
262
|
+
with torch.no_grad():
|
|
263
|
+
|
|
264
|
+
i, losses = 0, []
|
|
265
|
+
for i_all, (data_x, data_y) in enumerate(loader):
|
|
266
|
+
data_x = [v.cuda(non_blocking=True) if isinstance(v, torch.Tensor) else v for v in data_x]
|
|
267
|
+
data_y = [v.cuda(non_blocking=True) if isinstance(v, torch.Tensor) else v for v in data_y]
|
|
268
|
+
|
|
269
|
+
if config.mask == 'separate': # for old CondBase model
|
|
270
|
+
pred, = model(data_x[0], data_x[1], data_x[2])
|
|
271
|
+
else:
|
|
272
|
+
# assert config.mask in {'text', 'highlight'}
|
|
273
|
+
pred, _, _, _ = model(data_x[0], data_x[1], return_features=True)
|
|
274
|
+
|
|
275
|
+
metric.add([pred + shift], data_y)
|
|
276
|
+
|
|
277
|
+
i += 1
|
|
278
|
+
if config.max_iterations and i >= config.max_iterations:
|
|
279
|
+
break
|
|
280
|
+
|
|
281
|
+
key_prefix = config['name'] if 'name' in config else 'coco'
|
|
282
|
+
return {key_prefix: metric.scores()}
|
|
283
|
+
#return {key_prefix: {k: v for k, v in zip(metric.names(), metric.value())}}
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
if config.test_dataset == 'phrasecut':
|
|
287
|
+
from datasets.phrasecut import PhraseCut
|
|
288
|
+
|
|
289
|
+
only_visual = config.only_visual is not None and config.only_visual
|
|
290
|
+
with_visual = config.with_visual is not None and config.with_visual
|
|
291
|
+
|
|
292
|
+
dataset = PhraseCut('test',
|
|
293
|
+
image_size=train_config.image_size,
|
|
294
|
+
mask=config.mask,
|
|
295
|
+
with_visual=with_visual, only_visual=only_visual, aug_crop=False,
|
|
296
|
+
aug_color=False)
|
|
297
|
+
|
|
298
|
+
loader = DataLoader(dataset, batch_size=config.batch_size, num_workers=2, shuffle=False, drop_last=False)
|
|
299
|
+
metric = get_attribute(config.metric)(resize_pred=True, **metric_args)
|
|
300
|
+
|
|
301
|
+
shift = config.shift if 'shift' in config else 0
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
with torch.no_grad():
|
|
305
|
+
|
|
306
|
+
i, losses = 0, []
|
|
307
|
+
for i_all, (data_x, data_y) in enumerate(loader):
|
|
308
|
+
data_x = [v.cuda(non_blocking=True) if isinstance(v, torch.Tensor) else v for v in data_x]
|
|
309
|
+
data_y = [v.cuda(non_blocking=True) if isinstance(v, torch.Tensor) else v for v in data_y]
|
|
310
|
+
|
|
311
|
+
pred, _, _, _ = model(data_x[0], data_x[1], return_features=True)
|
|
312
|
+
metric.add([pred + shift], data_y)
|
|
313
|
+
|
|
314
|
+
i += 1
|
|
315
|
+
if config.max_iterations and i >= config.max_iterations:
|
|
316
|
+
break
|
|
317
|
+
|
|
318
|
+
key_prefix = config['name'] if 'name' in config else 'phrasecut'
|
|
319
|
+
return {key_prefix: metric.scores()}
|
|
320
|
+
#return {key_prefix: {k: v for k, v in zip(metric.names(), metric.value())}}
|
|
321
|
+
|
|
322
|
+
if config.test_dataset == 'pascal_zs':
|
|
323
|
+
from third_party.JoEm.model.metric import Evaluator
|
|
324
|
+
from third_party.JoEm.data_loader import get_seen_idx, get_unseen_idx, VOC
|
|
325
|
+
from datasets.pascal_zeroshot import PascalZeroShot, PASCAL_VOC_CLASSES_ZS
|
|
326
|
+
|
|
327
|
+
from models.clipseg import CLIPSegMultiLabel
|
|
328
|
+
|
|
329
|
+
n_unseen = train_config.remove_classes[1]
|
|
330
|
+
|
|
331
|
+
pz = PascalZeroShot('val', n_unseen, image_size=352)
|
|
332
|
+
m = CLIPSegMultiLabel(model=train_config.name).cuda()
|
|
333
|
+
m.eval();
|
|
334
|
+
|
|
335
|
+
print(len(pz), n_unseen)
|
|
336
|
+
print('training removed', [c for class_set in PASCAL_VOC_CLASSES_ZS[:n_unseen // 2] for c in class_set])
|
|
337
|
+
|
|
338
|
+
print('unseen', [VOC[i] for i in get_unseen_idx(n_unseen)])
|
|
339
|
+
print('seen', [VOC[i] for i in get_seen_idx(n_unseen)])
|
|
340
|
+
|
|
341
|
+
loader = DataLoader(pz, batch_size=8)
|
|
342
|
+
evaluator = Evaluator(21, get_unseen_idx(n_unseen), get_seen_idx(n_unseen))
|
|
343
|
+
|
|
344
|
+
for i, (data_x, data_y) in enumerate(loader):
|
|
345
|
+
pred = m(data_x[0].cuda())
|
|
346
|
+
evaluator.add_batch(data_y[0].numpy(), pred.argmax(1).cpu().detach().numpy())
|
|
347
|
+
|
|
348
|
+
if config.max_iter is not None and i > config.max_iter:
|
|
349
|
+
break
|
|
350
|
+
|
|
351
|
+
scores = evaluator.Mean_Intersection_over_Union()
|
|
352
|
+
key_prefix = config['name'] if 'name' in config else 'pas_zs'
|
|
353
|
+
|
|
354
|
+
return {key_prefix: {k: scores[k] for k in ['seen', 'unseen', 'harmonic', 'overall']}}
|
|
355
|
+
|
|
356
|
+
elif config.test_dataset in {'same_as_training', 'affordance'}:
|
|
357
|
+
loss_fn = get_attribute(train_config.loss)
|
|
358
|
+
|
|
359
|
+
metric_cls = get_attribute(config.metric)
|
|
360
|
+
metric = metric_cls(**metric_args)
|
|
361
|
+
|
|
362
|
+
if config.test_dataset == 'same_as_training':
|
|
363
|
+
dataset_cls = get_attribute(train_config.dataset)
|
|
364
|
+
elif config.test_dataset == 'affordance':
|
|
365
|
+
dataset_cls = get_attribute('datasets.lvis_oneshot3.LVIS_Affordance')
|
|
366
|
+
dataset_name = 'aff'
|
|
367
|
+
else:
|
|
368
|
+
dataset_cls = get_attribute('datasets.lvis_oneshot3.LVIS_OneShot')
|
|
369
|
+
dataset_name = 'lvis'
|
|
370
|
+
|
|
371
|
+
_, dataset_args, _ = filter_args(config, inspect.signature(dataset_cls).parameters)
|
|
372
|
+
|
|
373
|
+
dataset_args['image_size'] = train_config.image_size # explicitly use training image size for evaluation
|
|
374
|
+
|
|
375
|
+
if model.__class__.__name__ == 'PFENetWrapper':
|
|
376
|
+
dataset_args['image_size'] = config.image_size
|
|
377
|
+
|
|
378
|
+
log.info('init dataset', str(dataset_cls))
|
|
379
|
+
dataset = dataset_cls(**dataset_args)
|
|
380
|
+
|
|
381
|
+
log.info(f'Score on {model.__class__.__name__} on {dataset_cls.__name__}')
|
|
382
|
+
|
|
383
|
+
data_loader = torch.utils.data.DataLoader(dataset, batch_size=config.batch_size, shuffle=config.shuffle)
|
|
384
|
+
|
|
385
|
+
# explicitly set prompts
|
|
386
|
+
if config.prompt == 'plain':
|
|
387
|
+
model.prompt_list = ['{}']
|
|
388
|
+
elif config.prompt == 'fixed':
|
|
389
|
+
model.prompt_list = ['a photo of a {}.']
|
|
390
|
+
elif config.prompt == 'shuffle':
|
|
391
|
+
model.prompt_list = ['a photo of a {}.', 'a photograph of a {}.', 'an image of a {}.', '{}.']
|
|
392
|
+
elif config.prompt == 'shuffle_clip':
|
|
393
|
+
from models.clip_prompts import imagenet_templates
|
|
394
|
+
model.prompt_list = imagenet_templates
|
|
395
|
+
|
|
396
|
+
config.assume_no_unused_keys(exceptions=['max_iterations'])
|
|
397
|
+
|
|
398
|
+
t_start = time.time()
|
|
399
|
+
|
|
400
|
+
with torch.no_grad(): # TODO: switch to inference_mode (torch 1.9)
|
|
401
|
+
i, losses = 0, []
|
|
402
|
+
for data_x, data_y in data_loader:
|
|
403
|
+
|
|
404
|
+
data_x = [x.cuda() if isinstance(x, torch.Tensor) else x for x in data_x]
|
|
405
|
+
data_y = [x.cuda() if isinstance(x, torch.Tensor) else x for x in data_y]
|
|
406
|
+
|
|
407
|
+
if model.__class__.__name__ in {'ConditionBase4', 'PFENetWrapper'}:
|
|
408
|
+
pred, = model(data_x[0], data_x[1], data_x[2])
|
|
409
|
+
visual_q = None
|
|
410
|
+
else:
|
|
411
|
+
pred, visual_q, _, _ = model(data_x[0], data_x[1], return_features=True)
|
|
412
|
+
|
|
413
|
+
loss = loss_fn(pred, data_y[0])
|
|
414
|
+
|
|
415
|
+
metric.add([pred], data_y)
|
|
416
|
+
|
|
417
|
+
losses += [float(loss)]
|
|
418
|
+
|
|
419
|
+
i += 1
|
|
420
|
+
if config.max_iterations and i >= config.max_iterations:
|
|
421
|
+
break
|
|
422
|
+
|
|
423
|
+
# scores = {m: s for m, s in zip(metric.names(), metric.value())}
|
|
424
|
+
scores = metric.scores()
|
|
425
|
+
|
|
426
|
+
keys = set(scores.keys())
|
|
427
|
+
if dataset.negative_prob > 0 and 'mIoU' in keys:
|
|
428
|
+
keys.remove('mIoU')
|
|
429
|
+
|
|
430
|
+
name_mask = dataset.mask.replace('text_label', 'txt')[:3]
|
|
431
|
+
name_neg = '' if dataset.negative_prob == 0 else '_' + str(dataset.negative_prob)
|
|
432
|
+
|
|
433
|
+
score_name = config.name if 'name' in config else f'{dataset_name}_{name_mask}{name_neg}'
|
|
434
|
+
|
|
435
|
+
scores = {score_name: {k: v for k,v in scores.items() if k in keys}}
|
|
436
|
+
scores[score_name].update({'test_loss': np.mean(losses)})
|
|
437
|
+
|
|
438
|
+
log.info(f'Evaluation took {time.time() - t_start:.1f}s')
|
|
439
|
+
|
|
440
|
+
return scores
|
|
441
|
+
else:
|
|
442
|
+
raise ValueError('invalid test dataset')
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
if __name__ == '__main__':
|
|
453
|
+
main()
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
|
|
3
|
+
with open("README.md", "r", encoding="utf-8") as readme_file:
|
|
4
|
+
readme = readme_file.read()
|
|
5
|
+
|
|
6
|
+
requirements = [
|
|
7
|
+
"numpy",
|
|
8
|
+
"scipy",
|
|
9
|
+
"matplotlib",
|
|
10
|
+
"torch",
|
|
11
|
+
"torchvision",
|
|
12
|
+
"opencv-python",
|
|
13
|
+
"CLIP @ git+https://github.com/openai/CLIP.git"
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
setup(
|
|
17
|
+
name='clipseg',
|
|
18
|
+
packages=['clipseg'],
|
|
19
|
+
package_dir={'clipseg': 'models'},
|
|
20
|
+
package_data={'clipseg': [
|
|
21
|
+
"../weights/*.pth",
|
|
22
|
+
]},
|
|
23
|
+
version='0.0.1',
|
|
24
|
+
url='https://github.com/timojl/clipseg',
|
|
25
|
+
python_requires='>=3.9',
|
|
26
|
+
install_requires=requirements,
|
|
27
|
+
description='This repository contains the code used in the paper "Image Segmentation Using Text and Image Prompts".',
|
|
28
|
+
long_description=readme,
|
|
29
|
+
long_description_content_type="text/markdown",
|
|
30
|
+
)
|