Spaces:
Runtime error
Runtime error
Commit
·
5d3f355
1
Parent(s):
98d84be
semi final
Browse files- .gitignore +5 -0
- app.py +36 -3
- face_recognition.py +26 -0
- photo_search.py +32 -0
- requirements.txt +72 -0
- util/__pycache__/download.cpython-311.pyc +0 -0
- util/download.py +14 -0
.gitignore
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.env
|
2 |
+
temp/
|
3 |
+
tmp/
|
4 |
+
*.npz
|
5 |
+
*.ann
|
app.py
CHANGED
@@ -1,7 +1,40 @@
|
|
1 |
import gradio as gr
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
-
|
4 |
-
|
|
|
|
|
|
|
5 |
|
6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
iface.launch()
|
|
|
1 |
import gradio as gr
|
2 |
+
from util import download
|
3 |
+
import os
|
4 |
+
from dotenv import load_dotenv
|
5 |
+
from photo_search import PhotoSearch
|
6 |
+
from PIL import Image
|
7 |
|
8 |
+
load_dotenv()
|
9 |
+
# tree_path = download.gdrive(os.getenv('TREE_GDRIVE_ID'), dir='temp')
|
10 |
+
# data_path = download.gdrive(os.getenv('DATA_GDRIVE_ID'), dir='temp')
|
11 |
+
tree_path= 'temp/trees.ann'
|
12 |
+
data_path = 'temp/result_torch.npz'
|
13 |
|
14 |
+
ai = PhotoSearch(tree_path, data_path)
|
15 |
+
|
16 |
+
def search_photo(image):
|
17 |
+
try:
|
18 |
+
found_ids = ai.search(image)
|
19 |
+
if len(found_ids) == 0:
|
20 |
+
return '''
|
21 |
+
Foto Serupa Tidak Ditemukan, Tips:
|
22 |
+
- Gunakan foto terupdate,
|
23 |
+
- Jika kamu punya foto saat lari, lebih baik gunakan foto itu,
|
24 |
+
- Jangan menggunakan foto blur,
|
25 |
+
- Jangan upload foto yang menggunakan aksesoris yang tidak kamu gunakan saat lari (semisal kacamata)
|
26 |
+
'''
|
27 |
+
|
28 |
+
result = f"{len(found_ids)} foto kamu berhasil ditemukan!"
|
29 |
+
except Exception as e:
|
30 |
+
result = f"Gagal: {e}"
|
31 |
+
return result
|
32 |
+
|
33 |
+
|
34 |
+
gr_inputs = [
|
35 |
+
gr.Image(type='pil')
|
36 |
+
]
|
37 |
+
|
38 |
+
gr.Markdown('Upload Foto Wajah Kamu Ya (Pastikan hanya terdapat SATU wajah pada foto yang kamu upload)')
|
39 |
+
iface = gr.Interface(fn=search_photo, inputs=gr_inputs, outputs="markdown")
|
40 |
iface.launch()
|
face_recognition.py
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from facenet_pytorch import InceptionResnetV1, MTCNN as FACE_DETECTOR
|
2 |
+
import torch
|
3 |
+
import numpy as np
|
4 |
+
|
5 |
+
device = 'cuda:0' if torch.cuda.is_available() else 'cpu'
|
6 |
+
print('running device: ', device)
|
7 |
+
|
8 |
+
class FacenetPytorch:
|
9 |
+
|
10 |
+
def __init__(self):
|
11 |
+
self.face_detector = FACE_DETECTOR(keep_all=True, device=device, margin=20, thresholds=[0.6, 0.9, 0.9])
|
12 |
+
self.resnet = InceptionResnetV1(pretrained='vggface2').eval()
|
13 |
+
|
14 |
+
def get_embedding(self, image):
|
15 |
+
faces = self.extract_faces(image)
|
16 |
+
assert len(faces) == 1, f"total face should be 1, instead of {len(faces)}"
|
17 |
+
return np.squeeze(self.resnet(faces[0]).detach().numpy())
|
18 |
+
|
19 |
+
def extract_faces(self, image):
|
20 |
+
result = []
|
21 |
+
faces = self.face_detector(image)
|
22 |
+
if faces is not None:
|
23 |
+
print('total face: ', len(faces))
|
24 |
+
for face in faces:
|
25 |
+
result.append(face.unsqueeze(0))
|
26 |
+
return result
|
photo_search.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from annoy import AnnoyIndex
|
2 |
+
from face_recognition import FacenetPytorch
|
3 |
+
import numpy as np
|
4 |
+
from numpy.linalg import norm
|
5 |
+
|
6 |
+
class PhotoSearch:
|
7 |
+
def __init__ (self, tree_path, data_path, index_size = 512):
|
8 |
+
self.tree_path = tree_path
|
9 |
+
self.data_path = data_path
|
10 |
+
|
11 |
+
self.t = AnnoyIndex(index_size, 'angular')
|
12 |
+
self.t.load(tree_path)
|
13 |
+
|
14 |
+
data = np.load(data_path, allow_pickle=True)
|
15 |
+
self.face_grive_id = data.f.id
|
16 |
+
self.extractor = FacenetPytorch()
|
17 |
+
|
18 |
+
def search(self, image):
|
19 |
+
face_emb = self.extractor.get_embedding(image)
|
20 |
+
nns = self.t.get_nns_by_vector(face_emb, 20)
|
21 |
+
result = []
|
22 |
+
for n in nns:
|
23 |
+
face_origin = self.t.get_item_vector(n)
|
24 |
+
print(self.face_grive_id[n])
|
25 |
+
if self.cosine(face_emb, face_origin) < 0.7: continue
|
26 |
+
|
27 |
+
result.append('get..')
|
28 |
+
|
29 |
+
return result
|
30 |
+
|
31 |
+
def cosine(self, x, y):
|
32 |
+
return np.dot(x,y)/(norm(x)*norm(y))
|
requirements.txt
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
aiofiles==23.1.0
|
2 |
+
aiohttp==3.8.5
|
3 |
+
aiosignal==1.3.1
|
4 |
+
altair==5.0.1
|
5 |
+
annotated-types==0.5.0
|
6 |
+
annoy==1.17.3
|
7 |
+
async-timeout==4.0.2
|
8 |
+
click==8.1.6
|
9 |
+
cmake==3.27.0
|
10 |
+
contourpy==1.1.0
|
11 |
+
cycler==0.11.0
|
12 |
+
facenet-pytorch==2.5.3
|
13 |
+
fastapi==0.100.1
|
14 |
+
ffmpy==0.3.1
|
15 |
+
fonttools==4.41.1
|
16 |
+
frozenlist==1.4.0
|
17 |
+
fsspec==2023.6.0
|
18 |
+
gdown==4.7.1
|
19 |
+
gradio==3.39.0
|
20 |
+
gradio_client==0.3.0
|
21 |
+
h11==0.14.0
|
22 |
+
httpcore==0.17.3
|
23 |
+
httpx==0.24.1
|
24 |
+
huggingface-hub==0.16.4
|
25 |
+
keras==2.13.1
|
26 |
+
kiwisolver==1.4.4
|
27 |
+
linkify-it-py==2.0.2
|
28 |
+
lit==16.0.6
|
29 |
+
matplotlib==3.7.2
|
30 |
+
mdit-py-plugins==0.3.3
|
31 |
+
mpmath==1.3.0
|
32 |
+
mtcnn==0.1.1
|
33 |
+
multidict==6.0.4
|
34 |
+
networkx==3.1
|
35 |
+
numpy==1.25.1
|
36 |
+
nvidia-cublas-cu11==11.10.3.66
|
37 |
+
nvidia-cuda-cupti-cu11==11.7.101
|
38 |
+
nvidia-cuda-nvrtc-cu11==11.7.99
|
39 |
+
nvidia-cuda-runtime-cu11==11.7.99
|
40 |
+
nvidia-cudnn-cu11==8.5.0.96
|
41 |
+
nvidia-cufft-cu11==10.9.0.58
|
42 |
+
nvidia-curand-cu11==10.2.10.91
|
43 |
+
nvidia-cusolver-cu11==11.4.0.1
|
44 |
+
nvidia-cusparse-cu11==11.7.4.91
|
45 |
+
nvidia-nccl-cu11==2.14.3
|
46 |
+
nvidia-nvtx-cu11==11.7.91
|
47 |
+
opencv-python==4.8.0.74
|
48 |
+
orjson==3.9.2
|
49 |
+
pandas==2.0.3
|
50 |
+
Pillow==10.0.0
|
51 |
+
pydantic==2.1.1
|
52 |
+
pydantic_core==2.4.0
|
53 |
+
pydub==0.25.1
|
54 |
+
pyparsing==3.0.9
|
55 |
+
PySocks==1.7.1
|
56 |
+
python-dotenv==1.0.0
|
57 |
+
python-multipart==0.0.6
|
58 |
+
pytz==2023.3
|
59 |
+
semantic-version==2.10.0
|
60 |
+
starlette==0.27.0
|
61 |
+
sympy==1.12
|
62 |
+
toolz==0.12.0
|
63 |
+
torch==2.0.1
|
64 |
+
torchvision==0.15.2
|
65 |
+
tqdm==4.65.0
|
66 |
+
triton==2.0.0
|
67 |
+
typing_extensions==4.7.1
|
68 |
+
tzdata==2023.3
|
69 |
+
uc-micro-py==1.0.2
|
70 |
+
uvicorn==0.23.1
|
71 |
+
websockets==11.0.3
|
72 |
+
yarl==1.9.2
|
util/__pycache__/download.cpython-311.pyc
ADDED
Binary file (858 Bytes). View file
|
|
util/download.py
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gdown
|
2 |
+
import os
|
3 |
+
|
4 |
+
|
5 |
+
def gdrive(id, dir = "."):
|
6 |
+
filename = gdown.download(id=id, quiet=True)
|
7 |
+
file_path = f'{dir}/{filename}'
|
8 |
+
|
9 |
+
if os.path.isdir(dir) == False: os.mkdir(dir)
|
10 |
+
try:
|
11 |
+
os.replace(filename, file_path)
|
12 |
+
except:
|
13 |
+
print('replace err...')
|
14 |
+
return file_path
|