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,380 @@
|
|
|
1
|
+
|
|
2
|
+
import torch
|
|
3
|
+
import numpy as np
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
from os.path import join, isdir, isfile, expanduser
|
|
7
|
+
from PIL import Image
|
|
8
|
+
|
|
9
|
+
from torchvision import transforms
|
|
10
|
+
from torchvision.transforms.transforms import Resize
|
|
11
|
+
|
|
12
|
+
from torch.nn import functional as nnf
|
|
13
|
+
from general_utils import get_from_repository
|
|
14
|
+
|
|
15
|
+
from skimage.draw import polygon2mask
|
|
16
|
+
|
|
17
|
+
PASCAL_SYNSETS = ['person.n.01', 'bird.n.01', 'cat.n.01', 'cattle.n.01', 'dog.n.01', 'horse.n.01', 'sheep.n.01', 'aeroplane.n.01', 'bicycle.n.01',
|
|
18
|
+
'boat.n.01', 'bus.n.01', 'car.n.01', 'motorcycle.n.01', 'train.n.01', 'bottle.n.01', 'chair.n.01', 'kitchen_table.n.01',
|
|
19
|
+
'breakfast_table.n.01', 'trestle_table.n.01','pot_plant.n.01', 'sofa.n.01', 'television.n.03']
|
|
20
|
+
|
|
21
|
+
PASCAL_5I_SYNSETS_ORDERED = [
|
|
22
|
+
'aeroplane.n.01', 'bicycle.n.01', 'bird.n.01', 'vessel.n.02', 'bottle.n.01', 'bus.n.01', 'car.n.01',
|
|
23
|
+
'cat.n.01', 'chair.n.01', 'cattle.n.01', 'table.n.02', 'dog.n.01', 'horse.n.01', 'motorcycle.n.01',
|
|
24
|
+
'person.n.01', 'pot_plant.n.01', 'sheep.n.01', 'sofa.n.01', 'train.n.01', 'television.n.03']
|
|
25
|
+
|
|
26
|
+
# Pascal-5i classes
|
|
27
|
+
PASCAL_5I_CLASS_IDS = {
|
|
28
|
+
3: list(range(1, 16)),
|
|
29
|
+
2: list(range(1, 11)) + list(range(16, 21)),
|
|
30
|
+
1: list(range(1, 6)) + list(range(11, 21)),
|
|
31
|
+
0: list(range(6, 21))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def traverse_lemmas(synset):
|
|
36
|
+
""" list of all lemma names of hypernyms """
|
|
37
|
+
|
|
38
|
+
out = synset.lemma_names()
|
|
39
|
+
for h in synset.hypernyms():
|
|
40
|
+
out += traverse_lemmas(h)
|
|
41
|
+
|
|
42
|
+
return out
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def traverse_lemmas_hypo(synset, max_depth=None, depth=0):
|
|
46
|
+
""" list of all lemma names of hypernyms """
|
|
47
|
+
|
|
48
|
+
if synset.name() == 'person.n.01':
|
|
49
|
+
return ['person', 'human', 'man', 'woman', 'toddler', 'baby', 'body', 'child', 'infant']
|
|
50
|
+
|
|
51
|
+
out = [l.name() for l in synset.lemmas()]
|
|
52
|
+
|
|
53
|
+
# print(' '*depth, synset.name())
|
|
54
|
+
|
|
55
|
+
if max_depth is not None and depth >= max_depth:
|
|
56
|
+
return out
|
|
57
|
+
|
|
58
|
+
# print(' '*(3*depth), out)
|
|
59
|
+
for h in synset.hyponyms():
|
|
60
|
+
out += traverse_lemmas_hypo(h, max_depth, depth+1)
|
|
61
|
+
|
|
62
|
+
return out
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def random_crop_slices(origin_size, target_size):
|
|
67
|
+
"""Gets slices of a random crop. """
|
|
68
|
+
assert origin_size[0] >= target_size[0] and origin_size[1] >= target_size[1], f'actual size: {origin_size}, target size: {target_size}'
|
|
69
|
+
|
|
70
|
+
offset_y = torch.randint(0, origin_size[0] - target_size[0] + 1, (1,)).item() # range: 0 <= value < high
|
|
71
|
+
offset_x = torch.randint(0, origin_size[1] - target_size[1] + 1, (1,)).item()
|
|
72
|
+
|
|
73
|
+
return slice(offset_y, offset_y + target_size[0]), slice(offset_x, offset_x + target_size[1])
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def find_crop(seg, image_size, iterations=1000, min_frac=None, best_of=None):
|
|
77
|
+
|
|
78
|
+
best_crops = []
|
|
79
|
+
best_crop_not_ok = float('-inf'), None, None
|
|
80
|
+
min_sum = 0
|
|
81
|
+
|
|
82
|
+
seg = seg.astype('bool')
|
|
83
|
+
|
|
84
|
+
if min_frac is not None:
|
|
85
|
+
#min_sum = seg.sum() * min_frac
|
|
86
|
+
min_sum = seg.shape[0] * seg.shape[1] * min_frac
|
|
87
|
+
|
|
88
|
+
for iteration in range(iterations):
|
|
89
|
+
sl_y, sl_x = random_crop_slices(seg.shape, image_size)
|
|
90
|
+
seg_ = seg[sl_y, sl_x]
|
|
91
|
+
sum_seg_ = seg_.sum()
|
|
92
|
+
|
|
93
|
+
if sum_seg_ > min_sum:
|
|
94
|
+
|
|
95
|
+
if best_of is None:
|
|
96
|
+
return sl_y, sl_x, False
|
|
97
|
+
else:
|
|
98
|
+
best_crops += [(sum_seg_, sl_y, sl_x)]
|
|
99
|
+
if len(best_crops) >= best_of:
|
|
100
|
+
best_crops.sort(key=lambda x:x[0], reverse=True)
|
|
101
|
+
sl_y, sl_x = best_crops[0][1:]
|
|
102
|
+
|
|
103
|
+
return sl_y, sl_x, False
|
|
104
|
+
|
|
105
|
+
else:
|
|
106
|
+
if sum_seg_ > best_crop_not_ok[0]:
|
|
107
|
+
best_crop_not_ok = sum_seg_, sl_y, sl_x
|
|
108
|
+
|
|
109
|
+
else:
|
|
110
|
+
# return best segmentation found
|
|
111
|
+
return best_crop_not_ok[1:] + (best_crop_not_ok[0] <= min_sum,)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class PhraseCut(object):
|
|
115
|
+
|
|
116
|
+
def __init__(self, split, image_size=400, negative_prob=0, aug=None, aug_color=False, aug_crop=True,
|
|
117
|
+
min_size=0, remove_classes=None, with_visual=False, only_visual=False, mask=None):
|
|
118
|
+
super().__init__()
|
|
119
|
+
|
|
120
|
+
self.negative_prob = negative_prob
|
|
121
|
+
self.image_size = image_size
|
|
122
|
+
self.with_visual = with_visual
|
|
123
|
+
self.only_visual = only_visual
|
|
124
|
+
self.phrase_form = '{}'
|
|
125
|
+
self.mask = mask
|
|
126
|
+
self.aug_crop = aug_crop
|
|
127
|
+
|
|
128
|
+
if aug_color:
|
|
129
|
+
self.aug_color = transforms.Compose([
|
|
130
|
+
transforms.ColorJitter(0.5, 0.5, 0.2, 0.05),
|
|
131
|
+
])
|
|
132
|
+
else:
|
|
133
|
+
self.aug_color = None
|
|
134
|
+
|
|
135
|
+
get_from_repository('PhraseCut', ['PhraseCut.tar'], integrity_check=lambda local_dir: all([
|
|
136
|
+
isdir(join(local_dir, 'VGPhraseCut_v0')),
|
|
137
|
+
isdir(join(local_dir, 'VGPhraseCut_v0', 'images')),
|
|
138
|
+
isfile(join(local_dir, 'VGPhraseCut_v0', 'refer_train.json')),
|
|
139
|
+
len(os.listdir(join(local_dir, 'VGPhraseCut_v0', 'images'))) in {108250, 108249}
|
|
140
|
+
]))
|
|
141
|
+
|
|
142
|
+
from third_party.PhraseCutDataset.utils.refvg_loader import RefVGLoader
|
|
143
|
+
self.refvg_loader = RefVGLoader(split=split)
|
|
144
|
+
|
|
145
|
+
# img_ids where the size in the annotations does not match actual size
|
|
146
|
+
invalid_img_ids = set([150417, 285665, 498246, 61564, 285743, 498269, 498010, 150516, 150344, 286093, 61530,
|
|
147
|
+
150333, 286065, 285814, 498187, 285761, 498042])
|
|
148
|
+
|
|
149
|
+
mean = [0.485, 0.456, 0.406]
|
|
150
|
+
std = [0.229, 0.224, 0.225]
|
|
151
|
+
self.normalize = transforms.Normalize(mean, std)
|
|
152
|
+
|
|
153
|
+
self.sample_ids = [(i, j)
|
|
154
|
+
for i in self.refvg_loader.img_ids
|
|
155
|
+
for j in range(len(self.refvg_loader.get_img_ref_data(i)['phrases']))
|
|
156
|
+
if i not in invalid_img_ids]
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
# self.all_phrases = list(set([p for i in self.refvg_loader.img_ids for p in self.refvg_loader.get_img_ref_data(i)['phrases']]))
|
|
160
|
+
|
|
161
|
+
from nltk.stem import WordNetLemmatizer
|
|
162
|
+
wnl = WordNetLemmatizer()
|
|
163
|
+
|
|
164
|
+
# Filter by class (if remove_classes is set)
|
|
165
|
+
if remove_classes is None:
|
|
166
|
+
pass
|
|
167
|
+
else:
|
|
168
|
+
from nltk.corpus import wordnet
|
|
169
|
+
|
|
170
|
+
print('remove pascal classes...')
|
|
171
|
+
|
|
172
|
+
get_data = self.refvg_loader.get_img_ref_data # shortcut
|
|
173
|
+
keep_sids = None
|
|
174
|
+
|
|
175
|
+
if remove_classes[0] == 'pas5i':
|
|
176
|
+
subset_id = remove_classes[1]
|
|
177
|
+
|
|
178
|
+
avoid = [PASCAL_5I_SYNSETS_ORDERED[i] for i in range(20) if i+1 not in PASCAL_5I_CLASS_IDS[subset_id]]
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
elif remove_classes[0] == 'zs':
|
|
182
|
+
stop = remove_classes[1]
|
|
183
|
+
|
|
184
|
+
from datasets.pascal_zeroshot import PASCAL_VOC_CLASSES_ZS
|
|
185
|
+
|
|
186
|
+
avoid = [c for class_set in PASCAL_VOC_CLASSES_ZS[:stop] for c in class_set]
|
|
187
|
+
print(avoid)
|
|
188
|
+
|
|
189
|
+
elif remove_classes[0] == 'aff':
|
|
190
|
+
# avoid = ['drink.v.01', 'sit.v.01', 'ride.v.02']
|
|
191
|
+
# all_lemmas = set(['drink', 'sit', 'ride'])
|
|
192
|
+
avoid = ['drink', 'drinks', 'drinking', 'sit', 'sits', 'sitting',
|
|
193
|
+
'ride', 'rides', 'riding',
|
|
194
|
+
'fly', 'flies', 'flying', 'drive', 'drives', 'driving', 'driven',
|
|
195
|
+
'swim', 'swims', 'swimming',
|
|
196
|
+
'wheels', 'wheel', 'legs', 'leg', 'ear', 'ears']
|
|
197
|
+
keep_sids = [(i, j) for i, j in self.sample_ids if
|
|
198
|
+
all(x not in avoid for x in get_data(i)['phrases'][j].split(' '))]
|
|
199
|
+
|
|
200
|
+
print('avoid classes:', avoid)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
if keep_sids is None:
|
|
204
|
+
all_lemmas = [s for ps in avoid for s in traverse_lemmas_hypo(wordnet.synset(ps), max_depth=None)]
|
|
205
|
+
all_lemmas = list(set(all_lemmas))
|
|
206
|
+
all_lemmas = [h.replace('_', ' ').lower() for h in all_lemmas]
|
|
207
|
+
all_lemmas = set(all_lemmas)
|
|
208
|
+
|
|
209
|
+
# divide into multi word and single word
|
|
210
|
+
all_lemmas_s = set(l for l in all_lemmas if ' ' not in l)
|
|
211
|
+
all_lemmas_m = set(l for l in all_lemmas if l not in all_lemmas_s)
|
|
212
|
+
|
|
213
|
+
# new3
|
|
214
|
+
phrases = [get_data(i)['phrases'][j] for i, j in self.sample_ids]
|
|
215
|
+
remove_sids = set((i,j) for (i,j), phrase in zip(self.sample_ids, phrases)
|
|
216
|
+
if any(l in phrase for l in all_lemmas_m) or
|
|
217
|
+
len(set(wnl.lemmatize(w) for w in phrase.split(' ')).intersection(all_lemmas_s)) > 0
|
|
218
|
+
)
|
|
219
|
+
keep_sids = [(i, j) for i, j in self.sample_ids if (i,j) not in remove_sids]
|
|
220
|
+
|
|
221
|
+
print(f'Reduced to {len(keep_sids) / len(self.sample_ids):.3f}')
|
|
222
|
+
removed_ids = set(self.sample_ids) - set(keep_sids)
|
|
223
|
+
|
|
224
|
+
print('Examples of removed', len(removed_ids))
|
|
225
|
+
for i, j in list(removed_ids)[:20]:
|
|
226
|
+
print(i, get_data(i)['phrases'][j])
|
|
227
|
+
|
|
228
|
+
self.sample_ids = keep_sids
|
|
229
|
+
|
|
230
|
+
from itertools import groupby
|
|
231
|
+
samples_by_phrase = [(self.refvg_loader.get_img_ref_data(i)['phrases'][j], (i, j))
|
|
232
|
+
for i, j in self.sample_ids]
|
|
233
|
+
samples_by_phrase = sorted(samples_by_phrase)
|
|
234
|
+
samples_by_phrase = groupby(samples_by_phrase, key=lambda x: x[0])
|
|
235
|
+
|
|
236
|
+
self.samples_by_phrase = {prompt: [s[1] for s in prompt_sample_ids] for prompt, prompt_sample_ids in samples_by_phrase}
|
|
237
|
+
|
|
238
|
+
self.all_phrases = list(set(self.samples_by_phrase.keys()))
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
if self.only_visual:
|
|
242
|
+
assert self.with_visual
|
|
243
|
+
self.sample_ids = [(i, j) for i, j in self.sample_ids
|
|
244
|
+
if len(self.samples_by_phrase[self.refvg_loader.get_img_ref_data(i)['phrases'][j]]) > 1]
|
|
245
|
+
|
|
246
|
+
# Filter by size (if min_size is set)
|
|
247
|
+
sizes = [self.refvg_loader.get_img_ref_data(i)['gt_boxes'][j] for i, j in self.sample_ids]
|
|
248
|
+
image_sizes = [self.refvg_loader.get_img_ref_data(i)['width'] * self.refvg_loader.get_img_ref_data(i)['height'] for i, j in self.sample_ids]
|
|
249
|
+
#self.sizes = [sum([(s[2] - s[0]) * (s[3] - s[1]) for s in size]) for size in sizes]
|
|
250
|
+
self.sizes = [sum([s[2] * s[3] for s in size]) / img_size for size, img_size in zip(sizes, image_sizes)]
|
|
251
|
+
|
|
252
|
+
if min_size:
|
|
253
|
+
print('filter by size')
|
|
254
|
+
|
|
255
|
+
self.sample_ids = [self.sample_ids[i] for i in range(len(self.sample_ids)) if self.sizes[i] > min_size]
|
|
256
|
+
|
|
257
|
+
self.base_path = join(expanduser('~/datasets/PhraseCut/VGPhraseCut_v0/images/'))
|
|
258
|
+
|
|
259
|
+
def __len__(self):
|
|
260
|
+
return len(self.sample_ids)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def load_sample(self, sample_i, j):
|
|
264
|
+
|
|
265
|
+
img_ref_data = self.refvg_loader.get_img_ref_data(sample_i)
|
|
266
|
+
|
|
267
|
+
polys_phrase0 = img_ref_data['gt_Polygons'][j]
|
|
268
|
+
phrase = img_ref_data['phrases'][j]
|
|
269
|
+
phrase = self.phrase_form.format(phrase)
|
|
270
|
+
|
|
271
|
+
masks = []
|
|
272
|
+
for polys in polys_phrase0:
|
|
273
|
+
for poly in polys:
|
|
274
|
+
poly = [p[::-1] for p in poly] # swap x,y
|
|
275
|
+
masks += [polygon2mask((img_ref_data['height'], img_ref_data['width']), poly)]
|
|
276
|
+
|
|
277
|
+
seg = np.stack(masks).max(0)
|
|
278
|
+
img = np.array(Image.open(join(self.base_path, str(img_ref_data['image_id']) + '.jpg')))
|
|
279
|
+
|
|
280
|
+
min_shape = min(img.shape[:2])
|
|
281
|
+
|
|
282
|
+
if self.aug_crop:
|
|
283
|
+
sly, slx, exceed = find_crop(seg, (min_shape, min_shape), iterations=50, min_frac=0.05)
|
|
284
|
+
else:
|
|
285
|
+
sly, slx = slice(0, None), slice(0, None)
|
|
286
|
+
|
|
287
|
+
seg = seg[sly, slx]
|
|
288
|
+
img = img[sly, slx]
|
|
289
|
+
|
|
290
|
+
seg = seg.astype('uint8')
|
|
291
|
+
seg = torch.from_numpy(seg).view(1, 1, *seg.shape)
|
|
292
|
+
|
|
293
|
+
if img.ndim == 2:
|
|
294
|
+
img = np.dstack([img] * 3)
|
|
295
|
+
|
|
296
|
+
img = torch.from_numpy(img).permute(2,0,1).unsqueeze(0).float()
|
|
297
|
+
|
|
298
|
+
seg = nnf.interpolate(seg, (self.image_size, self.image_size), mode='nearest')[0,0]
|
|
299
|
+
img = nnf.interpolate(img, (self.image_size, self.image_size), mode='bilinear', align_corners=True)[0]
|
|
300
|
+
|
|
301
|
+
# img = img.permute([2,0, 1])
|
|
302
|
+
img = img / 255.0
|
|
303
|
+
|
|
304
|
+
if self.aug_color is not None:
|
|
305
|
+
img = self.aug_color(img)
|
|
306
|
+
|
|
307
|
+
img = self.normalize(img)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
return img, seg, phrase
|
|
312
|
+
|
|
313
|
+
def __getitem__(self, i):
|
|
314
|
+
|
|
315
|
+
sample_i, j = self.sample_ids[i]
|
|
316
|
+
|
|
317
|
+
img, seg, phrase = self.load_sample(sample_i, j)
|
|
318
|
+
|
|
319
|
+
if self.negative_prob > 0:
|
|
320
|
+
if torch.rand((1,)).item() < self.negative_prob:
|
|
321
|
+
|
|
322
|
+
new_phrase = None
|
|
323
|
+
while new_phrase is None or new_phrase == phrase:
|
|
324
|
+
idx = torch.randint(0, len(self.all_phrases), (1,)).item()
|
|
325
|
+
new_phrase = self.all_phrases[idx]
|
|
326
|
+
phrase = new_phrase
|
|
327
|
+
seg = torch.zeros_like(seg)
|
|
328
|
+
|
|
329
|
+
if self.with_visual:
|
|
330
|
+
# find a corresponding visual image
|
|
331
|
+
if phrase in self.samples_by_phrase and len(self.samples_by_phrase[phrase]) > 1:
|
|
332
|
+
idx = torch.randint(0, len(self.samples_by_phrase[phrase]), (1,)).item()
|
|
333
|
+
other_sample = self.samples_by_phrase[phrase][idx]
|
|
334
|
+
#print(other_sample)
|
|
335
|
+
img_s, seg_s, _ = self.load_sample(*other_sample)
|
|
336
|
+
|
|
337
|
+
from datasets.utils import blend_image_segmentation
|
|
338
|
+
|
|
339
|
+
if self.mask in {'separate', 'text_and_separate'}:
|
|
340
|
+
# assert img.shape[1:] == img_s.shape[1:] == seg_s.shape == seg.shape[1:]
|
|
341
|
+
add_phrase = [phrase] if self.mask == 'text_and_separate' else []
|
|
342
|
+
vis_s = add_phrase + [img_s, seg_s, True]
|
|
343
|
+
else:
|
|
344
|
+
if self.mask.startswith('text_and_'):
|
|
345
|
+
mask_mode = self.mask[9:]
|
|
346
|
+
label_add = [phrase]
|
|
347
|
+
else:
|
|
348
|
+
mask_mode = self.mask
|
|
349
|
+
label_add = []
|
|
350
|
+
|
|
351
|
+
masked_img_s = torch.from_numpy(blend_image_segmentation(img_s, seg_s, mode=mask_mode, image_size=self.image_size)[0])
|
|
352
|
+
vis_s = label_add + [masked_img_s, True]
|
|
353
|
+
|
|
354
|
+
else:
|
|
355
|
+
# phrase is unique
|
|
356
|
+
vis_s = torch.zeros_like(img)
|
|
357
|
+
|
|
358
|
+
if self.mask in {'separate', 'text_and_separate'}:
|
|
359
|
+
add_phrase = [phrase] if self.mask == 'text_and_separate' else []
|
|
360
|
+
vis_s = add_phrase + [vis_s, torch.zeros(*vis_s.shape[1:], dtype=torch.uint8), False]
|
|
361
|
+
elif self.mask.startswith('text_and_'):
|
|
362
|
+
vis_s = [phrase, vis_s, False]
|
|
363
|
+
else:
|
|
364
|
+
vis_s = [vis_s, False]
|
|
365
|
+
else:
|
|
366
|
+
assert self.mask == 'text'
|
|
367
|
+
vis_s = [phrase]
|
|
368
|
+
|
|
369
|
+
seg = seg.unsqueeze(0).float()
|
|
370
|
+
|
|
371
|
+
data_x = (img,) + tuple(vis_s)
|
|
372
|
+
|
|
373
|
+
return data_x, (seg, torch.zeros(0), i)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
class PhraseCutPlus(PhraseCut):
|
|
377
|
+
|
|
378
|
+
def __init__(self, split, image_size=400, aug=None, aug_color=False, aug_crop=True, min_size=0, remove_classes=None, only_visual=False, mask=None):
|
|
379
|
+
super().__init__(split, image_size=image_size, negative_prob=0.2, aug=aug, aug_color=aug_color, aug_crop=aug_crop, min_size=min_size,
|
|
380
|
+
remove_classes=remove_classes, with_visual=True, only_visual=only_visual, mask=mask)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
|
|
2
|
+
import numpy as np
|
|
3
|
+
import torch
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def blend_image_segmentation(img, seg, mode, image_size=224):
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
if mode in {'blur_highlight', 'blur3_highlight', 'blur3_highlight01', 'blur_highlight_random', 'crop'}:
|
|
10
|
+
if isinstance(img, np.ndarray):
|
|
11
|
+
img = torch.from_numpy(img)
|
|
12
|
+
|
|
13
|
+
if isinstance(seg, np.ndarray):
|
|
14
|
+
seg = torch.from_numpy(seg)
|
|
15
|
+
|
|
16
|
+
if mode == 'overlay':
|
|
17
|
+
out = img * seg
|
|
18
|
+
out = [out.astype('float32')]
|
|
19
|
+
elif mode == 'highlight':
|
|
20
|
+
out = img * seg[None, :, :] * 0.85 + 0.15 * img
|
|
21
|
+
out = [out.astype('float32')]
|
|
22
|
+
elif mode == 'highlight2':
|
|
23
|
+
img = img / 2
|
|
24
|
+
out = (img+0.1) * seg[None, :, :] + 0.3 * img
|
|
25
|
+
out = [out.astype('float32')]
|
|
26
|
+
elif mode == 'blur_highlight':
|
|
27
|
+
from evaluation_utils import img_preprocess
|
|
28
|
+
out = [img_preprocess((None, [img], [seg]), blur=1, bg_fac=0.5).numpy()[0] - 0.01]
|
|
29
|
+
elif mode == 'blur3_highlight':
|
|
30
|
+
from evaluation_utils import img_preprocess
|
|
31
|
+
out = [img_preprocess((None, [img], [seg]), blur=3, bg_fac=0.5).numpy()[0] - 0.01]
|
|
32
|
+
elif mode == 'blur3_highlight01':
|
|
33
|
+
from evaluation_utils import img_preprocess
|
|
34
|
+
out = [img_preprocess((None, [img], [seg]), blur=3, bg_fac=0.1).numpy()[0] - 0.01]
|
|
35
|
+
elif mode == 'blur_highlight_random':
|
|
36
|
+
from evaluation_utils import img_preprocess
|
|
37
|
+
out = [img_preprocess((None, [img], [seg]), blur=0 + torch.randint(0, 3, (1,)).item(), bg_fac=0.1 + 0.8*torch.rand(1).item()).numpy()[0] - 0.01]
|
|
38
|
+
elif mode == 'crop':
|
|
39
|
+
from evaluation_utils import img_preprocess
|
|
40
|
+
out = [img_preprocess((None, [img], [seg]), blur=1, center_context=0.1, image_size=image_size)[0].numpy()]
|
|
41
|
+
elif mode == 'crop_blur_highlight':
|
|
42
|
+
from evaluation_utils import img_preprocess
|
|
43
|
+
out = [img_preprocess((None, [img], [seg]), blur=3, center_context=0.1, bg_fac=0.1, image_size=image_size)[0].numpy()]
|
|
44
|
+
elif mode == 'crop_blur_highlight352':
|
|
45
|
+
from evaluation_utils import img_preprocess
|
|
46
|
+
out = [img_preprocess((None, [img], [seg]), blur=3, center_context=0.1, bg_fac=0.1, image_size=352)[0].numpy()]
|
|
47
|
+
elif mode == 'shape':
|
|
48
|
+
out = [np.stack([seg[:, :]]*3).astype('float32')]
|
|
49
|
+
elif mode == 'concat':
|
|
50
|
+
out = [np.concatenate([img, seg[None, :, :]]).astype('float32')]
|
|
51
|
+
elif mode == 'image_only':
|
|
52
|
+
out = [img.astype('float32')]
|
|
53
|
+
elif mode == 'image_black':
|
|
54
|
+
out = [img.astype('float32')*0]
|
|
55
|
+
elif mode is None:
|
|
56
|
+
out = [img.astype('float32')]
|
|
57
|
+
elif mode == 'separate':
|
|
58
|
+
out = [img.astype('float32'), seg.astype('int64')]
|
|
59
|
+
elif mode == 'separate_img_black':
|
|
60
|
+
out = [img.astype('float32')*0, seg.astype('int64')]
|
|
61
|
+
elif mode == 'separate_seg_ones':
|
|
62
|
+
out = [img.astype('float32'), np.ones_like(seg).astype('int64')]
|
|
63
|
+
elif mode == 'separate_both_black':
|
|
64
|
+
out = [img.astype('float32')*0, seg.astype('int64')*0]
|
|
65
|
+
else:
|
|
66
|
+
raise ValueError(f'invalid mode: {mode}')
|
|
67
|
+
|
|
68
|
+
return out
|