-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathimage_retrieve.py
More file actions
158 lines (131 loc) · 4.87 KB
/
Copy pathimage_retrieve.py
File metadata and controls
158 lines (131 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import os
import uuid
from tqdm import tqdm
from qdrant_client import models, QdrantClient
from clip_client import ChineseClipTorch
from loguru import logger
def get_dir_files_path(file_dir, filetype='.txt'):
"""
Obtain the absolute paths of all files with the specified file type in the directory.
Args:
file_dir (str): The directory path.
filetype (str): The file type, e.g. '.txt'. If None, all files will be included.
Returns:
list: The absolute paths of all files with the specified file type.
"""
files_path = []
for root, dirs, files in os.walk(file_dir):
for file in files:
if filetype is None or (os.path.splitext(file)[1] == filetype):
files_path.append(os.path.join(root, file))
return files_path
class ImageRetrieve:
def __init__(self) -> None:
self.clip_client = ChineseClipTorch()
self.db_path = "./data/vector_db"
self.qdrant = QdrantClient(path=self.db_path)
self.collection_name = "image_retrieve"
self.vector_dim = 768
self.topn = 10
def create_collection(self):
"""
Create a new collection in the Qdrant database if it doesn't already exist.
"""
if not self.qdrant.collection_exists(self.collection_name):
self.qdrant.create_collection(
collection_name=self.collection_name,
vectors_config=models.VectorParams(
size=self.vector_dim, # Vector size is defined by used model
distance=models.Distance.COSINE
)
)
logger.info(f"Created {self.collection_name} successfully")
else:
logger.info(f"{self.collection_name} collection already exists")
def insert_single_data(self, id, doc):
"""
Insert a single data record into the Qdrant database.
Args:
id (str): The unique identifier for the data record.
doc (dict): The data record, including the image path.
"""
self.qdrant.upload_records(
collection_name=self.collection_name,
records=[
models.Record(
id=id,
vector=self.clip_client.compute_image_features(doc["image_path"])[0],
payload=doc
)
]
)
def batch_insert_data(self, documents):
"""
Insert a batch of data records into the Qdrant database.
Args:
documents (list): A list of data records, each containing an image path and a unique identifier.
"""
self.qdrant.upload_records(
collection_name=self.collection_name,
records=[
models.Record(
id=doc["id"],
vector=self.clip_client.compute_image_features(doc["image_path"])[0],
payload=doc
) for idx, doc in tqdm(enumerate(documents), total=len(documents))
]
)
def text2image(self, text):
"""
Retrieve the most similar images to the given text query.
Args:
text (str): The text query.
Returns:
list: The paths of the top-n most similar images.
"""
result = []
hits = self.qdrant.search(
collection_name=self.collection_name,
query_vector=self.clip_client.compute_text_features(text)[0],
limit=self.topn
)
for hit in hits:
image_path = hit.payload["image_path"]
score = hit.score
result.append(image_path)
return result
def image2image(self, image_path):
"""
Retrieve the most similar images to the given image.
Args:
image_path (str): The path of the input image.
Returns:
list: The paths of the top-n most similar images.
"""
result = []
hits = self.qdrant.search(
collection_name=self.collection_name,
query_vector=self.clip_client.compute_image_features(image_path)[0],
limit=self.topn
)
for hit in hits:
image_path = hit.payload["image_path"]
score = hit.score
result.append(image_path)
return result
if __name__ == "__main__":
image_retrieve = ImageRetrieve()
image_retrieve.create_collection()
image_dir = "./data/images"
files = get_dir_files_path(image_dir, '.png')
documents = []
for idx, file in enumerate(files):
document = {
"image_path": file,
"id": str(uuid.uuid4())
}
documents.append(document)
image_retrieve.batch_insert_data(documents)
query = "书包"
result = image_retrieve.text2image(query)
print(result)