Skip to content

Instantly share code, notes, and snippets.

@colinfwren
Last active November 14, 2022 19:58
Show Gist options
  • Save colinfwren/560862f588c5d7a4dab1acdcf3778bfc to your computer and use it in GitHub Desktop.
Save colinfwren/560862f588c5d7a4dab1acdcf3778bfc to your computer and use it in GitHub Desktop.
API to find a face using uploaded image
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