Last active
November 14, 2022 19:58
-
-
Save colinfwren/560862f588c5d7a4dab1acdcf3778bfc to your computer and use it in GitHub Desktop.
API to find a face using uploaded image
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from flask import Flask, request, jsonify, make_response | |
from werkzeug.utils import secure_filename | |
import dlib | |
import cv2 | |
import face_recognition | |
import os | |
import postgresql | |
app = Flask(__name__) | |
app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024 | |
app.config['UPLOAD_EXTENSIONS'] = ['.jpg', '.png', '.jpeg'] | |
app.config['UPLOAD_PATH'] = 'uploads' | |
def process_face_matches(face_matches): | |
results = [] | |
for face_match in face_matches: | |
results.append({ | |
'id': face_match[0], | |
'file': face_match[1], | |
'image_id': face_match[2] | |
}) | |
return results | |
def find_face_in_db(local_filename): | |
# Create a HOG face detector using the built-in dlib class | |
face_detector = dlib.get_frontal_face_detector() | |
# Load the image | |
image = cv2.imread(local_filename) | |
# Run the HOG face detector on the image data | |
detected_faces = face_detector(image, 1) | |
print("Found {} faces in the image file {}".format(len(detected_faces), local_filename)) | |
db = postgresql.open(os.environ.get('DATABASE_STRING')) | |
# Loop through each face we found in the image | |
face_records = [] | |
for i, face_rect in enumerate(detected_faces): | |
# Detected faces are returned as an object with the coordinates | |
# of the top, left, right and bottom edges | |
print("- Face #{} found at Left: {} Top: {} Right: {} Bottom: {}".format(i, face_rect.left(), face_rect.top(), | |
face_rect.right(), face_rect.bottom())) | |
crop = image[face_rect.top():face_rect.bottom(), face_rect.left():face_rect.right()] | |
encodings = face_recognition.face_encodings(crop) | |
threshold = 0.6 | |
if len(encodings) > 0: | |
query = "SELECT id, file, image_id FROM vectors WHERE sqrt(power(CUBE(array[{}]) <-> vec_low, 2) + power(CUBE(array[{}]) <-> vec_high, 2)) <= {} ".format( | |
','.join(str(s) for s in encodings[0][0:64]), | |
','.join(str(s) for s in encodings[0][64:128]), | |
threshold, | |
) + \ | |
"ORDER BY sqrt(power(CUBE(array[{}]) <-> vec_low, 2) + power(CUBE(array[{}]) <-> vec_high, 2)) ASC".format( | |
','.join(str(s) for s in encodings[0][0:64]), | |
','.join(str(s) for s in encodings[0][64:128]), | |
) | |
face_record = db.query(query) | |
face_records.append(process_face_matches(face_record)) | |
return face_records | |
@app.route('/faces/searches', methods=['POST']) | |
def faces_searches(): | |
uploaded_file = request.files['file'] | |
filename = secure_filename(uploaded_file.filename) | |
if filename != '': | |
file_ext = os.path.splitext(filename)[1] | |
if file_ext in app.config['UPLOAD_EXTENSIONS']: # and file_ext == validate_image(uploaded_file.stream): | |
file_path = os.path.join(app.config['UPLOAD_PATH'], filename) | |
uploaded_file.save(file_path) | |
face_matches = find_face_in_db(file_path) | |
os.remove(file_path) | |
return make_response(jsonify(matches=face_matches), 200) | |
return make_response(jsonify(error='Invalid file'), 400) | |
if __name__ == "__main__": | |
app.run(debug=True, port=9000) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment