face-recognition-app/face_recognition/app/app.py

129 lines
5.1 KiB
Python
Raw Normal View History

2019-06-24 21:41:30 +00:00
from flask import Flask, request, jsonify
2019-06-08 19:08:20 +00:00
from minio import Minio
2019-06-10 09:59:39 +00:00
from minio.error import (ResponseError, BucketAlreadyOwnedByYou, BucketAlreadyExists)
2019-06-08 18:59:15 +00:00
import os
2019-06-10 10:31:07 +00:00
import uuid
2019-06-11 10:17:19 +00:00
import pickle
2019-06-13 12:11:56 +00:00
import face_recognition
from werkzeug.datastructures import ImmutableMultiDict
2019-06-23 17:18:35 +00:00
import base64
2019-06-24 12:28:17 +00:00
import cv2
import numpy as np
2019-06-24 15:45:28 +00:00
import imutils
2019-06-08 17:11:05 +00:00
app = Flask(__name__)
#establish connection to minio for this instance of the api
2019-06-11 09:44:32 +00:00
minioClient = Minio('minio:9000', access_key=os.environ['s3-name'], secret_key=os.environ['s3-password'], secure=False)
2019-06-08 17:11:05 +00:00
@app.route('/')
def hello_docker():
return 'Hello, I run in a docker container'
2019-06-08 18:59:15 +00:00
@app.route('/acces_minio')
def access_minio():
2019-06-10 09:46:47 +00:00
for bucket in minioClient.list_buckets():
2019-06-10 10:35:09 +00:00
print(bucket.name, bucket.creation_date, flush=True)
return 'Connection Succesfull'
2019-06-11 09:24:06 +00:00
@app.route('/new_user_id')
def new_user_id():
#save demo object to reserve id in minio
2019-06-11 09:24:06 +00:00
id = None
#five tries to generate unique id
2019-06-11 09:24:06 +00:00
for limited_try in range(0,5):
2019-06-11 09:41:28 +00:00
id = str(uuid.uuid4())
2019-06-11 09:38:30 +00:00
if check_id(id) == False:
2019-06-11 09:24:06 +00:00
break
2019-06-11 10:17:19 +00:00
demo_object = ['test']
#dump demo object and save it like its a face encoding to reserve id
2019-06-11 10:42:46 +00:00
with open('/tmp/demo_object.pkl', 'wb') as f:
2019-06-11 10:28:25 +00:00
pickle.dump(demo_object, f)
2019-06-11 10:43:39 +00:00
minioClient.fput_object('users', str(id), '/tmp/demo_object.pkl')
2019-06-25 14:03:58 +00:00
return jsonify({'id':id})
2019-06-13 11:31:17 +00:00
2019-06-23 16:57:04 +00:00
@app.route('/init_face')
#call like https://face.sguba.de/init_face?id=123&encoded_string=base64encoded_urlsafe_string
2019-06-13 11:38:40 +00:00
def new_face():
id = request.args.get('id', None)
2019-06-23 16:54:49 +00:00
img = request.args.get('encoded_string', None)
2019-06-25 14:03:58 +00:00
temporary_img_path = '/tmp/'+str(id)+'.jpg'
temporary_pkl_path = '/tmp/'+str(id)+'.pkl'
#transcode base64_string to img and generate encoding
2019-06-25 14:03:58 +00:00
save_img(img, temporary_img_path)
2019-06-25 16:56:18 +00:00
face_encoding_response = encode_face(temporary_img_path)
#check if encoding was successfull, if yes save encoding in minio
2019-06-25 16:56:18 +00:00
if face_encoding_response['success']==True:
with open(temporary_pkl_path, 'wb') as file:
2019-06-25 17:03:13 +00:00
pickle.dump(face_encoding_response['encoding'], file)
2019-06-25 16:56:18 +00:00
minioClient.fput_object('users', str(id), temporary_pkl_path)
return jsonify({'success':face_encoding_response['success']})
2019-06-13 12:40:33 +00:00
2019-06-23 16:57:04 +00:00
@app.route('/check_face')
#call like https://face.sguba.de/check_face?id=123&encoded_string=abc
2019-06-13 12:40:33 +00:00
def check_face():
id = request.args.get('id', None)
2019-06-23 16:54:49 +00:00
img = request.args.get('encoded_string', None)
2019-06-25 14:03:58 +00:00
temporary_img_path = '/tmp/'+str(id)+'.jpg'
temporary_pkl_path = '/tmp/'+str(id)+'.pkl'
#transcode base64_string to img and generate encoding
2019-06-25 14:03:58 +00:00
save_img(img, temporary_img_path)
2019-06-25 17:11:16 +00:00
face_encoding_response = encode_face(temporary_img_path)
#check if encoding was successfull, if yes get initial encoding from minio and compare encodings
2019-06-25 17:11:16 +00:00
if face_encoding_response['success']==True:
minioClient.fget_object('users', str(id), temporary_pkl_path)
with open(temporary_pkl_path, 'rb') as file:
face_encoding = pickle.load(file)
face_encoding_response['result'] = str(face_recognition.compare_faces([face_encoding], face_encoding_response['encoding'])[0])
2019-06-25 17:18:45 +00:00
else:
face_encoding_response['result'] = str(False)
2019-06-25 17:11:16 +00:00
return jsonify({'result':face_encoding_response['result'],'success':face_encoding_response['success']})
2019-06-13 13:12:51 +00:00
2019-06-11 09:24:06 +00:00
def check_id(id):
2019-06-11 10:17:19 +00:00
#return True -> id bereits verwendet
2019-06-11 09:24:06 +00:00
#return False -> id noch nicht verwendet
users = minioClient.list_objects('users')
known = False
for user in users:
2019-06-11 10:54:43 +00:00
if id == user.object_name:
2019-06-11 09:24:06 +00:00
known = True
else:
pass
return known
2019-06-24 12:28:17 +00:00
def save_img(encoded_data, filename):
#length of base64 string is always a multiple of 4, if not its padded with =, here we add padding that might have been lost so there are no errors when decoding the img
2019-06-25 14:03:58 +00:00
encoded_data += "=" * ((4 - len(encoded_data) % 4) % 4)
#convert string to binary, decode base64, decode image and rotate it 90 degree because android studio rotates the camera, then save image to temp
2019-06-25 14:03:58 +00:00
encoded_data = bytes(encoded_data, encoding='utf-8')
2019-06-24 13:04:52 +00:00
nparr = np.fromstring(base64.urlsafe_b64decode(encoded_data), np.uint8)
2019-06-24 12:28:17 +00:00
img = cv2.imdecode(nparr, cv2.IMREAD_ANYCOLOR)
2019-06-24 15:45:28 +00:00
img = imutils.rotate(img, 90)
2019-06-24 12:28:17 +00:00
return cv2.imwrite(filename, img)
2019-06-25 16:56:18 +00:00
def encode_face(path):
#create face encoding from data, and check wether it was succesfull. If it was unsuccesfull the encodings list is empty
2019-06-25 16:56:18 +00:00
success = None
face = face_recognition.load_image_file(path)
face_encoding = face_recognition.face_encodings(face)
if len(face_encoding)==0:
response = {'success':False, 'encoding':None}
2019-06-25 16:56:18 +00:00
else:
response = {'success':True, 'encoding':face_encoding[0]}
2019-06-25 16:56:18 +00:00
return response
2019-06-10 10:31:07 +00:00
2019-06-10 09:59:39 +00:00
def setup():
#create minio buckets that are used at startup if they dont exist already
2019-06-10 09:59:39 +00:00
try:
minioClient.make_bucket("users")
2019-06-10 10:37:12 +00:00
except BucketAlreadyOwnedByYou as err:
2019-06-10 09:59:39 +00:00
pass
2019-06-10 10:37:12 +00:00
except BucketAlreadyExists as err:
2019-06-10 09:59:39 +00:00
pass
2019-06-10 10:37:12 +00:00
except ResponseError as err:
2019-06-10 09:59:39 +00:00
raise
#check if the script is run primarily and not imported etc.
2019-06-08 17:11:05 +00:00
if __name__ == '__main__':
2019-06-11 09:07:04 +00:00
setup()
#start running the api
2019-06-08 17:11:05 +00:00
app.run(host='0.0.0.0')