Plana-Archive commited on
Commit
95f9f03
·
verified ·
1 Parent(s): 7a2e7e8

Upload search_image_by_image/app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. search_image_by_image/app.py +158 -0
search_image_by_image/app.py ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ from collections import defaultdict
4
+ from typing import List, Dict
5
+
6
+ import faiss
7
+ import gradio as gr
8
+ import numpy as np
9
+ from PIL import Image
10
+ from cheesechaser.datapool import YandeWebpDataPool, ZerochanWebpDataPool, GelbooruWebpDataPool, \
11
+ KonachanWebpDataPool, AnimePicturesWebpDataPool, DanbooruNewestWebpDataPool, Rule34WebpDataPool
12
+ from hfutils.operate import get_hf_fs, get_hf_client
13
+ from hfutils.utils import TemporaryDirectory
14
+ from imgutils.tagging import wd14
15
+ from imgutils.utils import ts_lru_cache
16
+
17
+ from pools import quick_webp_pool
18
+
19
+ _REPO_ID = 'deepghs/anime_sites_indices'
20
+
21
+ hf_fs = get_hf_fs()
22
+ hf_client = get_hf_client()
23
+
24
+ _DEFAULT_MODEL_NAME = 'SwinV2_v3_iqdb_10_46796044_8GB'
25
+ _ALL_MODEL_NAMES = [
26
+ os.path.dirname(os.path.relpath(path, _REPO_ID))
27
+ for path in hf_fs.glob(f'{_REPO_ID}/*/knn.index')
28
+ ]
29
+
30
+ _SITE_CLS = {
31
+ 'danbooru': DanbooruNewestWebpDataPool,
32
+ 'yandere': YandeWebpDataPool,
33
+ 'zerochan': ZerochanWebpDataPool,
34
+ 'gelbooru': GelbooruWebpDataPool,
35
+ 'konachan': KonachanWebpDataPool,
36
+ 'anime_pictures': AnimePicturesWebpDataPool,
37
+ 'rule34': Rule34WebpDataPool,
38
+ }
39
+
40
+
41
+ def _get_from_ids(site_name: str, ids: List[int]) -> Dict[int, Image.Image]:
42
+ with TemporaryDirectory() as td:
43
+ site_cls = _SITE_CLS.get(site_name) or quick_webp_pool(site_name, 3)
44
+ datapool = site_cls()
45
+ datapool.batch_download_to_directory(
46
+ resource_ids=ids,
47
+ dst_dir=td,
48
+ )
49
+
50
+ retval = {}
51
+ for file in os.listdir(td):
52
+ id_ = int(os.path.splitext(file)[0])
53
+ image = Image.open(os.path.join(td, file))
54
+ image.load()
55
+ retval[id_] = image
56
+
57
+ return retval
58
+
59
+
60
+ def _get_from_raw_ids(ids: List[str]) -> Dict[str, Image.Image]:
61
+ _sites = defaultdict(list)
62
+ for id_ in ids:
63
+ site_name, num_id = id_.rsplit('_', maxsplit=1)
64
+ num_id = int(num_id)
65
+ _sites[site_name].append(num_id)
66
+
67
+ _retval = {}
68
+ for site_name, site_ids in _sites.items():
69
+ _retval.update({
70
+ f'{site_name}_{id_}': image
71
+ for id_, image in _get_from_ids(site_name, site_ids).items()
72
+ })
73
+ return _retval
74
+
75
+
76
+ @ts_lru_cache(maxsize=3)
77
+ def _get_index_info(repo_id: str, model_name: str):
78
+ image_ids = np.load(hf_client.hf_hub_download(
79
+ repo_id=repo_id,
80
+ repo_type='model',
81
+ filename=f'{model_name}/ids.npy',
82
+ ))
83
+ knn_index = faiss.read_index(hf_client.hf_hub_download(
84
+ repo_id=repo_id,
85
+ repo_type='model',
86
+ filename=f'{model_name}/knn.index',
87
+ ))
88
+
89
+ config = json.loads(open(hf_client.hf_hub_download(
90
+ repo_id=repo_id,
91
+ repo_type='model',
92
+ filename=f'{model_name}/infos.json',
93
+ )).read())["index_param"]
94
+ faiss.ParameterSpace().set_index_parameters(knn_index, config)
95
+ return image_ids, knn_index
96
+
97
+
98
+ def search(model_name: str, img_input, n_neighbours: int):
99
+ images_ids, knn_index = _get_index_info(_REPO_ID, model_name)
100
+ embeddings = wd14.get_wd14_tags(
101
+ img_input,
102
+ model_name="SwinV2_v3",
103
+ fmt="embedding",
104
+ )
105
+ embeddings = np.expand_dims(embeddings, 0)
106
+ faiss.normalize_L2(embeddings)
107
+
108
+ dists, indexes = knn_index.search(embeddings, k=n_neighbours)
109
+ neighbours_ids = images_ids[indexes][0]
110
+
111
+ captions = []
112
+ images = []
113
+ ids_to_images = _get_from_raw_ids(neighbours_ids)
114
+ for image_id, dist in zip(neighbours_ids, dists[0]):
115
+ if image_id in ids_to_images:
116
+ images.append(ids_to_images[image_id])
117
+ captions.append(f"{image_id}/{dist:.2f}")
118
+
119
+ return list(zip(images, captions))
120
+
121
+
122
+ if __name__ == "__main__":
123
+ with gr.Blocks() as demo:
124
+ with gr.Row():
125
+ with gr.Column():
126
+ img_input = gr.Image(type="pil", label="Input")
127
+
128
+ with gr.Column():
129
+ with gr.Row():
130
+ n_model = gr.Dropdown(
131
+ choices=_ALL_MODEL_NAMES,
132
+ value=_DEFAULT_MODEL_NAME,
133
+ label='Index to Use',
134
+ )
135
+ with gr.Row():
136
+ n_neighbours = gr.Slider(
137
+ minimum=1,
138
+ maximum=50,
139
+ value=20,
140
+ step=1,
141
+ label="# of images",
142
+ )
143
+ find_btn = gr.Button("Find similar images")
144
+
145
+ with gr.Row():
146
+ similar_images = gr.Gallery(label="Similar images", columns=[5])
147
+
148
+ find_btn.click(
149
+ fn=search,
150
+ inputs=[
151
+ n_model,
152
+ img_input,
153
+ n_neighbours,
154
+ ],
155
+ outputs=[similar_images],
156
+ )
157
+
158
+ demo.queue().launch()