Ready to try!
Signed-off-by: James Ketrenos <james_git@ketrenos.com>
This commit is contained in:
parent
8b94fc1a94
commit
b51e8fa307
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
.env
|
.env
|
||||||
node_modules
|
node_modules
|
||||||
|
frontend/auto-clusters.html
|
||||||
|
@ -50,5 +50,4 @@ COPY /frontend /website/frontend
|
|||||||
COPY /db /website/db
|
COPY /db /website/db
|
||||||
COPY /config /website/config
|
COPY /config /website/config
|
||||||
|
|
||||||
|
|
||||||
CMD [ "/entrypoint.sh" ]
|
CMD [ "/entrypoint.sh" ]
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
},
|
},
|
||||||
"picturesPath": "./pictures",
|
"picturesPath": "./pictures",
|
||||||
"basePath": "/photos",
|
"basePath": "/photos",
|
||||||
"faceData": "./pictures/face-data",
|
"facesPath": "./pictures/face-data",
|
||||||
"sessions": {
|
"sessions": {
|
||||||
"db": "sessions.db",
|
"db": "sessions.db",
|
||||||
"store-secret": "234j23jffj23f!41$@#!1113j3"
|
"store-secret": "234j23jffj23f!41$@#!1113j3"
|
||||||
|
@ -11,7 +11,7 @@ services:
|
|||||||
# - db
|
# - db
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- ${PORT}:${PORT}
|
- ${PORT}:8123
|
||||||
volumes:
|
volumes:
|
||||||
- ${PICTURES}:/pictures
|
- ${PICTURES}:/pictures
|
||||||
- ${PWD}/db:/db
|
- ${PWD}/db:/db
|
||||||
|
@ -14,13 +14,13 @@ from ketrface.dbscan import *
|
|||||||
from ketrface.db import *
|
from ketrface.db import *
|
||||||
from ketrface.config import *
|
from ketrface.config import *
|
||||||
|
|
||||||
html_base = '../'
|
|
||||||
db_path = '../db/photos.db'
|
|
||||||
|
|
||||||
config = read_config()
|
config = read_config()
|
||||||
json_str = json.dumps(config, indent = 2)
|
|
||||||
print(json_str)
|
html_path = merge_config_path(config['path'], 'frontend')
|
||||||
exit(0)
|
pictures_path = merge_config_path(config['path'], config['picturesPath'])
|
||||||
|
faces_path = merge_config_path(config['path'], config['facesPath'])
|
||||||
|
db_path = merge_config_path(config['path'], config["db"]["photos"]["host"])
|
||||||
|
html_base = config['basePath']
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
# Switch to using DBSCAN
|
# Switch to using DBSCAN
|
||||||
@ -52,7 +52,7 @@ def gen_html(identities):
|
|||||||
label = f'Cluster ({face["cluster"]["id"]})'
|
label = f'Cluster ({face["cluster"]["id"]})'
|
||||||
|
|
||||||
print('<div style="position:relative;display:inline-flex;flex-direction:column">')
|
print('<div style="position:relative;display:inline-flex;flex-direction:column">')
|
||||||
path = f'{html_base}/faces/{"{:02d}".format(faceId % 10)}'
|
path = f'{html_base}/faces/{"{:02d}".format(faceId % 100)}'
|
||||||
print(f'<img src="{path}/{faceId}.jpg"/>')
|
print(f'<img src="{path}/{faceId}.jpg"/>')
|
||||||
print(f'<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">{label}: {distance}</div>')
|
print(f'<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">{label}: {distance}</div>')
|
||||||
print(f'<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">{faceId} {photoId} {confidence} {focus}</div>')
|
print(f'<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">{faceId} {photoId} {confidence} {focus}</div>')
|
||||||
@ -140,7 +140,17 @@ def cluster_sort(A, B):
|
|||||||
elif diff < 0:
|
elif diff < 0:
|
||||||
return -1
|
return -1
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
def build_straglers(faces):
|
||||||
|
noise = []
|
||||||
|
undefined = []
|
||||||
|
for face in faces:
|
||||||
|
if face['cluster'] == Noise:
|
||||||
|
noise.append(face)
|
||||||
|
elif face['cluster'] == Undefined:
|
||||||
|
undefined.append(face)
|
||||||
|
return noise + undefined
|
||||||
|
|
||||||
print('Loading faces from database')
|
print('Loading faces from database')
|
||||||
faces = load_faces()
|
faces = load_faces()
|
||||||
print(f'{len(faces)} faces loaded')
|
print(f'{len(faces)} faces loaded')
|
||||||
@ -165,8 +175,6 @@ while removed != 0:
|
|||||||
if removed > 0:
|
if removed > 0:
|
||||||
print(f'Excluded {removed} faces this epoch')
|
print(f'Excluded {removed} faces this epoch')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print(f'{len(identities)} identities seeded.')
|
print(f'{len(identities)} identities seeded.')
|
||||||
|
|
||||||
# Cluster the clusters...
|
# Cluster the clusters...
|
||||||
@ -185,19 +193,22 @@ for cluster in reduced:
|
|||||||
# Creating a set containing those faces which have not been bound
|
# Creating a set containing those faces which have not been bound
|
||||||
# to an identity to recluster them in isolation from the rest of
|
# to an identity to recluster them in isolation from the rest of
|
||||||
# the faces
|
# the faces
|
||||||
noise = []
|
straglers = build_straglers(faces)
|
||||||
undefined = []
|
reduced = reduced + DBSCAN(straglers)
|
||||||
clustered = []
|
|
||||||
for face in faces:
|
|
||||||
if face['cluster'] == Noise:
|
|
||||||
noise.append(face)
|
|
||||||
elif face['cluster'] == Undefined:
|
|
||||||
undefined.append(face)
|
|
||||||
|
|
||||||
print(f'Stats: Noise = {len(noise)}, Undefined = {len(undefined)}')
|
# Build a final cluster with all remaining uncategorized faces
|
||||||
|
remaining_cluster = {
|
||||||
straglers = DBSCAN(noise + undefined)
|
'id': len(reduced) + 1,
|
||||||
reduced = update_cluster_averages(reduced + straglers)
|
'distance': 0,
|
||||||
|
'descriptors': [],
|
||||||
|
'cluster': Undefined,
|
||||||
|
'faces': []
|
||||||
|
}
|
||||||
|
straglers = build_straglers(faces)
|
||||||
|
for face in straglers:
|
||||||
|
face['cluster'] = remaining_cluster
|
||||||
|
remaining_cluster['faces'].append(face)
|
||||||
|
reduced.append(remaining_cluster)
|
||||||
|
|
||||||
# Give all merged identity lists a unique ID
|
# Give all merged identity lists a unique ID
|
||||||
for id, identity in enumerate(reduced):
|
for id, identity in enumerate(reduced):
|
||||||
@ -205,6 +216,8 @@ for id, identity in enumerate(reduced):
|
|||||||
for face in identity['faces']:
|
for face in identity['faces']:
|
||||||
face['cluster'] = identity
|
face['cluster'] = identity
|
||||||
|
|
||||||
|
reduced = update_cluster_averages(reduced)
|
||||||
|
|
||||||
update_distances(reduced)
|
update_distances(reduced)
|
||||||
|
|
||||||
sort_identities(reduced)
|
sort_identities(reduced)
|
||||||
@ -224,7 +237,7 @@ for i, A in enumerate(reduced):
|
|||||||
distance = "{:0.4f}".format(distance)
|
distance = "{:0.4f}".format(distance)
|
||||||
print(f'{A["id"]} to {B["id"]} = {distance}: MERGE')
|
print(f'{A["id"]} to {B["id"]} = {distance}: MERGE')
|
||||||
|
|
||||||
print('Writing to "identities.html"')
|
print('Writing to "auto-clusters.html"')
|
||||||
redirect_on('identities.html')
|
redirect_on(os.path.join(html_path, 'auto-clusters.html'))
|
||||||
gen_html(reduced)
|
gen_html(reduced)
|
||||||
redirect_off()
|
redirect_off()
|
||||||
|
@ -11,8 +11,16 @@ import numpy as np
|
|||||||
import cv2
|
import cv2
|
||||||
from ketrface.util import *
|
from ketrface.util import *
|
||||||
from ketrface.db import *
|
from ketrface.db import *
|
||||||
|
from ketrface.config import *
|
||||||
|
|
||||||
|
config = read_config()
|
||||||
|
|
||||||
|
html_path = merge_config_path(config['path'], 'frontend')
|
||||||
|
pictures_path = merge_config_path(config['path'], config['picturesPath'])
|
||||||
|
faces_path = merge_config_path(config['path'], config['facesPath'])
|
||||||
|
db_path = merge_config_path(config['path'], config["db"]["photos"]["host"])
|
||||||
|
html_base = config['basePath']
|
||||||
|
|
||||||
face_base = '/pictures/'
|
|
||||||
model_name = 'VGG-Face' # 'ArcFace'
|
model_name = 'VGG-Face' # 'ArcFace'
|
||||||
detector_backend = 'mtcnn' # 'retinaface'
|
detector_backend = 'mtcnn' # 'retinaface'
|
||||||
model = DeepFace.build_model(model_name)
|
model = DeepFace.build_model(model_name)
|
||||||
@ -237,7 +245,7 @@ with conn:
|
|||||||
'descriptorId': faceDescriptorId,
|
'descriptorId': faceDescriptorId,
|
||||||
})
|
})
|
||||||
|
|
||||||
path = f'{face_base}faces/{"{:02d}".format(faceId % 10)}'
|
path = f'{faces_path}/{"{:02d}".format(faceId % 100)}'
|
||||||
try:
|
try:
|
||||||
os.makedirs(path)
|
os.makedirs(path)
|
||||||
except FileExistsError:
|
except FileExistsError:
|
||||||
@ -252,6 +260,9 @@ with conn:
|
|||||||
exif_ifd = {piexif.ExifIFD.UserComment: compressed_str}
|
exif_ifd = {piexif.ExifIFD.UserComment: compressed_str}
|
||||||
exif_dict = {"0th": {}, "Exif": exif_ifd, "1st": {},
|
exif_dict = {"0th": {}, "Exif": exif_ifd, "1st": {},
|
||||||
"thumbnail": None, "GPS": {}}
|
"thumbnail": None, "GPS": {}}
|
||||||
image.save(f'{path}/{faceId}.jpg', exif = piexif.dump(exif_dict))
|
image.save(
|
||||||
|
f'{path}/{faceId}.jpg',
|
||||||
|
quality = 'maximum',
|
||||||
|
exif = piexif.dump(exif_dict))
|
||||||
|
|
||||||
update_face_count(conn, photoId, len(faces))
|
update_face_count(conn, photoId, len(faces))
|
||||||
|
@ -1,155 +0,0 @@
|
|||||||
<div>
|
|
||||||
<div><b>Identity 1 has 13</b><br></div>
|
|
||||||
<div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/04/134.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (1): 0.0345</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">134 43 0.999 328</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/02/132.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (1): 0.0472</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">132 42 1.000 259</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/03/73.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (1): 0.0490</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">73 10 1.000 2266</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/07/47.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (1): 0.0651</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">47 7 0.997 4824</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/09/139.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (1): 0.0660</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">139 46 0.998 126</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/07/137.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (1): 0.0674</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">137 44 0.998 727</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/01/71.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (1): 0.0747</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">71 9 1.000 3734</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/06/146.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (1): 0.0753</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">146 50 1.000 178</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/00/130.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (1): 0.0826</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">130 41 1.000 425</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/06/56.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (1): 0.0950</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">56 8 0.999 4833</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/03/143.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (1): 0.0964</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">143 48 1.000 222</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/04/144.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (1): 0.1522</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">144 49 1.000 230</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/05/25.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (1): 0.2030</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">25 6 1.000 205</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div><b>Identity 0 has 9</b><br></div>
|
|
||||||
<div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/06/136.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (0): 0.0690</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">136 44 1.000 779</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/01/131.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (0): 0.0826</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">131 41 0.991 489</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/07/147.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (0): 0.0832</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">147 50 0.998 223</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/05/135.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (0): 0.0923</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">135 43 0.997 262</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/08/138.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (0): 0.1008</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">138 45 0.992 612</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/03/133.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (0): 0.1021</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">133 42 0.992 772</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/04/14.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (0): 0.1084</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">14 5 0.995 2610</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/03/3.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (0): 0.1120</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">3 1 0.999 25</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/06/46.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (0): 0.1525</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">46 7 0.997 4384</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div><b>Identity 2 has 6</b><br></div>
|
|
||||||
<div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/03/83.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (2): 0.0413</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">83 20 0.999 724</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/06/86.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (2): 0.1122</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">86 20 0.996 766</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/05/85.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (2): 0.1245</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">85 20 0.998 931</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/07/87.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (2): 0.1343</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">87 20 0.995 475</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/03/123.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (2): 0.1386</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">123 37 0.998 1097</div>
|
|
||||||
</div>
|
|
||||||
<div style="position:relative;display:inline-flex;flex-direction:column">
|
|
||||||
<img src="..//faces/05/125.jpg"/>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;top:0px;left:0px;right:0px;padding:0.25rem">Cluster (2): 0.1708</div>
|
|
||||||
<div style="background-color:rgba(255, 255, 255, 0.4);position:absolute;bottom:0px;left:0px;right:0px;padding:0.25rem">125 39 1.000 162</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,6 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import collections
|
import re
|
||||||
|
|
||||||
def dict_merge(dct, merge_dct):
|
def dict_merge(dct, merge_dct):
|
||||||
""" Recursive dict merge. Inspired by :meth:``dict.update()``, instead of
|
""" Recursive dict merge. Inspired by :meth:``dict.update()``, instead of
|
||||||
@ -25,7 +25,6 @@ def read_config():
|
|||||||
while file == None:
|
while file == None:
|
||||||
try:
|
try:
|
||||||
config_path = os.path.join(path, 'config', 'default.json')
|
config_path = os.path.join(path, 'config', 'default.json')
|
||||||
print(f'Trying {config_path}')
|
|
||||||
file = open(config_path, 'r')
|
file = open(config_path, 'r')
|
||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
@ -37,6 +36,8 @@ def read_config():
|
|||||||
if file is None:
|
if file is None:
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
res['path'] = path
|
||||||
|
|
||||||
data = json.load(file)
|
data = json.load(file)
|
||||||
file.close()
|
file.close()
|
||||||
dict_merge(res, data)
|
dict_merge(res, data)
|
||||||
@ -55,3 +56,9 @@ def read_config():
|
|||||||
dict_merge(res, data)
|
dict_merge(res, data)
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def merge_config_path(config_path, path):
|
||||||
|
if path[0] == '/':
|
||||||
|
return os.path.normpath(path)
|
||||||
|
return os.path.normpath(os.path.join(config_path, path))
|
||||||
|
|
@ -16,6 +16,7 @@ const express = require("express"),
|
|||||||
require("./console-line.js"); /* Monkey-patch console.log with line numbers */
|
require("./console-line.js"); /* Monkey-patch console.log with line numbers */
|
||||||
|
|
||||||
const picturesPath = config.get("picturesPath").replace(/\/$/, "") + "/",
|
const picturesPath = config.get("picturesPath").replace(/\/$/, "") + "/",
|
||||||
|
facesPath = config.get("facesPath").replace(/\/$/, "") + "/",
|
||||||
serverConfig = config.get("server");
|
serverConfig = config.get("server");
|
||||||
|
|
||||||
let basePath = config.get("basePath");
|
let basePath = config.get("basePath");
|
||||||
@ -25,8 +26,9 @@ if (basePath == "//") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let photoDB = null, userDB = null;
|
let photoDB = null, userDB = null;
|
||||||
console.log("Loading pictures out of: " + picturesPath);
|
console.log(`Loading pictures out of: ${picturesPath}`);
|
||||||
console.log("Hosting server from: " + basePath);
|
console.log(`Loading faces out of: ${facesPath} (mapped to ${basePath}faces})`);
|
||||||
|
console.log(`Hosting server from: ${basePath}`);
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
@ -238,7 +240,7 @@ app.use(basePath, index);
|
|||||||
const users = require("./routes/users");
|
const users = require("./routes/users");
|
||||||
app.use(basePath + "api/v1/users", users.router);
|
app.use(basePath + "api/v1/users", users.router);
|
||||||
|
|
||||||
app.use(function(err, req, res, next) {
|
app.use((err, req, res, next) => {
|
||||||
res.status(err.status || 500).json({
|
res.status(err.status || 500).json({
|
||||||
message: err.message,
|
message: err.message,
|
||||||
error: {}
|
error: {}
|
||||||
@ -246,7 +248,7 @@ app.use(function(err, req, res, next) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* Check authentication */
|
/* Check authentication */
|
||||||
app.use(basePath, function(req, res, next) {
|
app.use(basePath, (req, res, next) => {
|
||||||
return users.getSessionUser(req).then(function(user) {
|
return users.getSessionUser(req).then(function(user) {
|
||||||
if (user.restriction) {
|
if (user.restriction) {
|
||||||
return res.status(401).send(user.restriction);
|
return res.status(401).send(user.restriction);
|
||||||
@ -258,6 +260,11 @@ app.use(basePath, function(req, res, next) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.use(`${basePath}faces/`, express.static(facesPath, {
|
||||||
|
maxAge: '14d',
|
||||||
|
index: false
|
||||||
|
}));
|
||||||
|
|
||||||
/* Everything below here requires a successful authentication */
|
/* Everything below here requires a successful authentication */
|
||||||
app.use(basePath, express.static(picturesPath, {
|
app.use(basePath, express.static(picturesPath, {
|
||||||
maxAge: '14d',
|
maxAge: '14d',
|
||||||
|
@ -37,7 +37,7 @@ const maxConcurrency = require("os").cpus().length;
|
|||||||
require("./console-line.js"); /* Monkey-patch console.log with line numbers */
|
require("./console-line.js"); /* Monkey-patch console.log with line numbers */
|
||||||
|
|
||||||
const picturesPath = config.get("picturesPath").replace(/\/$/, "") + "/",
|
const picturesPath = config.get("picturesPath").replace(/\/$/, "") + "/",
|
||||||
faceData = picturesPath + "face-data/";
|
facesPath = config.get("facesPath").replace(/\/$/, "") + "/";
|
||||||
|
|
||||||
let photoDB = null;
|
let photoDB = null;
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ require("./db/photos").then(function(db) {
|
|||||||
return Promise.map(faces, (face) => {
|
return Promise.map(faces, (face) => {
|
||||||
return Promise.map([ "-data.json", "-original.png" ], (suffix) => {
|
return Promise.map([ "-data.json", "-original.png" ], (suffix) => {
|
||||||
const id = face.id,
|
const id = face.id,
|
||||||
dataPath = faceData + (id % 100) + "/" + id + suffix;
|
dataPath = facesPath + (id % 100) + "/" + id + suffix;
|
||||||
return exists(dataPath).then((result) => {
|
return exists(dataPath).then((result) => {
|
||||||
if (result) {
|
if (result) {
|
||||||
console.log(`...removing ${dataPath}`);
|
console.log(`...removing ${dataPath}`);
|
||||||
@ -185,7 +185,7 @@ require("./db/photos").then(function(db) {
|
|||||||
}).spread((results, metadata) => {
|
}).spread((results, metadata) => {
|
||||||
return metadata.lastID;
|
return metadata.lastID;
|
||||||
}).then((id) => {
|
}).then((id) => {
|
||||||
const path = faceData + (id % 100);
|
const path = facesPath + (id % 100);
|
||||||
return mkdir(path).then(() => {
|
return mkdir(path).then(() => {
|
||||||
const dataPath = `${path}/${id}-data.json`, data = [];
|
const dataPath = `${path}/${id}-data.json`, data = [];
|
||||||
console.log(`...writing descriptor data to ${dataPath}...`);
|
console.log(`...writing descriptor data to ${dataPath}...`);
|
||||||
@ -280,7 +280,7 @@ require("./db/photos").then(function(db) {
|
|||||||
console.log(`...reading ${allFaces.length} descriptors...`);
|
console.log(`...reading ${allFaces.length} descriptors...`);
|
||||||
return Promise.map(allFaces, (face) => {
|
return Promise.map(allFaces, (face) => {
|
||||||
const id = face.id,
|
const id = face.id,
|
||||||
dataPath = faceData + "/" + (id % 100) + "/" + id + "-data.json";
|
dataPath = facesPath + "/" + (id % 100) + "/" + id + "-data.json";
|
||||||
|
|
||||||
if (id in descriptors) {
|
if (id in descriptors) {
|
||||||
return;
|
return;
|
||||||
|
@ -22,7 +22,7 @@ const maxConcurrency = require("os").cpus().length;
|
|||||||
require("./console-line.js"); /* Monkey-patch console.log with line numbers */
|
require("./console-line.js"); /* Monkey-patch console.log with line numbers */
|
||||||
|
|
||||||
const picturesPath = config.get("picturesPath").replace(/\/$/, "") + "/",
|
const picturesPath = config.get("picturesPath").replace(/\/$/, "") + "/",
|
||||||
faceData = picturesPath + "face-data/";
|
facesPath = config.get("facesPath").replace(/\/$/, "") + "/";
|
||||||
|
|
||||||
function alignFromLandmarks(image, landmarks, drawLandmarks) {
|
function alignFromLandmarks(image, landmarks, drawLandmarks) {
|
||||||
const faceMargin = 0.45,
|
const faceMargin = 0.45,
|
||||||
@ -151,7 +151,7 @@ require("./db/photos").then(function(db) {
|
|||||||
_height: (photo.bottom - photo.top) * photo.height,
|
_height: (photo.bottom - photo.top) * photo.height,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
descriptor: JSON.parse(fs.readFileSync(faceData + (id % 100) + "/" + id + "-data.json"))
|
descriptor: JSON.parse(fs.readFileSync(facesPath + (id % 100) + "/" + id + "-data.json"))
|
||||||
} ];
|
} ];
|
||||||
return [ file, image, detectors ];
|
return [ file, image, detectors ];
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user