From da70497f3514b03c16b986ef157addea280077aa Mon Sep 17 00:00:00 2001 From: kinaryml Date: Wed, 22 Mar 2023 21:15:04 -0700 Subject: [PATCH] Updated Face Stylizer implementation and tests --- .../python/test/vision/face_stylizer_test.py | 8 +++----- mediapipe/tasks/python/vision/BUILD | 2 +- mediapipe/tasks/python/vision/face_stylizer.py | 8 +++++--- mediapipe/tasks/testdata/vision/BUILD | 1 + .../vision/face_stylization_dummy.tflite | Bin 0 -> 21430 bytes 5 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 mediapipe/tasks/testdata/vision/face_stylization_dummy.tflite diff --git a/mediapipe/tasks/python/test/vision/face_stylizer_test.py b/mediapipe/tasks/python/test/vision/face_stylizer_test.py index 3c39851dd..32643821f 100644 --- a/mediapipe/tasks/python/test/vision/face_stylizer_test.py +++ b/mediapipe/tasks/python/test/vision/face_stylizer_test.py @@ -36,7 +36,7 @@ _FaceStylizerOptions = face_stylizer.FaceStylizerOptions _RUNNING_MODE = running_mode_module.VisionTaskRunningMode _ImageProcessingOptions = image_processing_options_module.ImageProcessingOptions -_MODEL = 'face_stylizer_model_placeholder.tflite' +_MODEL = 'face_stylization_dummy.tflite' _IMAGE = 'cats_and_dogs.jpg' _STYLIZED_IMAGE = 'stylized_image_placeholder.jpg' _TEST_DATA_DIR = 'mediapipe/tasks/testdata/vision' @@ -104,11 +104,9 @@ class FaceStylizerTest(parameterized.TestCase): stylizer = _FaceStylizer.create_from_options(options) # Performs face stylization on the input. - stylized_image = stylizer.detect(self.test_image) + stylized_image = stylizer.stylize(self.test_image) # Comparing results. - self.assertTrue( - np.array_equal(stylized_image.numpy_view(), - self.test_image.numpy_view())) + # TODO: # Closes the stylizer explicitly when the stylizer is not used in # a context. stylizer.close() diff --git a/mediapipe/tasks/python/vision/BUILD b/mediapipe/tasks/python/vision/BUILD index e21171fc2..f89ef04da 100644 --- a/mediapipe/tasks/python/vision/BUILD +++ b/mediapipe/tasks/python/vision/BUILD @@ -162,7 +162,7 @@ py_library( "//mediapipe/python:_framework_bindings", "//mediapipe/python:packet_creator", "//mediapipe/python:packet_getter", - "//mediapipe/tasks/cc/vision/image_segmenter/proto:face_stylizer_graph_options_py_pb2", + "//mediapipe/tasks/cc/vision/face_stylizer/proto:face_stylizer_graph_options_py_pb2", "//mediapipe/tasks/python/core:base_options", "//mediapipe/tasks/python/core:optional_dependencies", "//mediapipe/tasks/python/core:task_info", diff --git a/mediapipe/tasks/python/vision/face_stylizer.py b/mediapipe/tasks/python/vision/face_stylizer.py index cd840fe85..1393982da 100644 --- a/mediapipe/tasks/python/vision/face_stylizer.py +++ b/mediapipe/tasks/python/vision/face_stylizer.py @@ -124,8 +124,10 @@ class FaceStylizer(base_vision_task_api.BaseVisionTaskApi): return image = packet_getter.get_image(output_packets[_IMAGE_OUT_STREAM_NAME]) stylized_image_packet = output_packets[_STYLIZED_IMAGE_NAME] + stylized_image = packet_getter.get_image(stylized_image_packet) + options.result_callback( - stylized_image_packet, image, + stylized_image, image, stylized_image_packet.timestamp.value // _MICRO_SECONDS_PER_MILLISECOND) task_info = _TaskInfo( @@ -173,7 +175,7 @@ class FaceStylizer(base_vision_task_api.BaseVisionTaskApi): _NORM_RECT_STREAM_NAME: packet_creator.create_proto(normalized_rect.to_pb2()) }) - return output_packets[_STYLIZED_IMAGE_NAME] + return packet_getter.get_image(output_packets[_STYLIZED_IMAGE_NAME]) def stylize_for_video( self, @@ -209,7 +211,7 @@ class FaceStylizer(base_vision_task_api.BaseVisionTaskApi): packet_creator.create_proto(normalized_rect.to_pb2()).at( timestamp_ms * _MICRO_SECONDS_PER_MILLISECOND) }) - return output_packets[_STYLIZED_IMAGE_NAME] + return packet_getter.get_image(output_packets[_STYLIZED_IMAGE_NAME]) def stylize_async( self, diff --git a/mediapipe/tasks/testdata/vision/BUILD b/mediapipe/tasks/testdata/vision/BUILD index 097acad43..f77e1780c 100644 --- a/mediapipe/tasks/testdata/vision/BUILD +++ b/mediapipe/tasks/testdata/vision/BUILD @@ -170,6 +170,7 @@ filegroup( "face_detection_short_range.tflite", "face_landmark.tflite", "face_landmark_with_attention.tflite", + "face_stylization_dummy.tflite", "face_landmarker.task", "hair_segmentation.tflite", "hand_landmark_full.tflite", diff --git a/mediapipe/tasks/testdata/vision/face_stylization_dummy.tflite b/mediapipe/tasks/testdata/vision/face_stylization_dummy.tflite new file mode 100644 index 0000000000000000000000000000000000000000..2523a3a5d16fe29058a1beae2433d3a2e3fa4ac6 GIT binary patch literal 21430 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 X=g0Pt>F+X6o`?2-QUPOc%E