Commented most relevant files for submission

This commit is contained in:
fabrice 2019-06-26 10:45:52 +02:00
parent ffc345aaab
commit 4fa3571a27
3 changed files with 29 additions and 16 deletions

View File

@ -1,9 +1,11 @@
FROM python:3.6
#copy requirements file and install required libraries. CMake is installed seperately because it is needed for face recognition and the way pip installs the requirements file fails as CMake isnt installed in time
COPY ./requirements.txt /app/requirements.txt
WORKDIR /app
RUN pip install CMake
RUN pip install -r requirements.txt
RUN rm requirements.txt
#make new user so the container duesnt run using root, then copy the api and start it
RUN useradd -ms /bin/bash admin
USER admin
COPY /app .

View File

@ -11,6 +11,7 @@ import cv2
import numpy as np
import imutils
app = Flask(__name__)
#establish connection to minio for this instance of the api
minioClient = Minio('minio:9000', access_key=os.environ['s3-name'], secret_key=os.environ['s3-password'], secure=False)
@app.route('/')
@ -27,25 +28,29 @@ def access_minio():
def new_user_id():
#save demo object to reserve id in minio
id = None
#five tries to generate unique id
for limited_try in range(0,5):
id = str(uuid.uuid4())
if check_id(id) == False:
break
demo_object = ['test']
#dump demo object and save it like its a face encoding to reserve id
with open('/tmp/demo_object.pkl', 'wb') as f:
pickle.dump(demo_object, f)
minioClient.fput_object('users', str(id), '/tmp/demo_object.pkl')
return jsonify({'id':id})
@app.route('/init_face')
#call like https://face.sguba.de/init_face?id=123&encoded_string=abc
#call like https://face.sguba.de/init_face?id=123&encoded_string=base64encoded_urlsafe_string
def new_face():
id = request.args.get('id', None)
img = request.args.get('encoded_string', None)
temporary_img_path = '/tmp/'+str(id)+'.jpg'
temporary_pkl_path = '/tmp/'+str(id)+'.pkl'
#transcode base64_string to img and generate encoding
save_img(img, temporary_img_path)
face_encoding_response = encode_face(temporary_img_path)
#check if encoding was successfull, if yes save encoding in minio
if face_encoding_response['success']==True:
with open(temporary_pkl_path, 'wb') as file:
pickle.dump(face_encoding_response['encoding'], file)
@ -59,8 +64,10 @@ def check_face():
img = request.args.get('encoded_string', None)
temporary_img_path = '/tmp/'+str(id)+'.jpg'
temporary_pkl_path = '/tmp/'+str(id)+'.pkl'
#transcode base64_string to img and generate encoding
save_img(img, temporary_img_path)
face_encoding_response = encode_face(temporary_img_path)
#check if encoding was successfull, if yes get initial encoding from minio and compare encodings
if face_encoding_response['success']==True:
minioClient.fget_object('users', str(id), temporary_pkl_path)
with open(temporary_pkl_path, 'rb') as file:
@ -84,7 +91,9 @@ def check_id(id):
return known
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
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
encoded_data = bytes(encoded_data, encoding='utf-8')
nparr = np.fromstring(base64.urlsafe_b64decode(encoded_data), np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_ANYCOLOR)
@ -92,18 +101,18 @@ def save_img(encoded_data, filename):
return cv2.imwrite(filename, img)
def encode_face(path):
#create face encoding from data, and check wether it was succesfull. If it was unsuccesfull the encodings list is empty
success = None
face = face_recognition.load_image_file(path)
face_encoding = face_recognition.face_encodings(face)
if len(face_encoding)==0:
success = False
response = {'success':success, 'encoding':None}
response = {'success':False, 'encoding':None}
else:
success = True
response = {'success':success, 'encoding':face_encoding[0]}
response = {'success':True, 'encoding':face_encoding[0]}
return response
def setup():
#create minio buckets that are used at startup if they dont exist already
try:
minioClient.make_bucket("users")
except BucketAlreadyOwnedByYou as err:
@ -113,7 +122,8 @@ def setup():
except ResponseError as err:
raise
#check if the script is run primarily and not imported etc.
if __name__ == '__main__':
setup()
#start running the api
app.run(host='0.0.0.0')

View File

@ -1,5 +1,6 @@
version: "2"
#customized for the environment. Requires traefik reverse proxy
networks:
face-recognition:
external: false
@ -20,7 +21,7 @@ services:
environment:
- s3-adress=minio
- s3-name=face-minio
- s3-password = testpw1
- s3-password=testpw123
restart: unless-stopped
networks:
- face-recognition
@ -30,7 +31,7 @@ services:
labels:
- traefik.enable=true
- traefik.frontend.rule=Host:face.sguba.de
- traefik.port=5555
- traefik.port=5000
- traefik.docker.network=proxy
depends_on:
- minio
@ -40,19 +41,19 @@ services:
restart: unless-stopped
container_name: minio
ports:
- "9999:9000"
- "9009:9000"
environment:
- MINIO_ACCESS_KEY=face-minio
- MINIO_ACCESS_KEY=testpw1
- MINIO_SECRET_KEY=testpw123
networks:
- face-recognition
- proxy
labels:
- traefik.enable=true
- treafik.frontend.rule=face-minio.sguba.de
- traefik.port=9999
- traeffik.docker.network=proxy
- traefik.frontend.rule=Host:face-minio.sguba.de
- traefik.port=9000
- traefik.docker.network=proxy
volumes:
- face_minio_data:/data
- face_minio_config:/root/.minio
command: server /mlflow-minio/storage
command: minio server /data