o
    ?e|4                     @   s   d Z ddlZddlZddlZddlZddlZddlZddlmZ	 ddlm
Z
 ddlmZ dZdd Zd	d
 Zdd Zd(ddZdd Zdd Zdd Zd)ddZdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' ZdS )*zUtility functions for FlatBuffers.

All functions that are commonly used to work with FlatBuffers.

Refer to the tensorflow lite flatbuffer schema here:
tensorflow/lite/schema/schema.fbs
    N)schema_py_generated)schema_util)gfiles   TFL3c                 C   s   t j| d}t j|S )zBConverts a tflite model from a bytearray to an object for parsing.r   )	schema_fbZModelZGetRootAsModelModelTZInitFromObj)model_bytearraymodel_object r	   g/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorflow/lite/tools/flatbuffer_utils.pyconvert_bytearray_to_object&   s   r   c                 C   sp   t | std|  t | d}t| }W d   n1 s"w   Y  t|}tjdkr6t	|dd |S )a2  Reads a tflite model as a python object.

  Args:
    input_tflite_file: Full path name to the input tflite file

  Raises:
    RuntimeError: If input_tflite_file path is invalid.
    IOError: If input_tflite_file cannot be opened.

  Returns:
    A python object corresponding to the input tflite file.
  zInput file not found at %r
rbNbiglittle)
r   ZExistsRuntimeErrorGFile	bytearrayreadr   sys	byteorderbyte_swap_tflite_model_obj)input_tflite_fileZinput_file_handler   modelr	   r	   r
   
read_model,   s   

r   c                 C   s   t t| S )aC  Reads a tflite model as a python object with mutable tensors.

  Similar to read_model() with the addition that the returned object has
  mutable tensors (read_model() returns an object with immutable tensors).

  NOTE: This API only works for TFLite generated with
  _experimental_use_buffer_offset=false

  Args:
    input_tflite_file: Full path name to the input tflite file

  Raises:
    RuntimeError: If input_tflite_file path is invalid.
    IOError: If input_tflite_file cannot be opened.

  Returns:
    A mutable python object corresponding to the input tflite file.
  )copydeepcopyr   )r   r	   r	   r
   read_model_with_mutable_tensorsC   s   r       c                 C   s:   t d}| |}|j|td t| }|| }|S )z@Converts a tflite model from an object to a immutable bytearray.i   )Zfile_identifier)flatbuffersZBuilderZPackZFinish_TFLITE_FILE_IDENTIFIERbytesOutput)r   Zextra_bufferZbuilderZmodel_offsetr   r	   r	   r
   convert_object_to_bytearrayY   s   

r!   c                 C   sd   t jdkrt| } t| dd t| }t|d}|| W d   dS 1 s+w   Y  dS )as  Writes the tflite model, a python object, into the output file.

  NOTE: This API only works for TFLite generated with
  _experimental_use_buffer_offset=false

  Args:
    model_object: A tflite model as a python object
    output_tflite_file: Full path name to the output tflite file.

  Raises:
    IOError: If output_tflite_file path is invalid or cannot be opened.
  r   r   wbN)	r   r   r   r   r   r!   r   r   write)r   Zoutput_tflite_filer   Zoutput_file_handler	   r	   r
   write_modeld   s   

"r$   c                 C   s4   d| _ | jD ]}d|_|jD ]}d|_qqd| _dS )ay  Strips all nonessential strings from the model to reduce model size.

  We remove the following strings:
  (find strings by searching ":string" in the tensorflow lite flatbuffer schema)
  1. Model description
  2. SubGraph name
  3. Tensor names
  We retain OperatorCode custom_code and Metadata name.

  Args:
    model: The model from which to remove nonessential strings.
  N)description	subgraphsnametensorsZsignatureDefs)r   subgraphtensorr	   r	   r
   strip_stringsy   s   


r+   c                 C   s*   t jj D ]\}}|| kr|  S qdS )z4Converts a numerical enum to a readable tensor type.N)r   
TensorType__dict__items)Ztensor_typer'   valuer	   r	   r
   type_to_name   s
   r0   c                    s6  t | | j}tdt|} dur fdd|D }i }| jD ]"}|jD ]}|jdu r/ qC|jD ]}|j| }	t	|	j
||	j< q2q&q!|D ]R}
||
 j}|du rSdn|j}|dkr[qF||
d}|dr|dkrld	nd
}td|t|D ]}t dd}t|||| qwqFt|D ]
}t dd||< qqFdS )a  Randomize weights in a model.

  Args:
    model: The model in which to randomize weights.
    random_seed: The input to the random number generator (default value is 0).
    buffers_to_skip: The list of buffer indices to skip. The weights in these
      buffers are left unmodified.
     Nc                    s   g | ]}| vr|qS r	   r	   ).0idxbuffers_to_skipr	   r
   
<listcomp>       z%randomize_weights.<locals>.<listcomp>r   ZINT8FLOATFLOAT16efg      g      ?   )randomseedbuffersrangelenr&   	operatorsZinputsr(   r0   typebufferdatasizeget
startswithstructcalcsizeuniform	pack_intorandint)r   Zrandom_seedr5   r?   Z
buffer_idsZbuffer_typesgraphopZ	input_idxr*   iZbuffer_i_dataZbuffer_i_sizeZbuffer_typeZformat_codeoffsetr/   jr	   r4   r
   randomize_weights   s>   







rS   c                 C   s:   | j D ]}|jr|jd}||v r|| d|_qdS )zRename custom ops so they use the same naming style as builtin ops.

  Args:
    model: The input tflite model.
    map_custom_op_renames: A mapping from old to new custom op names.
  asciiN)operatorCodesZ
customCodedecodeencode)r   Zmap_custom_op_renamesop_codeZop_code_strr	   r	   r
   rename_custom_ops   s   
rY   c                 C   sD   | j | }t|j|j}ttj D ]\}}||kr|  S qdS )zConverts a TFLite op_code to the human readable name.

  Args:
    model: The input tflite model.
    op_code: The op_code to resolve to a readable name.

  Returns:
    A string containing the human readable op name, or None if not resolvable.
  N)rU   maxZbuiltinCodeZdeprecatedBuiltinCodevarsr   BuiltinOperatorr.   )r   rX   rO   coder'   r/   r	   r	   r
   opcode_to_name   s   

r^   c           	      C   s   t d}t }t| 3}|D ]%}||}|du rq|d}td|d}dd |D }|| qW d   t	|S 1 sBw   Y  t	|S )a@  Converts xxd output C++ source file to bytes (immutable).

  Args:
    input_cc_file: Full path name to th C++ source file dumped by xxd

  Raises:
    RuntimeError: If input_cc_file path is invalid.
    IOError: If input_cc_file cannot be opened.

  Returns:
    A bytearray corresponding to the input cc file array.
  z\W*(0x[0-9a-fA-F,x ]+).*Nr1   ,c                 S   s   g | ]}t |d dqS )   )base)int)r2   xr	   r	   r
   r6     r7   z'xxd_output_to_bytes.<locals>.<listcomp>)
recompiler   openmatchgroupfiltersplitextendr   )	input_cc_filepatternr   Zfile_handlelineZvalues_matchZ	list_textZvalues_textvaluesr	   r	   r
   xxd_output_to_bytes   s    




rp   c                 C   s   t | }t|S )a7  Converts xxd output C++ source file to object.

  Args:
    input_cc_file: Full path name to th C++ source file dumped by xxd

  Raises:
    RuntimeError: If input_cc_file path is invalid.
    IOError: If input_cc_file cannot be opened.

  Returns:
    A python object corresponding to the input tflite file.
  )rp   r   )rl   Zmodel_bytesr	   r	   r
   xxd_output_to_object  s   rq   c                    sD    fddt dt jD }dfdd|D  _dS )z4Helper function for byte-swapping the buffers field.c                    s   g | ]} j ||  qS r	   )rE   )r2   rP   )rD   	chunksizer	   r
   r6   %  s    z,byte_swap_buffer_content.<locals>.<listcomp>r   r   c                    s    g | ]}t | qS r	   )rb   
from_bytesto_bytes)r2   byteswap)rr   from_endinessto_endinessr	   r
   r6   *  s    N)r@   rA   rE   join)rD   rr   rv   rw   Zto_swapr	   )rD   rr   rv   rw   r
   byte_swap_buffer_content#  s   
ry   c           	      C   s$  | du rdS g }t jjt jjt jjg}t jjt jjt jjt jjg}t jj	t jj
t jjt jjg}| jD ]]}|jD ]W}|jdkr|jt| jk r|j|vr| j|j jdur|j|v ret| j|j d|| n#|j|v rvt| j|j d|| n|j|v rt| j|j d|| nq7||j q7q2dS )a  Byte swaps the buffers field in a TFLite model.

  Args:
    model: TFLite model object of from_endiness format.
    from_endiness: The original endianness format of the buffers in model.
    to_endiness: The destined endianness format of the buffers in model.
  Nr            )r   r,   r9   ZINT16ZUINT16ZFLOAT32ZINT32Z	COMPLEX64ZUINT32ZINT64ZFLOAT64Z
COMPLEX128ZUINT64r&   r(   rD   rA   r?   rE   rC   ry   append)	r   rv   rw   Zbuffer_swappedZtypes_of_16_bitsZtypes_of_32_bitsZtypes_of_64_bitsr)   r*   r	   r	   r
   r   3  sX   




r   c                 C   s(   | du rdS t | }t||| t|S )a  Generates a new model byte array after byte swapping its buffers field.

  Args:
    tflite_model: TFLite flatbuffer in a byte array.
    from_endiness: The original endianness format of the buffers in
      tflite_model.
    to_endiness: The destined endianness format of the buffers in tflite_model.

  Returns:
    TFLite flatbuffer in a byte array, after being byte swapped to to_endiness
    format.
  N)r   r   r!   )Ztflite_modelrv   rw   r   r	   r	   r
   byte_swap_tflite_bufferi  s
   r~   c                 C   sr   t | tjs
t| } t }| jD ]$}|jdu rq|jD ]}t| j	|j
 }|tjjkr3||jj qqt|S )zCalculates the number of unique resource variables in a model.

  Args:
    model: the input tflite model, either as bytearray or object.

  Returns:
    An integer number representing the number of unique resource variables.
  N)
isinstancer   r   r   setr&   rB   r   Z#get_builtin_code_from_operator_coderU   ZopcodeIndexr\   Z
VAR_HANDLEaddZbuiltinOptionsZ
sharedNamerA   )r   Zunique_shared_namesr)   rO   Zbuiltin_coder	   r	   r
   count_resource_variables  s   	



r   )r   )r   N)__doc__r   r=   rd   rI   r   r   Ztensorflow.lite.pythonr   r   r   Ztensorflow.python.platformr   r   r   r   r   r!   r$   r+   r0   rS   rY   r^   rp   rq   ry   r   r~   r   r	   r	   r	   r
   <module>   s6   

3'6