Ë
    ëÓ^j 5  ã                  óÌ   — d Z ddlmZ ddlmZ ddlmZ ddlZddl	m
Z ddlmZ ddlmZ  e«       Zddd	„Z	 d	 	 	 	 	 	 	 	 	 dd
„Z	 d	 	 	 	 	 	 	 dd„Z	 	 d	 	 	 	 	 	 	 	 	 	 	 dd„Zy)u-  ONNX Runtime inference helpers for RF-DETR exported models.

These functions handle session creation, image preprocessing, and detection decoding without requiring PyTorch or the
RF-DETR training stack â€” only ``onnxruntime``, ``numpy``, ``supervision``, and ``Pillow`` are needed at inference time.
é    )Úannotations)ÚPath)ÚAnyN)ÚImage)Ú
Detections)Ú
get_loggerc                óš  — 	 ddl }|€Kddg}|j                  «       }|D �cg c]	  }||v sŒ|‘Œ c}xs dg}|d   dk(  rt        j	                  d«       |j                  t        | «      |¬«      }t        j                  d|j                  «       «       |j                  «       D ]8  }t        j                  d	|j                  |j                  |j                  «       Œ: |j                  «       D ]8  }	t        j                  d
|	j                  |	j                  |	j                  «       Œ: |S # t        $ r}t        d«      |‚d}~ww xY wc c}w )u^  Load an ONNX model and create an ONNX Runtime inference session.

    Imports ``onnxruntime`` at call time so that the rest of the package remains usable without it installed.  Input and
    output names / shapes are logged at DEBUG level for troubleshooting.

    When ``providers`` is ``None``, the session auto-selects the best available backend: CUDA if ``onnxruntime-gpu`` is
    installed, otherwise CPU (with a warning).  Pass an explicit list to pin the backend â€” useful for benchmarking
    CPU vs CUDA side-by-side.

    Args:
        model_path: Path to the ``.onnx`` model file.
        providers: Ordered list of ORT execution providers, e.g.
            ``["CUDAExecutionProvider", "CPUExecutionProvider"]``.  When ``None`` (default), the best available
            provider is selected automatically.

    Returns:
        An ``onnxruntime.InferenceSession`` ready for inference.

    Raises:
        ImportError: If ``onnxruntime`` is not installed.

    Examples:
        .. code-block:: python

            sess = _create_onnx_session("model.onnx")
            print(sess.get_inputs()[0].name)
    r   NzTONNX Runtime inference requires 'onnxruntime'. Install it: `pip install onnxruntime`ÚCUDAExecutionProviderÚCPUExecutionProvideru’   CUDAExecutionProvider not available â€” running ONNX inference on CPU. Install onnxruntime-gpu for GPU acceleration: `pip install onnxruntime-gpu`©Ú	providersz!ONNX Runtime providers in use: %sz#Input  : name=%s  shape=%s  type=%sz#Output : name=%s  shape=%s  type=%s)ÚonnxruntimeÚImportErrorÚget_available_providersÚloggerÚwarningÚInferenceSessionÚstrÚdebugÚget_providersÚ
get_inputsÚnameÚshapeÚtypeÚget_outputs)
Ú
model_pathr   ÚortÚexcÚ
_preferredÚ
_availableÚpÚsessionÚinpÚouts
             úh/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/rfdetr/export/_onnx/inference.pyÚ_create_onnx_sessionr&      sB  € ð8Û!ð ÐØ-Ð/EÐFˆ
Ø×0Ñ0Ó2ˆ
Ø *Ö>˜1¨a°:ªo’QÒ>ÒZÐCYÐBZˆ	Ø�Q‰<Ð1Ò1Ü�N‰Nð^ôð ×"Ñ"¤3 z£?¸iÐ"ÓH€GÜ
‡L�LÐ4°g×6KÑ6KÓ6MÔNØ×!Ñ!Ó#ò [ˆÜ�‰Ð:¸C¿H¹HÀcÇiÁiÐQT×QYÑQYÕZð[à×"Ñ"Ó$ò [ˆÜ�‰Ð:¸C¿H¹HÀcÇiÁiÐQT×QYÑQYÕZð[à€Nøô) ò ÜØbó
àð	ûðüò ?s!   ‚D+  	EªEÄ+	EÄ4E Å Ec                óò  — g d¢}g d¢}t        j                  t        |«      D �cg c]
  }||dz     ‘Œ c}t         j                  ¬«      }t        j                  t        |«      D �cg c]
  }||dz     ‘Œ c}t         j                  ¬«      }|dk(  rdnd}	t        j                  | j	                  |	«      j                  ||ft        j                  j                  «      t         j                  ¬«      dz  }
|
j                  d	k(  r|
d
d
…d
d
…t         j                  f   }
|
|z
  |z  }
|
j                  d	dd«      }
t        j                  |
d¬«      j                  t         j                  «      S c c}w c c}w )uš  Resize and normalise a PIL image to an ``(1, C, H, W)`` float32 NCHW tensor.

    Resizes using ``BILINEAR`` to match ``torchvision.transforms.functional.resize()`` (PIL's default is ``BICUBIC``
    which produces slightly different values and can lower confidence scores).  Normalises with ImageNet statistics:
    ``mean=[0.485, 0.456, 0.406]``, ``std=[0.229, 0.224, 0.225]``.

    Args:
        image: Input PIL image; any mode â€” converted to ``"RGB"`` (3-channel) or ``"L"`` (1-channel) internally.
        height: Target spatial height expected by the model.
        width: Target spatial width expected by the model.
        channels: Number of channels the model expects (``1`` for grayscale, ``3`` for RGB).

    Returns:
        Float32 ndarray of shape ``(1, channels, height, width)``.

    Examples:
        .. code-block:: python

            inp = _preprocess_pil_to_nchw(image, height=640, width=640)
    )g
×£p=
ß?gÉv¾Ÿ/Ý?g–C‹lçûÙ?)gZd;ßOÍ?gyé&1¬Ì?gÍÌÌÌÌÌÌ?é   ©Údtypeé   ÚLÚRGBg     ào@é   Nr   ©Úaxis)ÚnpÚarrayÚrangeÚfloat32ÚconvertÚresizeÚPILImageÚ
ResamplingÚBILINEARÚndimÚnewaxisÚ	transposeÚexpand_dimsÚastype)ÚimageÚheightÚwidthÚchannelsÚ_imagenet_meanÚ_imagenet_stdÚiÚmeanÚstdÚpil_modeÚarrs              r%   Ú_preprocess_pil_to_nchwrJ   O   s+  € ò4 +€NÚ)€MÜ�8‰8´E¸(³OÖD¨q�^ A¨¡EÓ*ÒDÌBÏJÉJÔW€DÜ
�(‰(´%¸³/ÖB¨Q�M ! a¡%Ó(ÒBÌ"Ï*É*Ô
U€CØ !’m‰s¨€Hô 	�‰Ø�M‰M˜(Ó#×*Ñ*¨E°6¨?¼H×<OÑ<O×<XÑ<XÓYÜ—*‘*ô	
ð ñ		ð ð ‡x�x�1‚}Ø’!’QœŸ
™
Ð"Ñ#ˆØ�‰:˜Ñ
€CØ
�-‰-˜˜1˜aÓ
 €CÜ�>‰>˜# AÔ&×-Ñ-¬b¯j©jÓ9Ð9ùò EùÚBs   ¥E/Á'E4c           
     óú  — | j                  «       }| j                  «       }|d   j                  }|d   j                  \  }}}}	t	        j
                  |«      }
t        |
||	|«      }| j                  d||i«      }|D �cg c]  }|j                  ‘Œ }}t        d„ t        |«      D «       d«      }t        d„ t        |«      D «       d«      }|�|�€t        j                  d|«       t        |«      D ��cg c]*  \  }}|j                  dk(  sŒ|j                  d   dk(  sŒ)|‘Œ, }}}t        |«      D ��cg c]*  \  }}|j                  dk(  sŒ|j                  d   dk7  sŒ)|‘Œ, }}}t        |«      d	k(  rt        |«      d	k(  r|d   }|d   }nXt        |«      d
k(  rt        j                  d«       d}d	}n0|D �cg c]  }t        |j                  «      ‘Œ }}t        d|› �«      ‚||   d   }||   ddd…dd…f   }t        j!                  d|j                  t#        |j%                  «       «      t#        |j'                  «       «      t#        |j)                  «       «      «       t+        j,                  d	|j.                  ¬«      }||t+        j0                  |j3                  dd«       «      z   z  }|j'                  d¬«      }|j5                  d¬«      }t        j!                  dt#        |j%                  «       «      t#        |j'                  «       «      |t7        ||kD  j9                  «       «      «       ||kD  }||   j:                  \  }}}} |
j<                  \  }!}"t+        j>                  ||d
z  z
  || d
z  z
  ||d
z  z   || d
z  z   gd	¬«      }#|#t+        j@                  |!|"|!|"gt*        jB                  ¬«      z  }#tE        |#||   ||   jG                  t6        «      ¬«      |
fS c c}w c c}}w c c}}w c c}w )u½  Preprocess one image, run ONNX Runtime inference, and decode detections.

    Reads input shape from the session (NCHW ``float32``), resizes and normalises the image with ImageNet statistics,
    invokes the model, then decodes the ``dets`` / ``labels`` output tensors into a :class:`supervision.Detections`
    object with pixel-space ``xyxy`` boxes.

    **Input contract** (must match ``RFDETR.predict()`` preprocessing exactly):

    - Image is opened as-is and converted to ``"RGB"`` (3-channel) or ``"L"``
      (1-channel greyscale) depending on the model's channel count.
    - Resize uses ``PIL.Image.Resampling.BILINEAR`` â€” matching
      ``torchvision.transforms.functional.resize()`` which defaults to ``InterpolationMode.BILINEAR``.  Using PIL's
      default (``BICUBIC``) would produce slightly different pixel values and can degrade confidence.
    - Pixel values are scaled to ``[0, 1]`` then normalised with ImageNet
      statistics: ``mean=[0.485, 0.456, 0.406]``, ``std=[0.229, 0.224, 0.225]``.
    - The tensor is kept as ``[1, C, H, W]`` (NCHW) â€” unlike the TFLite helper
      which uses NHWC because ``onnx2tf`` transposes at export time.  ONNX RT consumes the native ONNX NCHW layout
      directly.

    Args:
        session: ONNX Runtime ``InferenceSession`` returned by
            ``_create_onnx_session``.
        image_path: Path to the input image (any format supported by Pillow).
            RGB images are used as-is; RGBA / palette images are converted.
        threshold: Confidence threshold; detections below this are discarded.

    Returns:
        A tuple of ``(detections, pil_img)`` where ``detections`` contains pixel-space ``xyxy`` boxes and ``pil_img`` is
        the original PIL image at its original resolution.

    Examples:
        .. code-block:: python

            sess = _create_onnx_session("model.onnx")
            dets, img = _run_inference(sess, "photo.jpg", threshold=0.3)
            print(dets.confidence)
    r   Nc              3  ó0   K  — | ]  \  }}d |v sŒ|–— Œ y­w)ÚdetsN© ©Ú.0rE   r   s      r%   ú	<genexpr>z!_run_inference.<locals>.<genexpr>µ   s   è ø€ ÒQ™G˜A˜tÀ&ÈDÂ.”aÑQùó   ‚�c              3  ó0   K  — | ]  \  }}d |v sŒ|–— Œ y­w)ÚlabelsNrN   rO   s      r%   rQ   z!_run_inference.<locals>.<genexpr>¶   s   è ø€ ÒT™W˜Q À8ÈtÒCS”qÑTùrR   zcName-based ONNX output matching failed (available names: %s). Falling back to shape-based matching.r(   éÿÿÿÿé   r+   r.   a2  Shape-based ONNX output matching is ambiguous (both outputs have last dim==4, which happens when num_classes==3).  Falling back to positional order: output 0 = boxes ('dets'), output 1 = logits ('labels').  If detections look wrong, inspect output names with _create_onnx_session() and set LOG_LEVEL=DEBUG.z³Shape-based ONNX output matching failed. Expected exactly one rank-3 tensor with last dim == 4 (boxes) and one rank-3 tensor with last dim != 4 (logits). Available output shapes: z2Logits stats: shape=%s min=%.3f max=%.3f mean=%.3fr)   i¨ÿÿÿéX   r/   uG   Scores stats: min=%.3f max=%.3f â€” detections above threshold %.2f: %d)ÚxyxyÚ
confidenceÚclass_id)$r   r   r   r   r7   ÚopenrJ   ÚrunÚnextÚ	enumerater   r   r:   ÚlenÚlistÚ
ValueErrorr   ÚfloatÚminÚmaxrF   r1   Úasarrayr*   ÚexpÚclipÚargmaxÚintÚsumÚTÚsizeÚstackr2   r4   r   r>   )$r"   Ú
image_pathÚ	thresholdÚinputsÚoutputsÚ
input_nameÚ_rB   r@   rA   Úpil_imgÚ
inp_tensorÚraw_outputsr$   Úoutput_namesÚ	boxes_idxÚ
logits_idxrE   Úarr_outÚshape_boxes_candidatesÚshape_logits_candidatesÚavailable_shapesÚ	boxes_cwhÚlogitsÚoneÚ
scores_allÚscoresÚclsÚkeepÚcxÚcyÚbwÚbhÚowÚohrX   s$                                       r%   Ú_run_inferencer‹   }   sÜ  € ðT ×ÑÓ!€FØ×!Ñ!Ó#€GØ˜‘—‘€Jà!'¨¡§¡Ñ€A€x�˜ä�m‰m˜JÓ'€GÜ(¨°&¸%ÀÓJ€Jà—+‘+˜d Z°Ð$<Ó=€Kð )0Ö0 �C—H“HÐ0€LÐ0ÜÑQ¤y°Ó'>ÔQÐSWÓX€IÜÑT¬	°,Ó(?ÔTÐVZÓ[€JØÐ˜JÑ.ä�‰ØqØô	
ô
 !*¨+Ó 6÷"
Ù�!�W¸'¿,¹,È!Ó:KÐPW×P]ÑP]Ð^`ÑPaÐefÓPfŠAð"
Ðñ "
ô !*¨+Ó 6÷#
Ù�!�W¸'¿,¹,È!Ó:KÐPW×P]ÑP]Ð^`ÑPaÐefÓPfŠAð#
Ðñ #
ô Ð%Ó&¨!Ò+´Ð4KÓ0LÐPQÒ0QØ.¨qÑ1ˆIØ0°Ñ3‰JÜ�Ó Ò"ô �N‰Nð+ôð ˆIØ‰JàCNÖO¸¤ W§]¡]Õ 3ÐOÐÐOÜð,à,<Ð+=ð?óð ð ˜IÑ& qÑ)€Ið ˜Ñ$ Qª¨3¨B¨3 YÑ/€Fô ‡L�LØ<Ø�‰Üˆf�j‰j‹lÓÜˆf�j‰j‹lÓÜˆf�k‰k‹mÓôô �*‰*�Q˜fŸl™lÔ
+€CØ˜œbŸf™f f§k¡k°#°rÓ&:Ð%:Ó;Ñ;Ñ<€JØ�^‰^ ˆ^Ó$€FØ
×
Ñ
 Ð
Ó
$€CÜ
‡L�LØQÜˆf�j‰j‹lÓÜˆf�j‰j‹lÓØÜˆV�iÑ×$Ñ$Ó&Ó'ôð �IÑ€Dà˜t‘_×&Ñ&�N€BˆˆB�Ø�\‰\�F€BˆÜ�8‰8�R˜"˜q™&‘[ " r¨A¡v¡+¨r°B¸±F©{¸BÀÀaÁ¹KÐHÈqÔQ€DØŒB�H‰H�b˜"˜b "Ð%¬R¯Z©ZÔ8Ñ8€Dä˜4¨F°4©LÀ3ÀtÁ9×CSÑCSÔTWÓCXÔYÐ[bÐbÐbùòK 1ùó"
ùó#
ùò&  Ps0   Á?O'Ã5O,ÄO,Ä O,Ä5O2ÅO2Å O2Æ:O8c                óÐ  — ddl }t        | |¬«      }|j                  «       d   }||d   k7  rt        d|d   ›d|›d�«      ‚|j	                  «       d   }|j
                  \  }	}
}}t        ||||
«      }|j                  |i}t        |«      D ]  }	|j                  d|«       Œ g }t        |«      D ]I  }	|j                  «       }|j                  d|«       |j                  |j                  «       |z
  dz  «       ŒK t        j                  |«      }|j                  «       d   j                  dd	«      }t        |j!                  «       «      t        |j#                  «       «      |fS )
uå  Benchmark ONNX Runtime inference for one image and provider list.

    Creates a fresh ``InferenceSession`` with the requested providers, preprocesses ``image`` once using ImageNet
    normalisation, then runs timed inference with ``time.perf_counter``.  GPU timings may underestimate real latency
    if the CUDA execution provider is configured for asynchronous execution; for accurate GPU timing use CUDA events.

    Args:
        onnx_path: Path to the ``.onnx`` model file.
        image: Input image (any size); resized to the model's expected spatial resolution.
        providers: Ordered list of ORT execution providers, e.g.
            ``["CUDAExecutionProvider", "CPUExecutionProvider"]``.
        warmup: Number of un-timed warm-up runs before measurement begins.
        runs: Number of timed runs used to compute statistics.

    Returns:
        A ``(mean_ms, std_ms, provider_label)`` tuple where ``provider_label`` is the first active provider with
        ``"ExecutionProvider"`` stripped, e.g. ``"CUDA"`` or ``"CPU"``.

    Examples:
        .. code-block:: python

            mean_ms, std_ms, label = _onnx_runtime("model.onnx", image, ["CPUExecutionProvider"])
            print(f"{label}: {mean_ms:.1f} ms Â± {std_ms:.1f}")
    r   Nr   zRequested provider u!    not active â€” ORT fell back to z8. Install onnxruntime-gpu: `pip install onnxruntime-gpu`g     @�@ÚExecutionProviderÚ )Útimer&   r   ÚRuntimeErrorr   r   rJ   r   r3   r\   Úperf_counterÚappendr1   r2   Úreplacerb   rF   rG   )Ú	onnx_pathr?   r   ÚwarmupÚrunsr�   ÚsessÚactiveÚ
input_metars   rB   r@   rA   r#   ÚfeedÚtimingsÚt0Úarr_tÚprovider_labels                      r%   Ú_onnx_runtimerŸ   ý   sn  € ó> ä 	°YÔ?€DØ×ÑÓ! !Ñ$€FØ�˜1‘ÒÜØ! )¨A¡,Ð!1Ð1RÐSYÐR\ð ]Eð Eó
ð 	
ð —‘Ó" 1Ñ%€JØ!+×!1Ñ!1Ñ€A€x�˜Ü
! %¨°¸Ó
A€CØ�O‰O˜SÐ!€Dä�6‹]ò ˆØ�‰��tÕðà€GÜ�4‹[ò <ˆØ×ÑÓ ˆØ�‰��tÔØ�‰˜×)Ñ)Ó+¨bÑ0°FÑ:Õ;ð<ô �H‰H�WÓ€EØ×'Ñ'Ó)¨!Ñ,×4Ñ4Ð5HÈ"ÓM€NÜ�—‘“Ó¤ e§i¡i£kÓ 2°NÐBÐBó    )N)r   ú
str | Pathr   zlist[str] | NoneÚreturnr   )r(   )
r?   úPILImage.Imager@   ri   rA   ri   rB   ri   r¢   z
np.ndarray)g333333Ó?)r"   r   rn   r¡   ro   rb   r¢   z!tuple[Detections, PILImage.Image])é   éd   )r”   z
Path | strr?   r£   r   z	list[str]r•   ri   r–   ri   r¢   ztuple[float, float, str])Ú__doc__Ú
__future__r   Úpathlibr   Útypingr   Únumpyr1   ÚPILr   r7   Úsupervisionr   Úrfdetr.utilities.loggerr   r   r&   rJ   r‹   rŸ   rN   r    r%   ú<module>r®      sì   ðñõ #å Ý ã Ý !Ý "å .á	‹€ô2ðr ð	+:Øð+:àð+:ð ð+:ð ð	+:ð
 ó+:ðb ð|cØð|càð|cð ð|cð 'ó	|cðH Øð6CØð6Càð6Cð ð6Cð ð	6Cð
 ð6Cð ô6Cr    