Scoring working!

Signed-off-by: James Ketrenos <james_git@ketrenos.com>
This commit is contained in:
James Ketr 2023-01-05 19:39:21 -08:00
parent 7a960c5f1f
commit 81e8a12546
2 changed files with 84 additions and 30 deletions

View File

@ -9,6 +9,10 @@ import numpy as np
from deepface import DeepFace
from retinaface import RetinaFace
sqlite3.register_adapter(np.array, lambda arr: arr.tobytes())
sqlite3.register_converter("array", np.frombuffer)
class NpEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, np.integer):
@ -96,6 +100,29 @@ def update_face_count(conn, photoId, faces):
conn.commit()
return None
def findCosineDistance(source_representation, test_representation):
if type(source_representation) == list:
source_representation = np.array(source_representation)
if type(test_representation) == list:
test_representation = np.array(test_representation)
a = np.matmul(np.transpose(source_representation), test_representation)
b = np.sum(np.multiply(source_representation, source_representation))
c = np.sum(np.multiply(test_representation, test_representation))
return 1 - (a / (np.sqrt(b) * np.sqrt(c)))
def findEuclideanDistance(source_representation, test_representation):
if type(source_representation) == list:
source_representation = np.array(source_representation)
if type(test_representation) == list:
test_representation = np.array(test_representation)
euclidean_distance = source_representation - test_representation
euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
euclidean_distance = np.sqrt(euclidean_distance)
return euclidean_distance
def l2_normalize(x):
return x / np.sqrt(np.sum(np.multiply(x, x)))
base = '/pictures/'
conn = create_connection('../db/photos.db')
faces = {}
@ -106,16 +133,55 @@ with conn:
res = cur.execute('''
SELECT faces.id,facedescriptors.descriptors
FROM faces
LEFT JOIN facedescriptors ON (faces.descriptorId=facedescriptors.id)
JOIN facedescriptors ON (faces.descriptorId=facedescriptors.id)
WHERE faces.identityId IS null
''')
for row in res.fetchall():
id, descriptors = row
if faces[id] is None:
face = {}
faces[id] = face
else:
if id in faces:
face = faces[id]
face['descriptors'] = descriptors
else:
face = {
'id': id,
'scanned': False
}
faces[id] = face
face['descriptors'] = np.frombuffer(descriptors)
for key1 in faces:
face1 = faces[key1]
if face1['scanned'] == True:
continue
face1['scanned'] = True
for key2 in faces:
if key1 == key2:
continue
face2 = faces[key2]
face = {
'between': (face1['id'], face2['id'])
}
face['distanceCosine'] = findCosineDistance(
face1['descriptors'],
face2['descriptors']
)
face['distanceEuclidian'] = findEuclideanDistance(
face1['descriptors'],
face2['descriptors']
)
face['distanceEuclidianL2'] = findEuclideanDistance(
l2_normalize(face1['descriptors']),
l2_normalize(face2['descriptors'])
)
face['scoring'] = 0
if face['distanceCosine'] >= 0.68:
face['scoring'] += 1
if face['distanceEuclidian'] >= 4.15:
face['scoring'] += 1
if face['distanceEuclidianL2'] >= 1.13:
face['scoring'] += 1
if face['scoring'] == 3: # Same face!
print(face)
# update_face_count(conn, photoId, len(faces))

View File

@ -62,11 +62,10 @@ def extract_faces(img, threshold=0.75, model = None, allow_upscaling = True):
# Re-implementation of 'extract_faces' with the addition of keeping a
# copy of the face image for caching on disk
if type(faces) == dict:
print(f'Found {len(faces)} faces')
i=1
k=1
for key in faces:
print(f'Processing face {i}/{len(faces)}')
i+=1
print(f'Processing face {k}/{len(faces)}')
k+=1
identity = faces[key]
facial_area = identity["facial_area"]
landmarks = identity["landmarks"]
@ -112,7 +111,7 @@ def extract_faces(img, threshold=0.75, model = None, allow_upscaling = True):
# Eye order is reversed as the routine does them backwards
image = Image.fromarray(facial_img)
image = alignment_procedure(image, right_eye, left_eye)
#image = image.resize(size = input_shape, resample = Image.LANCZOS)
image = image.resize(size = input_shape, resample = Image.LANCZOS)
resized = np.asarray(image)
identity['vector'] = DeepFace.represent(
@ -122,7 +121,6 @@ def extract_faces(img, threshold=0.75, model = None, allow_upscaling = True):
detector_backend = 'retinaface',
enforce_detection = False)
print(img.shape)
identity["face"] = {
'top': facial_area[1] / img.shape[0],
'left': facial_area[0] / img.shape[1],
@ -159,8 +157,8 @@ def create_face(conn, face):
:return: face id
"""
sql = '''
INSERT INTO faces(photoId,scanVersion,faceConfidence,top,left,bottom,right)
VALUES(?,?,?,?,?,?,?)
INSERT INTO faces(photoId,scanVersion,faceConfidence,top,left,bottom,right,descriptorId)
VALUES(?,?,?,?,?,?,?,?)
'''
cur = conn.cursor()
cur.execute(sql, (
@ -170,7 +168,8 @@ def create_face(conn, face):
face['top'],
face['left'],
face['bottom'],
face['right']
face['right'],
face['descriptorId']
))
conn.commit()
return cur.lastrowid
@ -179,8 +178,7 @@ def create_face_descriptor(conn, face):
"""
Create a new face in the faces table
:param conn:
:param faceId:
:param descriptor:
:param face:
:return: descriptor id
"""
sql = '''
@ -232,10 +230,12 @@ with conn:
if faces is None:
update_face_count(conn, photoId, 0)
continue
print(f'Handling {len(faces)} faces')
j=1
for key in faces:
face = faces[key]
image = face['image']
print(f'Writing face {j}/{len(faces)}')
j+=1
#face['analysis'] = DeepFace.analyze(img_path = img, actions = ['age', 'gender', 'race', 'emotion'], enforce_detection = False)
#face['analysis'] = DeepFace.analyze(img, actions = ['emotion'])
@ -279,15 +279,3 @@ with conn:
#print(df.head())
update_face_count(conn, photoId, len(faces))
exit(0)
#img2_path = sys.argv[2]
#print("image 1: ", img1_path);
#print("image 2: ", img2_path);
#result = DeepFace.verify(img1_path = img1_path, img2_path = img2_path, #model_name = models[1])
#print("result: ", result)
#face recognition
#df = DeepFace.find(img_path = img1_path, db_path = "./db/deepface", model_name = models[1])
#print("df: ", df)