276 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			276 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Copyright 2020 The MediaPipe Authors.
 | |
| #
 | |
| # Licensed under the Apache License, Version 2.0 (the "License");
 | |
| # you may not use this file except in compliance with the License.
 | |
| # You may obtain a copy of the License at
 | |
| #
 | |
| #      http://www.apache.org/licenses/LICENSE-2.0
 | |
| #
 | |
| # Unless required by applicable law or agreed to in writing, software
 | |
| # distributed under the License is distributed on an "AS IS" BASIS,
 | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| # See the License for the specific language governing permissions and
 | |
| # limitations under the License.
 | |
| 
 | |
| """The public facing packet creator APIs."""
 | |
| 
 | |
| from typing import List, Union
 | |
| import warnings
 | |
| 
 | |
| import numpy as np
 | |
| 
 | |
| from google.protobuf import message
 | |
| from mediapipe.python._framework_bindings import _packet_creator
 | |
| from mediapipe.python._framework_bindings import image
 | |
| from mediapipe.python._framework_bindings import image_frame
 | |
| from mediapipe.python._framework_bindings import packet
 | |
| 
 | |
| 
 | |
| create_string = _packet_creator.create_string
 | |
| create_bool = _packet_creator.create_bool
 | |
| create_int = _packet_creator.create_int
 | |
| create_int8 = _packet_creator.create_int8
 | |
| create_int16 = _packet_creator.create_int16
 | |
| create_int32 = _packet_creator.create_int32
 | |
| create_int64 = _packet_creator.create_int64
 | |
| create_uint8 = _packet_creator.create_uint8
 | |
| create_uint16 = _packet_creator.create_uint16
 | |
| create_uint32 = _packet_creator.create_uint32
 | |
| create_uint64 = _packet_creator.create_uint64
 | |
| create_float = _packet_creator.create_float
 | |
| create_double = _packet_creator.create_double
 | |
| create_int_array = _packet_creator.create_int_array
 | |
| create_float_array = _packet_creator.create_float_array
 | |
| create_int_vector = _packet_creator.create_int_vector
 | |
| create_bool_vector = _packet_creator.create_bool_vector
 | |
| create_float_vector = _packet_creator.create_float_vector
 | |
| create_string_vector = _packet_creator.create_string_vector
 | |
| create_image_vector = _packet_creator.create_image_vector
 | |
| create_packet_vector = _packet_creator.create_packet_vector
 | |
| create_string_to_packet_map = _packet_creator.create_string_to_packet_map
 | |
| create_matrix = _packet_creator.create_matrix
 | |
| 
 | |
| 
 | |
| def create_image_frame(data: Union[image_frame.ImageFrame, np.ndarray],
 | |
|                        *,
 | |
|                        image_format: image_frame.ImageFormat = None,
 | |
|                        copy: bool = None) -> packet.Packet:
 | |
|   """Create a MediaPipe ImageFrame packet.
 | |
| 
 | |
|   A MediaPipe ImageFrame packet can be created from an existing MediaPipe
 | |
|   ImageFrame object and the data will be realigned and copied into a new
 | |
|   ImageFrame object inside of the packet.
 | |
| 
 | |
|   A MediaPipe ImageFrame packet can also be created from the raw pixel data
 | |
|   represented as a numpy array with one of the uint8, uint16, and float data
 | |
|   types. There are three data ownership modes depending on how the 'copy' arg
 | |
|   is set.
 | |
| 
 | |
|   i) Default mode
 | |
|   If copy is not set, mutable data is always copied while the immutable data
 | |
|   is by reference.
 | |
| 
 | |
|   ii) Copy mode (safe)
 | |
|   If copy is set to True, the data will be realigned and copied into an
 | |
|   ImageFrame object inside of the packet regardless the immutablity of the
 | |
|   original data.
 | |
| 
 | |
|   iii) Reference mode (dangerous)
 | |
|   If copy is set to False, the data will be forced to be shared. If the data is
 | |
|   mutable (data.flags.writeable is True), a warning will be raised.
 | |
| 
 | |
|   Args:
 | |
|     data: A MediaPipe ImageFrame object or the raw pixel data that is
 | |
|       represnted as a numpy ndarray.
 | |
|     image_format: One of the image_frame.ImageFormat enum types.
 | |
|     copy: Indicate if the packet should copy the data from the numpy nparray.
 | |
| 
 | |
|   Returns:
 | |
|     A MediaPipe ImageFrame Packet.
 | |
| 
 | |
|   Raises:
 | |
|     ValueError:
 | |
|       i) When "data" is a numpy ndarray, "image_format" is not provided or
 | |
|         the "data" array is not c_contiguous in the reference mode.
 | |
|       ii) When "data" is an ImageFrame object, the "image_format" arg doesn't
 | |
|         match the image format of the "data" ImageFrame object or "copy" is
 | |
|         explicitly set to False.
 | |
|     TypeError: If "image format" doesn't match "data" array's data type.
 | |
| 
 | |
|   Examples:
 | |
|     np_array = np.random.randint(255, size=(321, 123, 3), dtype=np.uint8)
 | |
|     # Copy mode by default if the data array is writable.
 | |
|     image_frame_packet = mp.packet_creator.create_image_frame(
 | |
|         image_format=mp.ImageFormat.SRGB, data=np_array)
 | |
| 
 | |
|     # Make the array unwriteable to trigger the reference mode.
 | |
|     np_array.flags.writeable = False
 | |
|     image_frame_packet = mp.packet_creator.create_image_frame(
 | |
|         image_format=mp.ImageFormat.SRGB, data=np_array)
 | |
| 
 | |
|     image_frame = mp.ImageFrame(image_format=mp.ImageFormat.SRGB, data=np_array)
 | |
|     image_frame_packet = mp.packet_creator.create_image_frame(image_frame)
 | |
| 
 | |
|   """
 | |
|   if isinstance(data, image_frame.ImageFrame):
 | |
|     if image_format is not None and data.image_format != image_format:
 | |
|       raise ValueError(
 | |
|           'The provided image_format doesn\'t match the one from the data arg.')
 | |
|     if copy is not None and not copy:
 | |
|       # Taking a reference will make the created packet be mutable since the
 | |
|       # ImageFrame object can still be manipulated in Python, which voids packet
 | |
|       # immutability.
 | |
|       raise ValueError(
 | |
|           'Creating ImageFrame packet by taking a reference of another ImageFrame object is not supported yet.'
 | |
|       )
 | |
|     # pylint:disable=protected-access
 | |
|     return _packet_creator._create_image_frame_from_image_frame(data)
 | |
|     # pylint:enable=protected-access
 | |
|   else:
 | |
|     if image_format is None:
 | |
|       raise ValueError('Please provide \'image_format\' with \'data\'.')
 | |
|     # If copy arg is not set, copying the data if it's immutable. Otherwise,
 | |
|     # take a reference of the immutable data to avoid data copy.
 | |
|     if copy is None:
 | |
|       copy = True if data.flags.writeable else False
 | |
|     if not copy:
 | |
|       # TODO: Investigate why the first 2 bytes of the data has data
 | |
|       # corruption when "data" is not c_contiguous.
 | |
|       if not data.flags.c_contiguous:
 | |
|         raise ValueError(
 | |
|             'Reference mode is unavailable if \'data\' is not c_contiguous.')
 | |
|       if data.flags.writeable:
 | |
|         warnings.warn(
 | |
|             '\'data\' is still writeable. Taking a reference of the data to create ImageFrame packet is dangerous.',
 | |
|             RuntimeWarning, 2)
 | |
|     # pylint:disable=protected-access
 | |
|     return _packet_creator._create_image_frame_from_pixel_data(
 | |
|         image_format, data, copy)
 | |
|     # pylint:enable=protected-access
 | |
| 
 | |
| 
 | |
| def create_image(data: Union[image.Image, np.ndarray],
 | |
|                  *,
 | |
|                  image_format: image_frame.ImageFormat = None,
 | |
|                  copy: bool = None) -> packet.Packet:
 | |
|   """Create a MediaPipe Image packet.
 | |
| 
 | |
|   A MediaPipe Image packet can be created from an existing MediaPipe
 | |
|   Image object and the data will be realigned and copied into a new
 | |
|   Image object inside of the packet.
 | |
| 
 | |
|   A MediaPipe Image packet can also be created from the raw pixel data
 | |
|   represented as a numpy array with one of the uint8, uint16, and float data
 | |
|   types. There are three data ownership modes depending on how the 'copy' arg
 | |
|   is set.
 | |
| 
 | |
|   i) Default mode
 | |
|   If copy is not set, mutable data is always copied while the immutable data
 | |
|   is by reference.
 | |
| 
 | |
|   ii) Copy mode (safe)
 | |
|   If copy is set to True, the data will be realigned and copied into an
 | |
|   Image object inside of the packet regardless the immutablity of the
 | |
|   original data.
 | |
| 
 | |
|   iii) Reference mode (dangerous)
 | |
|   If copy is set to False, the data will be forced to be shared. If the data is
 | |
|   mutable (data.flags.writeable is True), a warning will be raised.
 | |
| 
 | |
|   Args:
 | |
|     data: A MediaPipe Image object or the raw pixel data that is represnted as a
 | |
|       numpy ndarray.
 | |
|     image_format: One of the mp.ImageFormat enum types.
 | |
|     copy: Indicate if the packet should copy the data from the numpy nparray.
 | |
| 
 | |
|   Returns:
 | |
|     A MediaPipe Image Packet.
 | |
| 
 | |
|   Raises:
 | |
|     ValueError:
 | |
|       i) When "data" is a numpy ndarray, "image_format" is not provided or
 | |
|         the "data" array is not c_contiguous in the reference mode.
 | |
|       ii) When "data" is an Image object, the "image_format" arg doesn't
 | |
|         match the image format of the "data" Image object or "copy" is
 | |
|         explicitly set to False.
 | |
|     TypeError: If "image format" doesn't match "data" array's data type.
 | |
| 
 | |
|   Examples:
 | |
|     np_array = np.random.randint(255, size=(321, 123, 3), dtype=np.uint8)
 | |
|     # Copy mode by default if the data array is writable.
 | |
|     image_packet = mp.packet_creator.create_image(
 | |
|         image_format=mp.ImageFormat.SRGB, data=np_array)
 | |
| 
 | |
|     # Make the array unwriteable to trigger the reference mode.
 | |
|     np_array.flags.writeable = False
 | |
|     image_packet = mp.packet_creator.create_image(
 | |
|         image_format=mp.ImageFormat.SRGB, data=np_array)
 | |
| 
 | |
|     image = mp.Image(image_format=mp.ImageFormat.SRGB, data=np_array)
 | |
|     image_packet = mp.packet_creator.create_image(image)
 | |
| 
 | |
|   """
 | |
|   if isinstance(data, image.Image):
 | |
|     if image_format is not None and data.image_format != image_format:
 | |
|       raise ValueError(
 | |
|           'The provided image_format doesn\'t match the one from the data arg.')
 | |
|     if copy is not None and not copy:
 | |
|       # Taking a reference will make the created packet be mutable since the
 | |
|       # Image object can still be manipulated in Python, which voids packet
 | |
|       # immutability.
 | |
|       raise ValueError(
 | |
|           'Creating Image packet by taking a reference of another Image object is not supported yet.'
 | |
|       )
 | |
|     # pylint:disable=protected-access
 | |
|     return _packet_creator._create_image_from_image(data)
 | |
|     # pylint:enable=protected-access
 | |
|   else:
 | |
|     if image_format is None:
 | |
|       raise ValueError('Please provide \'image_format\' with \'data\'.')
 | |
|     # If copy arg is not set, copying the data if it's immutable. Otherwise,
 | |
|     # take a reference of the immutable data to avoid data copy.
 | |
|     if copy is None:
 | |
|       copy = True if data.flags.writeable else False
 | |
|     if not copy:
 | |
|       # TODO: Investigate why the first 2 bytes of the data has data
 | |
|       # corruption when "data" is not c_contiguous.
 | |
|       if not data.flags.c_contiguous:
 | |
|         raise ValueError(
 | |
|             'Reference mode is unavailable if \'data\' is not c_contiguous.')
 | |
|       if data.flags.writeable:
 | |
|         warnings.warn(
 | |
|             '\'data\' is still writeable. Taking a reference of the data to create Image packet is dangerous.',
 | |
|             RuntimeWarning, 2)
 | |
|     # pylint:disable=protected-access
 | |
|     return _packet_creator._create_image_from_pixel_data(
 | |
|         image_format, data, copy)
 | |
|     # pylint:enable=protected-access
 | |
| 
 | |
| 
 | |
| def create_proto(proto_message: message.Message) -> packet.Packet:
 | |
|   """Create a MediaPipe protobuf message packet.
 | |
| 
 | |
|   Args:
 | |
|     proto_message: A Python protobuf message.
 | |
| 
 | |
|   Returns:
 | |
|     A MediaPipe protobuf message Packet.
 | |
| 
 | |
|   Raises:
 | |
|     RuntimeError: If the protobuf message type is not registered in MediaPipe.
 | |
| 
 | |
|   Examples:
 | |
|     detection = detection_pb2.Detection()
 | |
|     text_format.Parse('score: 0.5', detection)
 | |
|     packet = mp.packet_creator.create_proto(detection)
 | |
|     output_detection = mp.packet_getter.get_proto(packet)
 | |
|   """
 | |
|   # pylint:disable=protected-access
 | |
|   return _packet_creator._create_proto(proto_message.DESCRIPTOR.full_name,
 | |
|                                        proto_message.SerializeToString())
 | |
|   # pylint:enable=protected-access
 | |
| 
 | |
| 
 | |
| def create_proto_vector(message_list: List[message.Message]) -> packet.Packet:
 | |
|   raise NotImplementedError('create_proto_vector is not implemented.')
 |