o
    j                     @   s2   d dl Zd dlmZ ddlmZ G dd dZdS )    N)distance_matrix   )check_nDc                   @   sP   e Zd ZdZdd Zdd Zedd Zdd	 Zd
d Z	dd Z
edd ZdS )ThinPlateSplineTransformul  Thin-plate spline transformation.

    Given two matching sets of points, source and destination, this class
    estimates the thin-plate spline (TPS) transformation which transforms
    each point in source into its destination counterpart.

    Attributes
    ----------
    src : (N, 2) array_like
        Coordinates of control points in source image.

    References
    ----------
    .. [1] Bookstein, Fred L. "Principal warps: Thin-plate splines and the
           decomposition of deformations," IEEE Transactions on pattern analysis
           and machine intelligence 11.6 (1989): 567–585.
           DOI:`10.1109/34.24792`
           https://user.engineering.uiowa.edu/~aip/papers/bookstein-89.pdf

    Examples
    --------
    >>> import skimage as ski

    Define source and destination control points such that they simulate
    rotating by 90 degrees and generate a meshgrid from them:

    >>> src = np.array([[0, 0], [0, 5], [5, 5], [5, 0]])
    >>> dst = np.array([[5, 0], [0, 0], [0, 5], [5, 5]])

    Estimate the transformation:

    >>> tps = ski.transform.ThinPlateSplineTransform()
    >>> tps.estimate(src, dst)
    True

    Appyling the transformation to `src` approximates `dst`:

    >>> np.round(tps(src))
    array([[5., 0.],
           [0., 0.],
           [0., 5.],
           [5., 5.]])

    Create a meshgrid to apply the transformation to:

    >>> grid = np.meshgrid(np.arange(5), np.arange(5))
    >>> grid[1]
    array([[0, 0, 0, 0, 0],
           [1, 1, 1, 1, 1],
           [2, 2, 2, 2, 2],
           [3, 3, 3, 3, 3],
           [4, 4, 4, 4, 4]])

    >>> coords = np.vstack([grid[0].ravel(), grid[1].ravel()]).T
    >>> transformed = tps(coords)
    >>> np.round(transformed[:, 1]).reshape(5, 5).astype(int)
    array([[0, 1, 2, 3, 4],
           [0, 1, 2, 3, 4],
           [0, 1, 2, 3, 4],
           [0, 1, 2, 3, 4],
           [0, 1, 2, 3, 4]])
    c                 C   s   d| _ d | _d | _d S )NF)Z
_estimated_spline_mappingssrcself r
   f/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/skimage/transform/_thin_plate_splines.py__init__G   s   
z!ThinPlateSplineTransform.__init__c                 C   s^   | j du rd}t|t|}|jdks|jd dkr"d}t|| |}| ||}|S )a*  Estimate the transformation from a set of corresponding points.

        Parameters
        ----------
        coords : (N, 2) array_like
            x, y coordinates to transform

        Returns
        -------
        transformed_coords: (N, D) array
            Destination coordinates
        NzOTransformation is undefined, define it by calling `estimate` before applying itr      z%Input `coords` must have shape (N, 2))r   
ValueErrornparrayndimshape_radial_distance_spline_function)r	   coordsmsgradial_disttransformed_coordsr
   r
   r   __call__L   s   


z!ThinPlateSplineTransform.__call__c                 C   s   t d)NzNot supported)NotImplementedErrorr   r
   r
   r   inversej   s   z ThinPlateSplineTransform.inversec                 C   sN  t |ddd t |ddd |jd dk s|jd dk r"d}t||j|jkr6d|j d	|j }t||| _|j\}}t||}| |}tt|d
f|g}|d }	tj	|	|	ftj
d}
||
d|d|f< ||
d|ddf< |j|
ddd|f< t|t	|d
 |fg}ztj|
|| _W dS  tjjy   Y dS w )a  Estimate optimal spline mappings between source and destination points.

        Parameters
        ----------
        src : (N, 2) array_like
            Control points at source coordinates.
        dst : (N, 2) array_like
            Control points at destination coordinates.

        Returns
        -------
        success: bool
            True indicates that the estimation was successful.

        Notes
        -----
        The number N of source and destination points must match.
        r   r   )Zarg_namedstr      z,Need at least 3 points in in `src` and `dst`z'Shape of `src` and `dst` didn't match, z != r   )ZdtypeNFT)r   r   r   r   r   _radial_basis_kernelr   ZhstackZonesZzerosZfloat32TZvstackZlinalgZsolver   ZLinAlgError)r	   r   r   r   nddistKPZn_plus_3LVr
   r
   r   estimaten   s2   


z!ThinPlateSplineTransform.estimatec                 C   s   t || j}| |S )zCCompute the radial distance between input points and source points.)r   r   r   )r	   r   distsr
   r
   r   r      s   
z)ThinPlateSplineTransform._radial_distancec                 C   sT   | j jd }| jd| }| j|d }|d t||dd  t|| }|S )z3Estimate the spline function in X and Y directions.r   Nr   )r   r   r   r   dot)r	   r   r   r!   war   r
   r
   r   r      s
   (z)ThinPlateSplineTransform._spline_functionc              	   C   s0   d}| d }t | dkd|t ||  }|S )aj  Compute the radial basis function for thin-plate splines.

        Parameters
        ----------
        r : (4, N) ndarray
            Input array representing the Euclidean distance between each pair of
            two collections of control points.

        Returns
        -------
        U : (4, N) ndarray
            Calculated kernel function U.
        g:0yE>r   g        )r   wherelog)rZ_smallZr_sqUr
   r
   r   r      s    z-ThinPlateSplineTransform._radial_basis_kernelN)__name__
__module____qualname____doc__r   r   propertyr   r(   r   r   staticmethodr   r
   r
   r
   r   r      s    ?
/r   )numpyr   Zscipy.spatialr   Z_shared.utilsr   r   r
   r
   r
   r   <module>   s    