Plana-Archive commited on
Commit
9a7ba71
·
verified ·
1 Parent(s): 2f24914

Upload danbooru_character_search/index.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. danbooru_character_search/index.py +81 -0
danbooru_character_search/index.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ from functools import lru_cache
3
+
4
+ import numpy as np
5
+ import pandas as pd
6
+ from PIL import Image
7
+ from autofaiss import build_index
8
+ from hfutils.operate import get_hf_fs
9
+ from huggingface_hub import hf_hub_download
10
+ from imgutils.data import load_image
11
+ from imgutils.metrics import ccip_batch_extract_features, ccip_batch_differences, ccip_default_threshold
12
+
13
+ SRC_REPO = 'deepghs/character_index'
14
+
15
+ hf_fs = get_hf_fs()
16
+
17
+
18
+ @lru_cache()
19
+ def _make_index():
20
+ tag_infos = np.array(json.loads(hf_fs.read_text(f'datasets/{SRC_REPO}/index/tag_infos.json')))
21
+ embeddings = np.load(hf_hub_download(
22
+ repo_id=SRC_REPO,
23
+ repo_type='dataset',
24
+ filename='index/embeddings.npy',
25
+ ))
26
+ index, index_infos = build_index(embeddings, save_on_disk=False)
27
+ return (index, index_infos), tag_infos
28
+
29
+
30
+ def gender_predict(p):
31
+ if p['boy'] - p['girl'] >= 0.1:
32
+ return 'male'
33
+ elif p['girl'] - p['boy'] >= 0.1:
34
+ return 'female'
35
+ else:
36
+ return 'not_sure'
37
+
38
+
39
+ def query_character(image: Image.Image, count: int = 5, order_by: str = 'same_ratio', threshold: float = 0.7):
40
+ (index, index_infos), tag_infos = _make_index()
41
+ query = ccip_batch_extract_features([image])
42
+ assert query.shape == (1, 768)
43
+ query = query / np.linalg.norm(query)
44
+ all_dists, all_indices = index.search(query, k=count)
45
+ dists, indices = all_dists[0], all_indices[0]
46
+
47
+ images, records = {}, []
48
+ for dist, idx in zip(dists, indices):
49
+ info = tag_infos[idx]
50
+ current_image = load_image(hf_hub_download(
51
+ repo_id=SRC_REPO,
52
+ repo_type='dataset',
53
+ filename=f'{info["hprefix"]}/{info["short_tag"]}/1.webp'
54
+ ))
55
+ feats = np.load(hf_hub_download(
56
+ repo_id=SRC_REPO,
57
+ repo_type='dataset',
58
+ filename=f'{info["hprefix"]}/{info["short_tag"]}/feat.npy'
59
+ ))
60
+ diffs = ccip_batch_differences([query[0], *feats])[0, 1:]
61
+ images[info['tag']] = current_image
62
+ records.append({
63
+ 'id': info['id'],
64
+ 'tag': info['tag'],
65
+ 'gender': gender_predict(info['gender']),
66
+ 'copyright': info['copyright'],
67
+ 'index_score': dist,
68
+ 'mean_diff': diffs.mean(),
69
+ 'same_ratio': (diffs < ccip_default_threshold()).mean(),
70
+ })
71
+
72
+ df_records = pd.DataFrame(records)
73
+ df_records = df_records.sort_values(
74
+ by=[order_by, 'index_score'] if order_by != 'index_score' else ['index_score'],
75
+ ascending=[False, False] if order_by != 'index_score' else [False],
76
+ )
77
+ df_records = df_records[df_records[order_by] >= threshold]
78
+ ret_images = []
79
+ for row_item in df_records.to_dict('records'):
80
+ ret_images.append((images[row_item['tag']], f'{row_item["tag"]} ({row_item[order_by]:.3f})'))
81
+ return ret_images, df_records