Ë
    ýÿæi¦   ã                   óŒ   — d dl mZmZmZmZmZ d dlmZ d dlm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZmZ esdgZ G d	„ d
e«      Zy)é    )ÚAnyÚListÚOptionalÚSequenceÚUnion)ÚTensor)Úlip_vertex_error)ÚMetric)Údim_zero_cat)Ú_MATPLOTLIB_AVAILABLE)Ú_AX_TYPEÚ_PLOT_OUT_TYPEzLipVertexError.plotc            	       óì   ‡ — e Zd ZU dZdZeed<   dZeed<   dZeed<   dZ	e
ed<   ee   ed	<   ee   ed
<   	 ddee   dededdfˆ fd„Zdededdfd„Zdefd„Z	 ddeeeee   f      dee   defd„Zˆ xZS )ÚLipVertexErrora/
  Implements Lip Vertex Error (LVE) metric for 3D talking head evaluation.

    The Lip Vertex Error (LVE) metric evaluates the quality of lip synchronization in 3D facial animations by measuring
    the maximum Euclidean distance (L2 error) between corresponding lip vertices of the generated and ground truth
    meshes for each frame. The metric is defined as:

    .. math::
        \text{LVE} = \frac{1}{N} \sum_{i=1}^{N} \max_{v \in \text{lip}} \|x_{i,v} - \hat{x}_{i,v}\|_2^2

    where :math:`N` is the number of frames, :math:`x_{i,v}` represents the 3D coordinates of vertex :math:`v` in the
    lip region of the ground truth frame :math:`i`, and :math:`\hat{x}_{i,v}` represents the corresponding vertex in the
    predicted frame. The metric computes the maximum squared L2 distance between corresponding lip vertices for each
    frame and averages across all frames. A lower LVE value indicates better lip synchronization quality.

    As input to ``forward`` and ``update``, the metric accepts the following input:

    - ``preds`` (:class:`~torch.Tensor`): Predicted vertices tensor of shape (T, V, 3) where T is number of frames,
                V is number of vertices, and 3 represents XYZ coordinates
    - ``target`` (:class:`~torch.Tensor`): Ground truth vertices tensor of shape (T', V, 3) where T' can be different
                from T

    As output of ``forward`` and ``compute``, the metric returns the following output:

    - ``lve_score`` (:class:`~torch.Tensor`): A scalar tensor containing the mean Lip Vertex Error value across
                all frames.

    Args:
        mouth_map: List of vertex indices corresponding to the mouth region
        validate_args: bool indicating if input arguments and tensors should be validated for correctness.
            Set to ``False`` for faster computations.
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        ValueError:
            If the number of dimensions of `vertices_pred` or `vertices_gt` is not 3.
            If vertex dimensions (V) or coordinate dimensions (3) don't match
            If ``mouth_map`` is empty or contains invalid indices

    Example:
        >>> import torch
        >>> from torchmetrics.functional.multimodal import lip_vertex_error
        >>> vertices_pred = torch.randn(10, 100, 3, generator=torch.manual_seed(42))
        >>> vertices_gt = torch.randn(10, 100, 3, generator=torch.manual_seed(43))
        >>> mouth_map = [0, 1, 2, 3, 4]
        >>> lip_vertex_error(vertices_pred, vertices_gt, mouth_map)
        tensor(12.7688)

    TÚis_differentiableFÚhigher_is_betterÚfull_state_updateg        Úplot_lower_boundÚvertices_pred_listÚvertices_gt_listÚ	mouth_mapÚvalidate_argsÚkwargsÚreturnNc                 ó¾   •— t        ‰| �  di |¤Ž || _        || _        | j                  st	        d«      ‚| j                  dg d ¬«       | j                  dg d ¬«       y )Nzmouth_map cannot be empty.r   )ÚdefaultÚdist_reduce_fxr   © )ÚsuperÚ__init__r   r   Ú
ValueErrorÚ	add_state)Úselfr   r   r   Ú	__class__s       €úp/Volumes/fast/ai/experiments/voice-extract-mac/.venv/lib/python3.12/site-packages/torchmetrics/multimodal/lve.pyr    zLipVertexError.__init__V   s]   ø€ ô 	‰ÑÑ"˜6Ò"Ø"ˆŒØ*ˆÔà�~Š~ÜÐ9Ó:Ð:à�‰Ð+°RÈˆÔMØ�‰Ð)°2ÀdˆÕKó    Úvertices_predÚvertices_gtc                 ó¨  — | j                   rà|j                  dk7  s|j                  dk7  r&t        d|j                  › d|j                  › d�«      ‚|j                  dd |j                  dd k7  r&t        d|j                  › d|j                  › d�«      ‚t	        | j
                  «      |j                  d   k\  r2t        d	t	        | j
                  «      › d
|j                  d   › d�«      ‚t        |j                  d   |j                  d   «      }|d| }|d| }| j                  j                  |«       | j                  j                  |«       y)ae  Update metric states with predictions and targets.

        Args:
            vertices_pred: Predicted vertices tensor of shape (T, V, 3) where T is number of frames,
                V is number of vertices, and 3 represents XYZ coordinates
            vertices_gt: Ground truth vertices tensor of shape (T', V, 3) where T' can be different from T

        é   zIExpected both vertices_pred and vertices_gt to have 3 dimensions but got z and z dimensions respectively.é   NzdExpected vertices_pred and vertices_gt to have same vertex and coordinate dimensions but got shapes Ú.z5mouth_map contains invalid vertex indices. Max index z# is larger than number of vertices r   )
r   Úndimr!   ÚshapeÚmaxr   Úminr   Úappendr   )r#   r'   r(   Ú
min_framess       r%   ÚupdatezLipVertexError.updatef   ss  € ð ×ÒØ×!Ñ! QÒ&¨+×*:Ñ*:¸aÒ*?Ü Ø_Ø$×)Ñ)Ð*¨%°×0@Ñ0@Ð/AÐAZð\óð ð ×"Ñ" 1 2Ð&¨+×*;Ñ*;¸A¸BÐ*?Ò?Ü ðØ+×1Ñ1Ð2°%¸×8IÑ8IÐ7JÈ!ðMóð ô �4—>‘>Ó" m×&9Ñ&9¸!Ñ&<Ò<Ü ØKÌCÐPT×P^ÑP^ÓL_ÐK`ð a*Ø*7×*=Ñ*=¸aÑ*@Ð)AÀðDóð ô
 ˜×,Ñ,¨QÑ/°×1BÑ1BÀ1Ñ1EÓFˆ
Ø% k zÐ2ˆØ! + :Ð.ˆà×Ñ×&Ñ& }Ô5Ø×Ñ×$Ñ$ [Õ1r&   c                 óš   — t        | j                  «      }t        | j                  «      }t        ||| j                  | j
                  «      S )z—Compute the Lip Vertex Error over all accumulated states.

        Returns:
            torch.Tensor: A scalar tensor with the mean LVE value

        )r   r   r   r	   r   r   )r#   r'   r(   s      r%   ÚcomputezLipVertexError.compute‡   s?   € ô % T×%<Ñ%<Ó=ˆÜ" 4×#8Ñ#8Ó9ˆÜ ¨{¸D¿N¹NÈD×L^ÑL^Ó_Ð_r&   ÚvalÚaxc                 ó&   — | j                  ||«      S )a¡  Plot a single or multiple values from the metric.

        Args:
            val: Either a single result from calling `metric.forward` or `metric.compute` or a list of these results.
                If no value is provided, will automatically call `metric.compute` and plot that result.
            ax: An matplotlib axis object. If provided will add plot to that axis

        Returns:
            Figure and Axes object

        Raises:
            ModuleNotFoundError:
                If `matplotlib` is not installed

        .. plot::
            :scale: 75

            >>> # Example plotting a single value
            >>> import torch
            >>> from torchmetrics.multimodal.lve import LipVertexError
            >>> metric = LipVertexError(mouth_map=[0, 1, 2, 3, 4])
            >>> vertices_pred = torch.randn(10, 100, 3, generator=torch.manual_seed(42))
            >>> vertices_gt = torch.randn(10, 100, 3, generator=torch.manual_seed(43))
            >>> metric.update(vertices_pred, vertices_gt)
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> import torch
            >>> from torchmetrics.multimodal.lve import LipVertexError
            >>> metric = LipVertexError(mouth_map=[0, 1, 2, 3, 4])
            >>> values = []
            >>> for _ in range(10):
            ...     vertices_pred = torch.randn(10, 100, 3, generator=torch.manual_seed(42+_))
            ...     vertices_gt = torch.randn(10, 100, 3, generator=torch.manual_seed(43+_))
            ...     values.append(metric(vertices_pred, vertices_gt))
            >>> fig_, ax_ = metric.plot(values)

        )Ú_plot)r#   r6   r7   s      r%   ÚplotzLipVertexError.plot’   s   € ðX �z‰z˜#˜rÓ"Ð"r&   )T)NN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   ÚboolÚ__annotations__r   r   r   Úfloatr   r   Úintr   r    r3   r5   r   r   r   r   r   r:   Ú__classcell__)r$   s   @r%   r   r      së   ø… ñ/ðb #Ð�tÓ"Ø"Ð�dÓ"Ø#Ð�tÓ#Ø!Ð�eÓ!à˜V™Ó$Ø˜6‘lÓ"ð
 #ñLà˜‘9ðLð ðLð ð	Lð
 
õLð 2 Fð 2¸ð 2ÀDó 2ðB	`˜ó 	`ð _cñ,#Ø˜E &¨(°6Ñ*:Ð":Ñ;Ñ<ð,#ØIQÐRZÑI[ð,#à	÷,#r&   r   N)Útypingr   r   r   r   r   Útorchr   Ú&torchmetrics.functional.multimodal.lver	   Útorchmetrics.metricr
   Útorchmetrics.utilities.datar   Útorchmetrics.utilities.importsr   Útorchmetrics.utilities.plotr   r   Ú__doctest_skip__r   r   r&   r%   Ú<module>rL      s9   ð÷ 8Õ 7å å CÝ &Ý 4Ý @ß @áØ-Ð.Ðôb#�Võ b#r&   