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
2019-06-23 16:53:54 +00:00
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__ )
2019-06-26 08:45:52 +00:00
#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 )
2019-06-26 08:09:07 +00:00
return ' Connection Succesfull '
2019-06-11 09:24:06 +00:00
@app.route ( ' /new_user_id ' )
def new_user_id ( ) :
2019-06-26 08:09:07 +00:00
#save demo object to reserve id in minio
2019-06-11 09:24:06 +00:00
id = None
2019-06-26 08:45:52 +00:00
#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 ' ]
2019-06-26 08:45:52 +00:00
#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 ' )
2019-06-26 08:45:52 +00:00
#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 '
2019-06-26 08:45:52 +00:00
#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 )
2019-06-26 08:45:52 +00:00
#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 ' )
2019-06-23 16:53:54 +00:00
#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 '
2019-06-26 08:45:52 +00:00
#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 )
2019-06-26 08:45:52 +00:00
#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 ) :
2019-06-26 08:45:52 +00:00
#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 )
2019-06-26 08:45:52 +00:00
#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 ) :
2019-06-26 08:45:52 +00:00
#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 :
2019-06-26 08:45:52 +00:00
response = { ' success ' : False , ' encoding ' : None }
2019-06-25 16:56:18 +00:00
else :
2019-06-26 08:45:52 +00:00
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 ( ) :
2019-06-26 08:45:52 +00:00
#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
2019-06-26 08:45:52 +00:00
#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 ( )
2019-06-26 08:45:52 +00:00
#start running the api
2019-06-08 17:11:05 +00:00
app . run ( host = ' 0.0.0.0 ' )