diff --git a/.gitignore b/.gitignore index 0943baf896a6e46bc105cf63b3576035655bde20..e3b10f49282a6a4f99ff68439b95cff6bf9cf2c7 100644 --- a/.gitignore +++ b/.gitignore @@ -103,4 +103,5 @@ ENV/ # Custom .idea/ logs/ -*.sqlite \ No newline at end of file +*.sqlite +20170512-110547/ \ No newline at end of file diff --git a/app/utils/face_net.py b/app/utils/face_net.py index 15504190e903c0b055fd07bd3c7eac8ed5affa37..769678341aa3e440b6397a72e9394ec304326cf0 100644 --- a/app/utils/face_net.py +++ b/app/utils/face_net.py @@ -1,13 +1,32 @@ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import tensorflow.compat.v1 as tf + + class FaceNet: __shared_state = {} - def __init__(self): + def __init__(self, model_path): self.__dict__ = self.__shared_state self.state = 'Init' + with tf.gfile.FastGFile(model_path, "rb") as f: + graph_def = tf.GraphDef() + graph_def.ParseFromString(f.read()) + tf.import_graph_def(graph_def) + graph = tf.get_default_graph() + self.phase_train_placeholder = graph.get_tensor_by_name("import/phase_train:0") + self.images_placeholder = graph.get_tensor_by_name("import/input:0") + self.embeddings = graph.get_tensor_by_name("import/embeddings:0") + init = tf.global_variables_initializer() + self.sess = tf.Session() + self.sess.run(init) def __str__(self): return self.state - @staticmethod - def get_embedding(input_image): - return [0.1] * 128 + def get_embeddings(self, input_images): + feed_dict = {self.images_placeholder: input_images, self.phase_train_placeholder: False} + embeddings = self.sess.run(self.embeddings, feed_dict=feed_dict) + return embeddings diff --git a/app/utils/image_utils.py b/app/utils/image_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..35675aa79a608810d7cab93b8fa142e3390bdcdd --- /dev/null +++ b/app/utils/image_utils.py @@ -0,0 +1,18 @@ +import cv2 + +FACE_NET_INPUT_SIZE = 160 + + +def resize_to_160x160(image: str): + img = cv2.imread(image) + height, width = img.shape[:2] + res = img + if height < FACE_NET_INPUT_SIZE or width < FACE_NET_INPUT_SIZE: + diff = FACE_NET_INPUT_SIZE - min(height, width) + res = cv2.resize(img, (width + diff, height + diff), interpolation=cv2.INTER_CUBIC) + height, width = res.shape[:2] + x_center, y_center = height // 2, width // 2 + x1, y1, x2, y2 = x_center - 80, y_center - 80, x_center + 80, y_center + 80 + assert x2 - x1 == 160 and y2 - y1 == 160 + res = res[x1:x2, y1:y2] + return res diff --git a/main.py b/main.py index 5c6c4cf0696280c0136e9547a42aeb6a2eb8ff4a..846a6f5a3986ef858aaad73276c735b84b534298 100644 --- a/main.py +++ b/main.py @@ -3,4 +3,4 @@ from app import create_app app = create_app('development') if __name__ == '__main__': - app.run() + app.run(host='0.0.0.0', port=5000) diff --git a/requirements.txt b/requirements.txt index 9bef9102ac280270369e50b027ab458e3a5bf320..02d0396275e998fef8256cbf046b1fa253bd0e84 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ cryptography==2.8 python-dotenv==0.10.3 tensorflow-gpu==1.15 pymysql==0.9.3 +numpy==1.18.1 \ No newline at end of file diff --git a/tests/test_env.py b/tests/test_env.py new file mode 100644 index 0000000000000000000000000000000000000000..0c44daa64013e7a0c8c04d0d17a87b19b0c84d52 --- /dev/null +++ b/tests/test_env.py @@ -0,0 +1,15 @@ +import unittest + +import tensorflow.compat.v1 as tf + + +class FileUtilsTestCase(unittest.TestCase): + + def test_env(self): + gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.5) + with tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) as sess: + a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a') + b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b') + c = tf.matmul(a, b) + print(type(sess.run(c))) + self.assertEqual([[22., 28.], [49., 64.]], sess.run(c).tolist()) diff --git a/tests/test_face_net.py b/tests/test_face_net.py new file mode 100644 index 0000000000000000000000000000000000000000..d4e30eaecc11b6b8f510175ac72d5a5ba5d70d39 --- /dev/null +++ b/tests/test_face_net.py @@ -0,0 +1,16 @@ +import unittest + +import numpy as np + +from app.utils.face_net import FaceNet +from app.utils.image_utils import resize_to_160x160 + + +class FaceNetTestCase(unittest.TestCase): + + def test_get_embeddings(self): + image = 'D:\\face-recognition-data\\gAAAAABeOo7SDndQDYi4Cu5udFDYzF0egola_UIyBXfwZGAJEH3W7yPDvCBiiX2pz6Jwwkj-Io5OcXrfMw2ZnKrbMZDnup_sPky8vfxLLH0ZvewU17gP7FU=.webp' + res = resize_to_160x160(image) + model_path = "D:\\workspace-pycharm\\face-recognition-server\\20170512-110547\\20170512-110547.pb" + face_net = FaceNet(model_path) + self.assertEqual(128, len(face_net.get_embeddings(np.array([res]))[0])) diff --git a/tests/test_image_utils.py b/tests/test_image_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..121fd5f2b40a62e6c2694d80e31b0e49d90d6b5b --- /dev/null +++ b/tests/test_image_utils.py @@ -0,0 +1,16 @@ +import unittest + +import cv2 + +from app.utils.image_utils import resize_to_160x160 + + +class ImageUtilTestCase(unittest.TestCase): + + def test_resize_to_160x160(self): + image = 'D:\\face-recognition-data\\gAAAAABeOo7SDndQDYi4Cu5udFDYzF0egola_UIyBXfwZGAJEH3W7yPDvCBiiX2pz6Jwwkj-Io5OcXrfMw2ZnKrbMZDnup_sPky8vfxLLH0ZvewU17gP7FU=.webp' + res = resize_to_160x160(image) + image_split = image.split('.') + image_name = image_split[0] + '_160.' + image_split[1] + cv2.imwrite(image_name, res) + self.assertEqual((160, 160), res.shape[:2])