import faiss
|
import cv2
|
import time
|
import sys
|
import numpy as np
|
import pandas as pd
|
from flask import Flask
|
from flask import request
|
from flask import render_template
|
|
### search for vehicle or face
|
if len(sys.argv) != 2:
|
print("search for vehicle or face?")
|
print("'python3 search_server.py vehicle' OR 'python3 search_server.py face'")
|
quit()
|
search_for_vehicle = True if sys.argv[1] == "vehicle" else False
|
###
|
|
|
'''
|
create Index Object of faiss
|
'''
|
# load csv from disk
|
embedding_df = pd.read_csv("embeddings.csv", sep='|', index_col=0)
|
print(f"load csv snapshot, contains {len(embedding_df)} embeddings!")
|
print(embedding_df)
|
|
# create Index Object
|
embeddings_list = [[e for e in str(embedding).split(',')] for embedding in embedding_df["embedding"].to_list()]
|
embeddings = np.array(embeddings_list)
|
print(f"load embeddings successfully, shape is {embeddings.shape}")
|
dimension = embeddings.shape[1]
|
# you can try different Index type
|
search_index = faiss.IndexFlatIP(dimension)
|
# add all embeddings into Index, use it in search action later
|
search_index.add(embeddings)
|
|
|
'''
|
generate embedding data for query image
|
'''
|
# vehicle embedding model keep as same as vehicle_encoding_pipeline.cpp
|
vehicle_embedding_model_path = "../../../vp_data/models/trt/vehicle/dim256_batch=1_0916_norm.onnx"
|
# face embedding model keep as same as face_encoding_pipeline.cpp
|
face_embedding_model_path = "../../../vp_data/models/face/face_recognition_sface_2021dec.onnx"
|
|
embedding_model_path = vehicle_embedding_model_path if search_for_vehicle else face_embedding_model_path
|
input_size = (256, 256) if search_for_vehicle else (112, 112)
|
net = cv2.dnn.readNetFromONNX(embedding_model_path)
|
output_layer_names = net.getUnconnectedOutLayersNames()
|
def generate_embedding(query_image):
|
input_image = cv2.resize(query_image, input_size)
|
blob = cv2.dnn.blobFromImage(input_image)
|
net.setInput(blob)
|
out = net.forward(output_layer_names)
|
embedding = np.array(out[0])
|
return embedding
|
|
|
'''
|
create flask app
|
'''
|
app = Flask(__name__)
|
|
# home page
|
@app.route("/")
|
def home():
|
search_for = 'vehicles' if search_for_vehicle else 'faces'
|
return render_template("home.html", total_images = search_index.ntotal, search_for = search_for)
|
|
# search action
|
@app.route("/search", methods=["POST"])
|
def search():
|
# no exception catch
|
query_image = request.files['query_image']
|
topK = int(request.form['topK'])
|
|
# convert to cv2.mat and save to disk
|
img_array = np.asarray(bytearray(query_image.read()), dtype=np.uint8)
|
query_mat = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
|
query_image_path = "static/query_images/" + str(time.time()) + ".jpg"
|
cv2.imwrite(query_image_path, query_mat)
|
|
# generate embedding for query image and do search action
|
query_embedding = generate_embedding(query_mat)
|
D, I = search_index.search(query_embedding, topK)
|
|
# print search info
|
print("query embedding:")
|
print(query_embedding)
|
print("similiarity distance:")
|
print(D)
|
print("similiarity uid:")
|
print(I)
|
|
# shoot data
|
shoot_df = embedding_df.iloc[I[0]]
|
shoot_path = shoot_df['path']
|
shoot_distance = D[0]
|
shoot_uid = I[0]
|
|
# render search results
|
search_results = []
|
for i,p,d in zip(shoot_uid, shoot_path, shoot_distance):
|
search_results.append({"uid": i, "image_url": p, "distance":d})
|
return render_template("search_result.html", topK=topK, search_results=search_results, query_image_url=query_image_path)
|
|
|
if __name__ == "__main__":
|
app.run(host="192.168.77.68", port=9999)
|