-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.py
129 lines (89 loc) · 3.55 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import base64
from werkzeug.datastructures import FileStorage
from face import align_face, swap_faces
from models import get_classifier
from utils import setup_logger, allowed_file, download_face_files, file2image, image2b64, download_models
from models.utils import MODEL_REGISTER
import sys
import os
import io
import json
from flask import Flask, jsonify, request, Response, make_response, send_file
from flask_cors import CORS, cross_origin
from PIL import Image, ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
logger = setup_logger(__name__)
logger.info('Finished Importing')
logger.info('Downloading Necessary Files')
download_face_files()
# attach our logger to the system exceptions
sys.excepthook = lambda type, val, tb: logger.error("Unhandled exception:", exc_info=val)
app = Flask(__name__)
cors = CORS(app=app)
app.config['CORS_HEADERS'] = 'Content-Type'
if 'PRODUCTION' in os.environ:
# download all the models
logger.info('Downloading Models')
download_models()
else:
logger.info('Models should be in models folder in local run')
app.config['DEBUG'] = True
@app.route("/")
@cross_origin()
def hello_thetensorclan():
return jsonify({'message': 'You\'ve reached the TensorClan EndPoint'}), 200
@app.route("/classify/<model_handle>", methods=['POST'])
@cross_origin()
def classify_image_api(model_handle='resnet34-imagenet'):
if model_handle not in MODEL_REGISTER:
return Response({'error': f'{model_handle} not found in registered models'}, status=404)
if 'file' not in request.files:
return Response({'error': 'No file part'}, status=412)
file: FileStorage = request.files['file']
if file.filename == '':
return Response({'error': 'No file selected'}, status=417)
if allowed_file(file.filename):
image = file2image(file)
classifier = get_classifier(model_handle)
output = classifier(image)
return Response(json.dumps(output), status=200)
else:
return Response({'error': f'{file.mimetype} not allowed'}, status=412)
@app.route("/face-align", methods=["POST"])
@cross_origin()
def face_align_api():
if 'file' not in request.files:
return Response({'error': 'No file part'}, status=412)
file: FileStorage = request.files['file']
if file.filename == '':
return Response({'error': 'No file selected'}, status=417)
if allowed_file(file.filename):
image = file2image(file)
logger.info(f'Running Align Face on {file.filename}')
# align the face
aligned_face = align_face(image)
# convert it to bytes
b64_image = image2b64(aligned_face)
return jsonify(b64_image), 200
else:
return Response({'error': f'{file.mimetype} not allowed'}, status=412)
@app.route("/face-swap", methods=["POST"])
@cross_origin()
def face_swap_api():
if 'files' not in request.files:
return Response({'error': 'No files selected'}, status=412)
files = request.files.getlist('files')
if len(files) != 2:
return Response({'error': 'Select Two Faces (Images)'}, status=412)
face_one = files[0]
face_two = files[1]
if allowed_file(face_one.filename) and allowed_file(face_two.filename):
f1_image = file2image(face_one)
f2_image = file2image(face_two)
logger.info(f'Running FaceSwap')
swapped_face = swap_faces(f1_image, f2_image)
# convert it to bytes
b64_image = image2b64(swapped_face)
return jsonify(b64_image), 200
else:
return Response({'error': f'{face_one.mimetype} not allowed'}, status=412)