Spaces:
Paused
Paused
Add shared MoMA codebook option
Browse files
app.py
CHANGED
|
@@ -189,7 +189,13 @@ TOKENIZER_CODE = """# This tab builds a tiny image tokenizer from one image.
|
|
| 189 |
patches = split_image_into_grid(image, grid_size, patch_size)
|
| 190 |
vectors = flatten_each_patch_to_rgb_numbers(patches)
|
| 191 |
|
| 192 |
-
codebook
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
token_ids = nearest_code_for_each_patch(vectors, codebook)
|
| 194 |
|
| 195 |
# The compressed image is now a grid of integers.
|
|
@@ -770,14 +776,32 @@ def learned_codebook_rows(centroids, assignments, errors):
|
|
| 770 |
|
| 771 |
|
| 772 |
@spaces.GPU(duration=30)
|
| 773 |
-
def tokenize_image(image, grid_size, patch_size, codebook_size, iterations, seed):
|
| 774 |
grid_size = max(4, min(32, int(grid_size)))
|
| 775 |
patch_size = max(4, min(32, int(patch_size)))
|
| 776 |
codebook_size = max(2, min(64, int(codebook_size)))
|
| 777 |
prepared = prepare_tokenizer_image(image, grid_size, patch_size)
|
| 778 |
patches = image_to_patches(prepared, grid_size, patch_size)
|
| 779 |
vectors = patches.reshape(len(patches), -1)
|
| 780 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 781 |
reconstruction_vectors = centroids[assignments]
|
| 782 |
reconstruction = patches_to_image(reconstruction_vectors.reshape(len(patches), patch_size, patch_size, 3), grid_size, patch_size)
|
| 783 |
token_grid = draw_token_id_grid(assignments, grid_size)
|
|
@@ -787,25 +811,25 @@ def tokenize_image(image, grid_size, patch_size, codebook_size, iterations, seed
|
|
| 787 |
summary = (
|
| 788 |
f"Encoded the image into a {grid_size}x{grid_size} grid: {grid_size * grid_size} discrete token IDs.\n"
|
| 789 |
f"Each token represents one {patch_size}x{patch_size} RGB patch. "
|
| 790 |
-
f"The codebook has {len(centroids)} learned entries from
|
| 791 |
f"Mean reconstruction error per patch: {float(errors.mean()):.6f}. "
|
| 792 |
"Lower error means the learned codebook patch is closer to the original patch."
|
| 793 |
)
|
| 794 |
return prepared, token_grid, reconstruction, error_map, gallery, rows, summary
|
| 795 |
|
| 796 |
|
| 797 |
-
def initial_tokenizer(grid_size, patch_size, codebook_size, iterations, seed):
|
| 798 |
items, message = load_moma_items()
|
| 799 |
-
outputs = tokenize_image(items[0]["img"], grid_size, patch_size, codebook_size, iterations, seed)
|
| 800 |
summary = f"{message}\n\n{outputs[-1]}"
|
| 801 |
return (moma_gallery_items(),) + outputs[:-1] + (summary,)
|
| 802 |
|
| 803 |
|
| 804 |
-
def tokenize_moma_selection(grid_size, patch_size, codebook_size, iterations, seed, evt: gr.SelectData):
|
| 805 |
items, _ = load_moma_items()
|
| 806 |
index = evt.index if isinstance(evt.index, int) else 0
|
| 807 |
index = max(0, min(index, len(items) - 1))
|
| 808 |
-
return tokenize_image(items[index]["img"], grid_size, patch_size, codebook_size, iterations, seed)
|
| 809 |
|
| 810 |
|
| 811 |
def probability_rows(record):
|
|
@@ -1055,6 +1079,11 @@ def build_app():
|
|
| 1055 |
with gr.Row():
|
| 1056 |
tokenizer_codebook_size = gr.Slider(4, 48, value=16, step=1, label="Codebook size")
|
| 1057 |
tokenizer_iterations = gr.Slider(2, 30, value=10, step=1, label="K-means iterations")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1058 |
tokenizer_seed = gr.Number(value=7, precision=0, label="Codebook seed")
|
| 1059 |
tokenize_button = gr.Button("Tokenize uploaded image", variant="primary")
|
| 1060 |
|
|
@@ -1235,6 +1264,7 @@ def build_app():
|
|
| 1235 |
tokenizer_codebook_size,
|
| 1236 |
tokenizer_iterations,
|
| 1237 |
tokenizer_seed,
|
|
|
|
| 1238 |
]
|
| 1239 |
tokenizer_outputs = [
|
| 1240 |
tokenizer_original,
|
|
@@ -1261,6 +1291,7 @@ def build_app():
|
|
| 1261 |
tokenizer_codebook_size,
|
| 1262 |
tokenizer_iterations,
|
| 1263 |
tokenizer_seed,
|
|
|
|
| 1264 |
],
|
| 1265 |
outputs=tokenizer_outputs,
|
| 1266 |
show_progress="minimal",
|
|
@@ -1274,6 +1305,7 @@ def build_app():
|
|
| 1274 |
tokenizer_codebook_size,
|
| 1275 |
tokenizer_iterations,
|
| 1276 |
tokenizer_seed,
|
|
|
|
| 1277 |
],
|
| 1278 |
outputs=tokenizer_outputs,
|
| 1279 |
show_progress="minimal",
|
|
|
|
| 189 |
patches = split_image_into_grid(image, grid_size, patch_size)
|
| 190 |
vectors = flatten_each_patch_to_rgb_numbers(patches)
|
| 191 |
|
| 192 |
+
# The codebook can be trained on this image only,
|
| 193 |
+
# or on patches from all loaded MoMA images.
|
| 194 |
+
training_vectors = vectors
|
| 195 |
+
if codebook_source == "All loaded MoMA images":
|
| 196 |
+
training_vectors = flatten_patches_from_many_images(moma_images)
|
| 197 |
+
|
| 198 |
+
codebook = k_means(training_vectors, codebook_size)
|
| 199 |
token_ids = nearest_code_for_each_patch(vectors, codebook)
|
| 200 |
|
| 201 |
# The compressed image is now a grid of integers.
|
|
|
|
| 776 |
|
| 777 |
|
| 778 |
@spaces.GPU(duration=30)
|
| 779 |
+
def tokenize_image(image, grid_size, patch_size, codebook_size, iterations, seed, codebook_source):
|
| 780 |
grid_size = max(4, min(32, int(grid_size)))
|
| 781 |
patch_size = max(4, min(32, int(patch_size)))
|
| 782 |
codebook_size = max(2, min(64, int(codebook_size)))
|
| 783 |
prepared = prepare_tokenizer_image(image, grid_size, patch_size)
|
| 784 |
patches = image_to_patches(prepared, grid_size, patch_size)
|
| 785 |
vectors = patches.reshape(len(patches), -1)
|
| 786 |
+
|
| 787 |
+
if codebook_source == "All loaded MoMA images":
|
| 788 |
+
items, _ = load_moma_items()
|
| 789 |
+
training_vectors = []
|
| 790 |
+
for item in items:
|
| 791 |
+
train_image = prepare_tokenizer_image(item["img"], grid_size, patch_size)
|
| 792 |
+
train_patches = image_to_patches(train_image, grid_size, patch_size)
|
| 793 |
+
training_vectors.append(train_patches.reshape(len(train_patches), -1))
|
| 794 |
+
training_vectors = np.concatenate(training_vectors, axis=0)
|
| 795 |
+
centroids, _, _ = learn_codebook(training_vectors, codebook_size, iterations, seed)
|
| 796 |
+
source_text = f"all {len(items)} loaded MoMA images ({len(training_vectors)} training patches)"
|
| 797 |
+
else:
|
| 798 |
+
training_vectors = vectors
|
| 799 |
+
centroids, _, _ = learn_codebook(training_vectors, codebook_size, iterations, seed)
|
| 800 |
+
source_text = f"this image only ({len(training_vectors)} training patches)"
|
| 801 |
+
|
| 802 |
+
distances = squared_distances(vectors, centroids)
|
| 803 |
+
assignments = np.argmin(distances, axis=1).astype(np.int32)
|
| 804 |
+
errors = distances[np.arange(len(vectors)), assignments]
|
| 805 |
reconstruction_vectors = centroids[assignments]
|
| 806 |
reconstruction = patches_to_image(reconstruction_vectors.reshape(len(patches), patch_size, patch_size, 3), grid_size, patch_size)
|
| 807 |
token_grid = draw_token_id_grid(assignments, grid_size)
|
|
|
|
| 811 |
summary = (
|
| 812 |
f"Encoded the image into a {grid_size}x{grid_size} grid: {grid_size * grid_size} discrete token IDs.\n"
|
| 813 |
f"Each token represents one {patch_size}x{patch_size} RGB patch. "
|
| 814 |
+
f"The codebook has {len(centroids)} learned entries trained from {source_text}.\n"
|
| 815 |
f"Mean reconstruction error per patch: {float(errors.mean()):.6f}. "
|
| 816 |
"Lower error means the learned codebook patch is closer to the original patch."
|
| 817 |
)
|
| 818 |
return prepared, token_grid, reconstruction, error_map, gallery, rows, summary
|
| 819 |
|
| 820 |
|
| 821 |
+
def initial_tokenizer(grid_size, patch_size, codebook_size, iterations, seed, codebook_source):
|
| 822 |
items, message = load_moma_items()
|
| 823 |
+
outputs = tokenize_image(items[0]["img"], grid_size, patch_size, codebook_size, iterations, seed, codebook_source)
|
| 824 |
summary = f"{message}\n\n{outputs[-1]}"
|
| 825 |
return (moma_gallery_items(),) + outputs[:-1] + (summary,)
|
| 826 |
|
| 827 |
|
| 828 |
+
def tokenize_moma_selection(grid_size, patch_size, codebook_size, iterations, seed, codebook_source, evt: gr.SelectData):
|
| 829 |
items, _ = load_moma_items()
|
| 830 |
index = evt.index if isinstance(evt.index, int) else 0
|
| 831 |
index = max(0, min(index, len(items) - 1))
|
| 832 |
+
return tokenize_image(items[index]["img"], grid_size, patch_size, codebook_size, iterations, seed, codebook_source)
|
| 833 |
|
| 834 |
|
| 835 |
def probability_rows(record):
|
|
|
|
| 1079 |
with gr.Row():
|
| 1080 |
tokenizer_codebook_size = gr.Slider(4, 48, value=16, step=1, label="Codebook size")
|
| 1081 |
tokenizer_iterations = gr.Slider(2, 30, value=10, step=1, label="K-means iterations")
|
| 1082 |
+
tokenizer_codebook_source = gr.Radio(
|
| 1083 |
+
["This image only", "All loaded MoMA images"],
|
| 1084 |
+
value="This image only",
|
| 1085 |
+
label="Learn codebook from",
|
| 1086 |
+
)
|
| 1087 |
tokenizer_seed = gr.Number(value=7, precision=0, label="Codebook seed")
|
| 1088 |
tokenize_button = gr.Button("Tokenize uploaded image", variant="primary")
|
| 1089 |
|
|
|
|
| 1264 |
tokenizer_codebook_size,
|
| 1265 |
tokenizer_iterations,
|
| 1266 |
tokenizer_seed,
|
| 1267 |
+
tokenizer_codebook_source,
|
| 1268 |
]
|
| 1269 |
tokenizer_outputs = [
|
| 1270 |
tokenizer_original,
|
|
|
|
| 1291 |
tokenizer_codebook_size,
|
| 1292 |
tokenizer_iterations,
|
| 1293 |
tokenizer_seed,
|
| 1294 |
+
tokenizer_codebook_source,
|
| 1295 |
],
|
| 1296 |
outputs=tokenizer_outputs,
|
| 1297 |
show_progress="minimal",
|
|
|
|
| 1305 |
tokenizer_codebook_size,
|
| 1306 |
tokenizer_iterations,
|
| 1307 |
tokenizer_seed,
|
| 1308 |
+
tokenizer_codebook_source,
|
| 1309 |
],
|
| 1310 |
outputs=tokenizer_outputs,
|
| 1311 |
show_progress="minimal",
|