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.
Files changed (169) hide show
  1. backend/__init__.py +0 -0
  2. backend/invoke_ai_web_server.py +1724 -0
  3. backend/modules/__init__.py +0 -0
  4. backend/modules/create_cmd_parser.py +55 -0
  5. backend/modules/get_canvas_generation_mode.py +117 -0
  6. backend/modules/parameters.py +71 -0
  7. backend/modules/parse_seed_weights.py +47 -0
  8. configs/INITIAL_MODELS.yaml +80 -0
  9. configs/models.yaml.example +29 -0
  10. configs/sd-concepts.txt +803 -0
  11. configs/stable-diffusion/v1-finetune.yaml +110 -0
  12. configs/stable-diffusion/v1-finetune_style.yaml +103 -0
  13. configs/stable-diffusion/v1-inference.yaml +79 -0
  14. configs/stable-diffusion/v1-inpainting-inference.yaml +79 -0
  15. configs/stable-diffusion/v1-m1-finetune.yaml +110 -0
  16. docs/assets/invoke-web-server-1.png +0 -0
  17. docs/assets/invoke_ai_banner.png +0 -0
  18. invokeai-2.2.4.5.data/data/assets/caution.png +0 -0
  19. invokeai-2.2.4.5.data/data/configs/INITIAL_MODELS.yaml +80 -0
  20. invokeai-2.2.4.5.data/data/configs/models.yaml.example +29 -0
  21. invokeai-2.2.4.5.data/data/configs/sd-concepts.txt +803 -0
  22. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-finetune.yaml +110 -0
  23. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-finetune_style.yaml +103 -0
  24. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-inference.yaml +79 -0
  25. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-inpainting-inference.yaml +79 -0
  26. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-m1-finetune.yaml +110 -0
  27. invokeai-2.2.4.5.data/data/frontend/dist/assets/Inter-Bold.790c108b.ttf +0 -0
  28. invokeai-2.2.4.5.data/data/frontend/dist/assets/Inter.b9a8e5e2.ttf +0 -0
  29. invokeai-2.2.4.5.data/data/frontend/dist/assets/favicon.0d253ced.ico +0 -0
  30. invokeai-2.2.4.5.data/data/frontend/dist/assets/index-legacy-b741077f.js +48 -0
  31. invokeai-2.2.4.5.data/data/frontend/dist/assets/index.0dadf5d0.css +1 -0
  32. invokeai-2.2.4.5.data/data/frontend/dist/assets/index.21ff81eb.js +625 -0
  33. invokeai-2.2.4.5.data/data/frontend/dist/assets/logo.13003d72.png +0 -0
  34. invokeai-2.2.4.5.data/data/frontend/dist/assets/polyfills-legacy-dde3a68a.js +4 -0
  35. invokeai-2.2.4.5.data/data/frontend/dist/assets/polyfills.1ff60148.js +1 -0
  36. invokeai-2.2.4.5.data/data/frontend/dist/index.html +23 -0
  37. invokeai-2.2.4.5.data/data/scripts/configure_invokeai.py +797 -0
  38. invokeai-2.2.4.5.data/data/scripts/create_root.py +43 -0
  39. invokeai-2.2.4.5.data/data/scripts/dream.py +10 -0
  40. invokeai-2.2.4.5.data/data/scripts/images2prompt.py +30 -0
  41. invokeai-2.2.4.5.data/data/scripts/invoke.py +5 -0
  42. invokeai-2.2.4.5.data/data/scripts/legacy_api.py +681 -0
  43. invokeai-2.2.4.5.data/data/scripts/load_models.py +12 -0
  44. invokeai-2.2.4.5.data/data/scripts/merge_embeddings.py +124 -0
  45. invokeai-2.2.4.5.data/data/scripts/preload_models.py +12 -0
  46. invokeai-2.2.4.5.data/data/scripts/sd-metadata.py +22 -0
  47. invokeai-2.2.4.5.dist-info/LICENSE +21 -0
  48. invokeai-2.2.4.5.dist-info/LICENSE-ModelWeights.txt +294 -0
  49. invokeai-2.2.4.5.dist-info/METADATA +288 -0
  50. invokeai-2.2.4.5.dist-info/RECORD +169 -0
  51. invokeai-2.2.4.5.dist-info/WHEEL +5 -0
  52. invokeai-2.2.4.5.dist-info/entry_points.txt +4 -0
  53. invokeai-2.2.4.5.dist-info/top_level.txt +6 -0
  54. invokeai-2.2.4.5.dist-info/zip-safe +1 -0
  55. ldm/__init__.py +0 -0
  56. ldm/data/__init__.py +0 -0
  57. ldm/data/base.py +31 -0
  58. ldm/data/imagenet.py +466 -0
  59. ldm/data/lsun.py +126 -0
  60. ldm/data/personalized.py +202 -0
  61. ldm/data/personalized_style.py +169 -0
  62. ldm/generate.py +1159 -0
  63. ldm/invoke/CLI.py +960 -0
  64. ldm/invoke/__init__.py +3 -0
  65. ldm/invoke/args.py +1257 -0
  66. ldm/invoke/concepts_lib.py +169 -0
  67. ldm/invoke/conditioning.py +289 -0
  68. ldm/invoke/devices.py +27 -0
  69. ldm/invoke/generator/__init__.py +4 -0
  70. ldm/invoke/generator/base.py +335 -0
  71. ldm/invoke/generator/embiggen.py +501 -0
  72. ldm/invoke/generator/img2img.py +97 -0
  73. ldm/invoke/generator/inpaint.py +358 -0
  74. ldm/invoke/generator/omnibus.py +175 -0
  75. ldm/invoke/generator/txt2img.py +88 -0
  76. ldm/invoke/generator/txt2img2img.py +182 -0
  77. ldm/invoke/globals.py +31 -0
  78. ldm/invoke/image_util.py +70 -0
  79. ldm/invoke/log.py +66 -0
  80. ldm/invoke/model_cache.py +449 -0
  81. ldm/invoke/patchmatch.py +44 -0
  82. ldm/invoke/pngwriter.py +113 -0
  83. ldm/invoke/prompt_parser.py +655 -0
  84. ldm/invoke/readline.py +442 -0
  85. ldm/invoke/restoration/__init__.py +4 -0
  86. ldm/invoke/restoration/base.py +38 -0
  87. ldm/invoke/restoration/codeformer.py +103 -0
  88. ldm/invoke/restoration/codeformer_arch.py +276 -0
  89. ldm/invoke/restoration/gfpgan.py +84 -0
  90. ldm/invoke/restoration/outcrop.py +108 -0
  91. ldm/invoke/restoration/outpaint.py +92 -0
  92. ldm/invoke/restoration/realesrgan.py +90 -0
  93. ldm/invoke/restoration/vqgan_arch.py +435 -0
  94. ldm/invoke/seamless.py +30 -0
  95. ldm/invoke/server.py +282 -0
  96. ldm/invoke/server_legacy.py +246 -0
  97. ldm/invoke/txt2mask.py +136 -0
  98. ldm/lr_scheduler.py +143 -0
  99. ldm/models/__init__.py +0 -0
  100. ldm/models/autoencoder.py +596 -0
  101. ldm/models/diffusion/__init__.py +0 -0
  102. ldm/models/diffusion/classifier.py +355 -0
  103. ldm/models/diffusion/cross_attention_control.py +443 -0
  104. ldm/models/diffusion/cross_attention_map_saving.py +95 -0
  105. ldm/models/diffusion/ddim.py +111 -0
  106. ldm/models/diffusion/ddpm.py +2263 -0
  107. ldm/models/diffusion/ksampler.py +312 -0
  108. ldm/models/diffusion/plms.py +146 -0
  109. ldm/models/diffusion/sampler.py +450 -0
  110. ldm/models/diffusion/shared_invokeai_diffusion.py +244 -0
  111. ldm/modules/__init__.py +0 -0
  112. ldm/modules/attention.py +274 -0
  113. ldm/modules/diffusionmodules/__init__.py +0 -0
  114. ldm/modules/diffusionmodules/model.py +894 -0
  115. ldm/modules/diffusionmodules/openaimodel.py +1036 -0
  116. ldm/modules/diffusionmodules/util.py +314 -0
  117. ldm/modules/distributions/__init__.py +0 -0
  118. ldm/modules/distributions/distributions.py +104 -0
  119. ldm/modules/ema.py +88 -0
  120. ldm/modules/embedding_manager.py +413 -0
  121. ldm/modules/encoders/__init__.py +0 -0
  122. ldm/modules/encoders/modules.py +772 -0
  123. ldm/modules/image_degradation/__init__.py +6 -0
  124. ldm/modules/image_degradation/bsrgan.py +846 -0
  125. ldm/modules/image_degradation/bsrgan_light.py +751 -0
  126. ldm/modules/image_degradation/utils_image.py +1024 -0
  127. ldm/modules/losses/__init__.py +1 -0
  128. ldm/modules/losses/contperceptual.py +175 -0
  129. ldm/modules/losses/vqperceptual.py +240 -0
  130. ldm/modules/x_transformer.py +752 -0
  131. ldm/simplet2i.py +13 -0
  132. ldm/util.py +264 -0
  133. scripts/configure_invokeai.py +797 -0
  134. scripts/create_root.py +43 -0
  135. scripts/dream.py +10 -0
  136. scripts/images2prompt.py +30 -0
  137. scripts/invoke.py +5 -0
  138. scripts/legacy_api.py +681 -0
  139. scripts/load_models.py +12 -0
  140. scripts/merge_embeddings.py +124 -0
  141. scripts/orig_scripts/img2img.py +296 -0
  142. scripts/orig_scripts/inpaint.py +98 -0
  143. scripts/orig_scripts/knn2img.py +397 -0
  144. scripts/orig_scripts/sample_diffusion.py +313 -0
  145. scripts/orig_scripts/train_searcher.py +147 -0
  146. scripts/orig_scripts/txt2img.py +324 -0
  147. scripts/preload_models.py +12 -0
  148. scripts/sd-metadata.py +22 -0
  149. vendored/clip/clip/__init__.py +1 -0
  150. vendored/clip/clip/bpe_simple_vocab_16e6.txt.gz +0 -0
  151. vendored/clip/clip/clip.py +237 -0
  152. vendored/clip/clip/model.py +436 -0
  153. vendored/clip/clip/simple_tokenizer.py +132 -0
  154. vendored/clip/hubconf.py +42 -0
  155. vendored/clip/setup.py +21 -0
  156. vendored/clip/tests/test_consistency.py +25 -0
  157. vendored/clipseg/datasets/coco_wrapper.py +99 -0
  158. vendored/clipseg/datasets/pascal_zeroshot.py +60 -0
  159. vendored/clipseg/datasets/pfe_dataset.py +129 -0
  160. vendored/clipseg/datasets/phrasecut.py +380 -0
  161. vendored/clipseg/datasets/utils.py +68 -0
  162. vendored/clipseg/evaluation_utils.py +292 -0
  163. vendored/clipseg/general_utils.py +272 -0
  164. vendored/clipseg/metrics.py +271 -0
  165. vendored/clipseg/models/clipseg.py +538 -0
  166. vendored/clipseg/models/vitseg.py +286 -0
  167. vendored/clipseg/score.py +453 -0
  168. vendored/clipseg/setup.py +30 -0
  169. 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
+ )