o
    eN                     @   s   d Z ddlmZmZm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dlmZmZmZ dd
dZG dd deZG dd deZdS )zDClasses to represent keypoints, i.e. points given as xy-coordinates.    )print_functiondivisionabsolute_importN   )imgaug   )IAugmentable)normalize_shapeproject_coords_remove_out_of_image_fraction_h㈵>c                 C   s"  |dur| du s
J t d |} t| d}	 tjj| |g}|dkdddf }d||  }t|}|| }t|| |  d}	t	| t| }
|
dkrT|	}n.|
t	| kr\|S |	| | }tj
|}|dkrndn|
| }tdd| |	 td||  }tjj|||k r|S |}q)a  Estimate the geometric median of points in 2D.

    Code from https://stackoverflow.com/a/30305181

    Parameters
    ----------
    points : (N,2) ndarray
        Points in 2D. Second axis must be given in xy-form.

    eps : float, optional
        Distance threshold when to return the median.

    X : None or (N,2) ndarray, optional
        Deprecated.

    Returns
    -------
    (2,) ndarray
        Geometric median as xy-coordinate.

    Nz.Using 'X' is deprecated, use 'points' instead.r   Tr   )iaZwarn_deprecatednpmeanscipyZspatialZdistanceZcdistsumlenZlinalgZnormmaxminZ	euclidean)pointsZepsXydistZnonzerosZdist_invZdist_inv_sumZdist_inv_normTZ	num_zerosy1RrZrinv r   GD:\Projects\ConvertPro\env\Lib\site-packages\imgaug/augmentables/kps.pycompute_geometric_median   s2   

 r   c                   @   s   e Zd ZdZdd Zedd Zedd Zedd	 Zed
d Z	edd Z
dd Zdd Zdd Zdd Zd2ddZd2ddZ		d3d d!Z	d4d"d#Zd5d%d&Zd5d'd(Zd6d*d+Zd6d,d-Zd.d/ Zd0d1 Zd)S )7KeypointzA single keypoint (aka landmark) on an image.

    Parameters
    ----------
    x : number
        Coordinate of the keypoint on the x axis.

    y : number
        Coordinate of the keypoint on the y axis.

    c                 C   s   || _ || _d S Nxr   selfr#   r   r   r   r   __init__S   s   
zKeypoint.__init__c                 C   s,   t jdt jd}| j| jg|dddf< |S )zGet the xy-coordinates as an ``(N,2)`` ndarray.

        Added in 0.4.0.

        Returns
        -------
        ndarray
            An ``(N, 2)`` ``float32`` ndarray with ``N=1`` containing the
            coordinates of this keypoints.

        )r   r   dtyper   N)r   emptyfloat32r#   r   )r%   Zarrr   r   r   coordsW   s   zKeypoint.coordsc                 C      t t| jS )zGet the keypoint's x-coordinate, rounded to the closest integer.

        Returns
        -------
        result : int
            Keypoint's x-coordinate, rounded to the closest integer.

        )intr   roundr#   r%   r   r   r   x_inth      
zKeypoint.x_intc                 C   r,   )zGet the keypoint's y-coordinate, rounded to the closest integer.

        Returns
        -------
        result : int
            Keypoint's y-coordinate, rounded to the closest integer.

        )r-   r   r.   r   r/   r   r   r   y_intt   r1   zKeypoint.y_intc                 C   s   | j dddf S )zGet the keypoint's x- and y-coordinate as a single array.

        Added in 0.4.0.

        Returns
        -------
        ndarray
            A ``(2,)`` ``ndarray`` denoting the xy-coordinate pair.

        r   N)r+   r/   r   r   r   xy   s   zKeypoint.xyc                 C   s   t | jt jS )zGet the keypoint's xy-coord, rounded to closest integer.

        Added in 0.4.0.

        Returns
        -------
        ndarray
            A ``(2,)`` ``ndarray`` denoting the xy-coordinate pair.

        )r   r.   r3   astypeZint32r/   r   r   r   xy_int   s   zKeypoint.xy_intc                 C   s*   t | j| jfg||}|d \| _| _| S )a  Project in-place the keypoint onto a new position on a new image.

        E.g. if the keypoint is on its original image
        at ``x=(10 of 100 pixels)`` and ``y=(20 of 100 pixels)`` and is
        projected onto a new image with size ``(width=200, height=200)``, its
        new position will be ``(20, 40)``.

        This is intended for cases where the original image is resized.
        It cannot be used for more complex changes (e.g. padding, cropping).

        Added in 0.4.0.

        Parameters
        ----------
        from_shape : tuple of int
            Shape of the original image. (Before resize.)

        to_shape : tuple of int
            Shape of the new image. (After resize.)

        Returns
        -------
        imgaug.augmentables.kps.Keypoint
            Keypoint object with new coordinates.
            The instance of the keypoint may have been modified in-place.

        r   )r
   r#   r   )r%   
from_shapeto_shapeZxy_projr   r   r   project_   s   zKeypoint.project_c                 C      |   ||S )a$  Project the keypoint onto a new position on a new image.

        E.g. if the keypoint is on its original image
        at ``x=(10 of 100 pixels)`` and ``y=(20 of 100 pixels)`` and is
        projected onto a new image with size ``(width=200, height=200)``, its
        new position will be ``(20, 40)``.

        This is intended for cases where the original image is resized.
        It cannot be used for more complex changes (e.g. padding, cropping).

        Parameters
        ----------
        from_shape : tuple of int
            Shape of the original image. (Before resize.)

        to_shape : tuple of int
            Shape of the new image. (After resize.)

        Returns
        -------
        imgaug.augmentables.kps.Keypoint
            Keypoint object with new coordinates.

        )deepcopyr8   )r%   r6   r7   r   r   r   project   s   zKeypoint.projectc                 C   sX   t |}|dd \}}d| j  ko|k n  }d| j  ko#|k n  }| p+| S )a  Estimate whether this point is outside of the given image plane.

        Added in 0.4.0.

        Parameters
        ----------
        image : (H,W,...) ndarray or tuple of int
            Image dimensions to use.
            If an ``ndarray``, its shape will be used.
            If a ``tuple``, it is assumed to represent the image shape
            and must contain at least two integers.

        Returns
        -------
        bool
            ``True`` is the point is inside the image plane, ``False``
            otherwise.

        r   r   )r	   r   r#   )r%   imageshapeheightwidthZy_insideZx_insider   r   r   is_out_of_image   s
   zKeypoint.is_out_of_imagec                 C   s   t | |S )a  Compute fraction of the keypoint that is out of the image plane.

        The fraction is always either ``1.0`` (point is outside of the image
        plane) or ``0.0`` (point is inside the image plane). This method
        exists for consistency with other augmentables, e.g. bounding boxes.

        Added in 0.4.0.

        Parameters
        ----------
        image : (H,W,...) ndarray or tuple of int
            Image dimensions to use.
            If an ``ndarray``, its shape will be used.
            If a ``tuple``, it is assumed to represent the image shape
            and must contain at least two integers.

        Returns
        -------
        float
            Either ``1.0`` (point is outside of the image plane) or
            ``0.0`` (point is inside of it).

        )floatr@   r%   r<   r   r   r   compute_out_of_image_fraction      z&Keypoint.compute_out_of_image_fractionr   c                 C   s    |  j |7  _ |  j|7  _| S )a  Move the keypoint around on an image in-place.

        Added in 0.4.0.

        Parameters
        ----------
        x : number, optional
            Move by this value on the x axis.

        y : number, optional
            Move by this value on the y axis.

        Returns
        -------
        imgaug.augmentables.kps.Keypoint
            Keypoint object with new coordinates.
            The instance of the keypoint may have been modified in-place.

        r"   r$   r   r   r   shift_  s   zKeypoint.shift_c                 C   r9   )ai  Move the keypoint around on an image.

        Parameters
        ----------
        x : number, optional
            Move by this value on the x axis.

        y : number, optional
            Move by this value on the y axis.

        Returns
        -------
        imgaug.augmentables.kps.Keypoint
            Keypoint object with new coordinates.

        r:   rE   r$   r   r   r   shift#  s   zKeypoint.shiftr      r         ?   TFc                 C   sj  |rt |}|jdkrt|sJ dt|f n|jdkr-t|r-|g|jd  }|j}|}|dk r8|S |dkr?d}n|jt j	dd	}|t 
| }|jd
d \}	}
| j| j}}t||d  d
}t|d |d  |
}t||d  d
}t|d |d  |	}t ||gd
|
\}}t ||gd
|	\}}|d
k p||
k}|d
k p||
d k}|d
k p||	k}|d
k p||	d k}|o|}|o|}|| dk }|| dk }|s|s|s|s|dkr||||||f< n&d| |||||f  | |||||f< n|rtd|||jf |jj|jkr3|jdkr,t j|d
d|d}|j|dd	}|S )a*  Draw the keypoint onto a given image.

        The keypoint is drawn as a square.

        Parameters
        ----------
        image : (H,W,3) ndarray
            The image onto which to draw the keypoint.

        color : int or list of int or tuple of int or (3,) ndarray, optional
            The RGB color of the keypoint.
            If a single ``int`` ``C``, then that is equivalent to ``(C,C,C)``.

        alpha : float, optional
            The opacity of the drawn keypoint, where ``1.0`` denotes a fully
            visible keypoint and ``0.0`` an invisible one.

        size : int, optional
            The size of the keypoint. If set to ``S``, each square will have
            size ``S x S``.

        copy : bool, optional
            Whether to copy the image before drawing the keypoint.

        raise_if_out_of_image : bool, optional
            Whether to raise an exception if the keypoint is outside of the
            image.

        Returns
        -------
        image : (H,W,3) ndarray
            Image with drawn keypoint.

        r   zHGot a 2D image. Expected then 'color' to be a single number, but got %s.rK   g{Gz?gGz?r   F)copyr   z;Cannot draw keypoint x=%.8f, y=%.8f on image with shape %s.uint8rI   )out)r   rM   ndimr   Zis_single_numberstrr=   r(   r4   r*   arrayr2   r0   r   r   clip	Exceptionname)r%   r<   coloralphasizerM   raise_if_out_of_imageZinput_dtypeZalpha_colorr>   r?   r   r#   x1x2r   y2Z
x1_clippedZ
x2_clippedZ
y1_clippedZ
y2_clippedZx1_clipped_ooiZx2_clipped_ooiZy1_clipped_ooiZy2_clipped_ooiZx_ooiZy_ooiZx_zero_sizeZy_zero_sizer   r   r   draw_on_image6  sl   %


zKeypoint.draw_on_imagec                    s  |d | d|d   }t j|dft jd}t  j||   j||  |d | }d}d}t|D ]B\}	}
|dkr@ jg}nt  j|d d |   j|d d |  |}|D ]}||
g||< |d7 }q[|	|k rq|d7 }q3|d8 }q3|rz|S  fdd|D S )a  Generate nearby points based on manhattan distance.

        To generate the first neighbouring points, a distance of ``S`` (step
        size) is moved from the center point (this keypoint) to the top,
        right, bottom and left, resulting in four new points. From these new
        points, the pattern is repeated. Overlapping points are ignored.

        The resulting points have a shape similar to a square rotated
        by ``45`` degrees.

        Parameters
        ----------
        nb_steps : int
            The number of steps to move from the center point.
            ``nb_steps=1`` results in a total of ``5`` output points (one
            center point + four neighbours).

        step_size : number
            The step size to move from every point to its neighbours.

        return_array : bool, optional
            Whether to return the generated points as a list of
            :class:`Keypoint` or an array of shape ``(N,2)``, where ``N`` is
            the number of generated points and the second axis contains the
            x-/y-coordinates.

        Returns
        -------
        list of imgaug.augmentables.kps.Keypoint or (N,2) ndarray
            If `return_array` was ``False``, then a list of :class:`Keypoint`.
            Otherwise a numpy array of shape ``(N,2)``, where ``N`` is the
            number of generated points and the second axis contains
            the x-/y-coordinates. The center keypoint (the one on which this
            function was called) is always included.

        r   r   r'   r   c                    s"   g | ]} j |d  |d dqS r   r   r"   r:   ).0pointr/   r   r   
<listcomp>  s   " z>Keypoint.generate_similar_points_manhattan.<locals>.<listcomp>)r   zerosr*   Zlinspacer   	enumerater#   )r%   Znb_stepsZ	step_sizeZreturn_arrayZ	nb_pointsr   yyr?   Z	nth_pointZi_yr   xxr#   r   r/   r   !generate_similar_points_manhattan  s4   .




z*Keypoint.generate_similar_points_manhattan-C6?c                 C   sj   t |r	|j}nt |rtt |}nt|ts$J dt|f |j	j}| j	}t
j|j||ddS )a  Estimate if this and another KP have almost identical coordinates.

        Added in 0.4.0.

        Parameters
        ----------
        other : imgaug.augmentables.kps.Keypoint or iterable
            The other keypoint with which to compare this one.
            If this is an ``iterable``, it is assumed to contain the
            xy-coordinates of a keypoint.

        max_distance : number, optional
            The maximum euclidean distance between a this keypoint and the
            other one. If the distance is exceeded, the two keypoints are not
            viewed as equal.

        Returns
        -------
        bool
            Whether the two keypoints have almost identical coordinates.

        zcExpected 'other' to be an iterable containing one (x,y)-coordinate pair or a Keypoint. Got type %s.r   )ZatolZrtol)r   Zis_np_arrayZflatis_iterablelistflatten
isinstancer    typer+   r   Zallclose)r%   othermax_distanceZcoords_bZcoords_ar   r   r   coords_almost_equals  s   

zKeypoint.coords_almost_equalsc                 C      | j ||dS )a  Compare this and another KP's coordinates.

        .. note::

            This method is currently identical to ``coords_almost_equals``.
            It exists for consistency with ``BoundingBox`` and ``Polygons``.

        Added in 0.4.0.

        Parameters
        ----------
        other : imgaug.augmentables.kps.Keypoint or iterable
            The other object to compare against. Expected to be a
            ``Keypoint``.

        max_distance : number, optional
            See
            :func:`~imgaug.augmentables.kps.Keypoint.coords_almost_equals`.

        Returns
        -------
        bool
            ``True`` if the coordinates are almost equal. Otherwise ``False``.

        )ro   )rp   )r%   rn   ro   r   r   r   almost_equals  s   zKeypoint.almost_equalsNc                 C   rq   )a  Create a shallow copy of the keypoint instance.

        Parameters
        ----------
        x : None or number, optional
            Coordinate of the keypoint on the x axis.
            If ``None``, the instance's value will be copied.

        y : None or number, optional
            Coordinate of the keypoint on the y axis.
            If ``None``, the instance's value will be copied.

        Returns
        -------
        imgaug.augmentables.kps.Keypoint
            Shallow copy.

        r"   r_   r$   r   r   r   rM   ,  s   zKeypoint.copyc                 C   s0   |du r| j n|}|du r| jn|}t||dS )a  Create a deep copy of the keypoint instance.

        Parameters
        ----------
        x : None or number, optional
            Coordinate of the keypoint on the x axis.
            If ``None``, the instance's value will be copied.

        y : None or number, optional
            Coordinate of the keypoint on the y axis.
            If ``None``, the instance's value will be copied.

        Returns
        -------
        imgaug.augmentables.kps.Keypoint
            Deep copy.

        Nr"   )r#   r   r    r$   r   r   r   r:   A  s   zKeypoint.deepcopyc                 C      |   S r!   __str__r/   r   r   r   __repr__X     zKeypoint.__repr__c                 C   s   d| j | jf S )NzKeypoint(x=%.8f, y=%.8f)r"   r/   r   r   r   ru   [  s   zKeypoint.__str__r   r   rH   rJ   rK   TFF)rh   NN)__name__
__module____qualname____doc__r&   propertyr+   r0   r2   r3   r5   r8   r;   r@   rC   rE   rG   r]   rg   rp   rr   rM   r:   rv   ru   r   r   r   r   r    F   s<    




 


e

O
'

r    c                   @   s  e Zd ZdZdd Zedd Zejdd Zedd Zed	d
 Z	edd Z
dd Zdd Z		dPddZdd Zdd Zdd Zdd ZdQd!d"ZdQd#d$Zejd%d&d'd( Zd)d* Zeejd+d&d,d- Zed.d/ Zd0d1 ZdRd3d4Zed5d5d6d2d7fd8d9ZdSd:d;Zedd5d5d6d7d7fd<d=Z d>d? Z!d@dA Z"dTdBdCZ#dTdDdEZ$dFdG Z%dHdI Z&dJdK Z'dLdM Z(dNdO Z)d7S )UKeypointsOnImagea  Container for all keypoints on a single image.

    Parameters
    ----------
    keypoints : list of imgaug.augmentables.kps.Keypoint
        List of keypoints on the image.

    shape : tuple of int or ndarray
        The shape of the image on which the objects are placed.
        Either an image with shape ``(H,W,[C])`` or a ``tuple`` denoting
        such an image shape.

    Examples
    --------
    >>> import numpy as np
    >>> from imgaug.augmentables.kps import Keypoint, KeypointsOnImage
    >>>
    >>> image = np.zeros((70, 70))
    >>> kps = [Keypoint(x=10, y=20), Keypoint(x=34, y=60)]
    >>> kps_oi = KeypointsOnImage(kps, shape=image.shape)

    c                 C   s   || _ t|| _d S r!   )	keypointsr	   r=   r%   r   r=   r   r   r   r&   w  s   zKeypointsOnImage.__init__c                 C   s   | j S )zGet the keypoints in this container.

        Added in 0.4.0.

        Returns
        -------
        list of Keypoint
            Keypoints within this container.

        r   r/   r   r   r   items{  s   zKeypointsOnImage.itemsc                 C   s
   || _ dS )zSet the keypoints in this container.

        Added in 0.4.0.

        Parameters
        ----------
        value : list of Keypoint
            Keypoints within this container.

        Nr   )r%   valuer   r   r   r     s   
c                 C   
   | j d S )zfGet the image height.

        Returns
        -------
        int
            Image height.

        r   r=   r/   r   r   r   r>        

zKeypointsOnImage.heightc                 C   r   )zdGet the image width.

        Returns
        -------
        int
            Image width.

        r   r   r/   r   r   r   r?     r   zKeypointsOnImage.widthc                 C   s   t | jdkS )zDetermine whether this object contains zero keypoints.

        Returns
        -------
        bool
            ``True`` if this object contains zero keypoints.

        r   )r   r   r/   r   r   r   r)     s   
zKeypointsOnImage.emptyc                 C   s^   t |}|dd | jdd kr|| _| S t| jD ]\}}|| j|| j|< q|| _| S )a  Project all keypoints from one image shape to a new one in-place.

        Added in 0.4.0.

        Parameters
        ----------
        image : ndarray or tuple of int
            New image onto which the keypoints are to be projected.
            May also simply be that new image's shape tuple.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Object containing all projected keypoints.
            The object may have been modified in-place.

        r   r   )r	   r=   rd   r   r8   )r%   r<   Zon_shapeikpr   r   r   on_  s   zKeypointsOnImage.on_c                 C      |   |S )a  Project all keypoints from one image shape to a new one.

        Parameters
        ----------
        image : ndarray or tuple of int
            New image onto which the keypoints are to be projected.
            May also simply be that new image's shape tuple.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Object containing all projected keypoints.

        )r:   r   rB   r   r   r   on  s   zKeypointsOnImage.onrH   rJ   rK   TFc              	   C   s8   |rt |n|}| jD ]}|j||||d|d}q|S )a  Draw all keypoints onto a given image.

        Each keypoint is drawn as a square of provided color and size.

        Parameters
        ----------
        image : (H,W,3) ndarray
            The image onto which to draw the keypoints.
            This image should usually have the same shape as
            set in ``KeypointsOnImage.shape``.

        color : int or list of int or tuple of int or (3,) ndarray, optional
            The RGB color of all keypoints.
            If a single ``int`` ``C``, then that is equivalent to ``(C,C,C)``.

        alpha : float, optional
            The opacity of the drawn keypoint, where ``1.0`` denotes a fully
            visible keypoint and ``0.0`` an invisible one.

        size : int, optional
            The size of each point. If set to ``C``, each square will have
            size ``C x C``.

        copy : bool, optional
            Whether to copy the image before drawing the points.

        raise_if_out_of_image : bool, optional
            Whether to raise an exception if any keypoint is outside of the
            image.

        Returns
        -------
        (H,W,3) ndarray
            Image with drawn keypoints.

        F)rV   rW   rX   rM   rY   )r   rM   r   r]   )r%   r<   rV   rW   rX   rM   rY   keypointr   r   r   r]     s   '

zKeypointsOnImage.draw_on_imagec                 C   s
   t | |S )a  Remove all KPs with an OOI fraction of at least `fraction` in-place.

        'OOI' is the abbreviation for 'out of image'.

        This method exists for consistency with other augmentables, e.g.
        bounding boxes.

        Added in 0.4.0.

        Parameters
        ----------
        fraction : number
            Minimum out of image fraction that a keypoint has to have in
            order to be removed. Note that any keypoint can only have a
            fraction of either ``1.0`` (is outside) or ``0.0`` (is inside).
            Set this to ``0.0+eps`` to remove all points that are outside of
            the image. Setting this to ``0.0`` will remove all points.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Reduced set of keypoints, with those thathad an out of image
            fraction greater or equal the given one removed.
            The object may have been modified in-place.

        )r   r%   fractionr   r   r   remove_out_of_image_fraction_  s   
z.KeypointsOnImage.remove_out_of_image_fraction_c                 C   r   )aS  Remove all KPs with an out of image fraction of at least `fraction`.

        This method exists for consistency with other augmentables, e.g.
        bounding boxes.

        Added in 0.4.0.

        Parameters
        ----------
        fraction : number
            Minimum out of image fraction that a keypoint has to have in
            order to be removed. Note that any keypoint can only have a
            fraction of either ``1.0`` (is outside) or ``0.0`` (is inside).
            Set this to ``0.0+eps`` to remove all points that are outside of
            the image. Setting this to ``0.0`` will remove all points.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Reduced set of keypoints, with those thathad an out of image
            fraction greater or equal the given one removed.

        )r:   r   r   r   r   r   remove_out_of_image_fraction5  rD   z-KeypointsOnImage.remove_out_of_image_fractionc                 C   s
   |  dS )ay  Remove all KPs that are outside of the image plane.

        This method exists for consistency with other augmentables, e.g.
        bounding boxes.

        Added in 0.4.0.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Keypoints that are inside the image plane.
            The object may have been modified in-place.

              ?)r   r/   r   r   r   clip_out_of_image_O  s   
z#KeypointsOnImage.clip_out_of_image_c                 C   s   |    S )aA  Remove all KPs that are outside of the image plane.

        This method exists for consistency with other augmentables, e.g.
        bounding boxes.

        Added in 0.4.0.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Keypoints that are inside the image plane.

        )r:   r   r/   r   r   r   clip_out_of_imagea  s   z"KeypointsOnImage.clip_out_of_imager   c                 C   s,   t | jD ]\}}|j||d| j|< q| S )a  Move the keypoints on the x/y-axis in-place.

        Added in 0.4.0.

        Parameters
        ----------
        x : number, optional
            Move each keypoint by this value on the x axis.

        y : number, optional
            Move each keypoint by this value on the y axis.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Keypoints after moving them.
            The object and its items may have been modified in-place.

        r"   )rd   r   rE   )r%   r#   r   r   r   r   r   r   rE   q  s   zKeypointsOnImage.shift_c                 C   s   |   j||dS )a  Move the keypoints on the x/y-axis.

        Parameters
        ----------
        x : number, optional
            Move each keypoint by this value on the x axis.

        y : number, optional
            Move each keypoint by this value on the y axis.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Keypoints after moving them.

        r"   rF   r$   r   r   r   rG     s   zKeypointsOnImage.shiftzKeypointsOnImage.to_xy_array())Zalt_funcc                 C   rs   )-  Convert all keypoint coordinates to an array of shape ``(N,2)``.

        Returns
        -------
        (N, 2) ndarray
            Array containing the coordinates of all keypoints.
            ``N`` denotes the number of keypoints. The second axis denotes
            the x/y-coordinates.

        )to_xy_arrayr/   r   r   r   get_coords_array  s   z!KeypointsOnImage.get_coords_arrayc                 C   sN   t jt| jdft jd}t| jD ]\}}|j||df< |j||df< q|S )r   r   r'   r   r   )r   rc   r   r   r*   rd   r#   r   )r%   resultr   r   r   r   r   r     s
   zKeypointsOnImage.to_xy_arrayz KeypointsOnImage.from_xy_array()c                 C   s   t | |S )a  Convert an ``(N,2)`` array to a ``KeypointsOnImage`` object.

        Parameters
        ----------
        coords : (N, 2) ndarray
            Coordinates of ``N`` keypoints on an image, given as a ``(N,2)``
            array of xy-coordinates.

        shape : tuple
            The shape of the image on which the keypoints are placed.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            :class:`KeypointsOnImage` object containing the array's keypoints.

        )r   from_xy_array)r+   r=   r   r   r   from_coords_array  s   z"KeypointsOnImage.from_coords_arrayc                 C   sh   t j|t jd}|jd dkrtg |S |jdkr |jd dks(J d|jf dd |D }t||S )a-  Convert an ``(N,2)`` array to a ``KeypointsOnImage`` object.

        Parameters
        ----------
        xy : (N, 2) ndarray or iterable of iterable of number
            Coordinates of ``N`` keypoints on an image, given as a ``(N,2)``
            array of xy-coordinates.

        shape : tuple of int or ndarray
            The shape of the image on which the keypoints are placed.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            :class:`KeypointsOnImage` object containing the array's keypoints.

        r'   r   r   rL   7Expected input array to have shape (N,2), got shape %s.c                 S   s    g | ]}t |d  |d dqS r^   )r    )r`   coordr   r   r   rb     s     z2KeypointsOnImage.from_xy_array.<locals>.<listcomp>)r   rR   r*   r=   r   rP   )clsr3   r=   r   r   r   r   r     s   

zKeypointsOnImage.from_xy_arrayc                 C   s   t j|t jd}|jd dks#|jdkr|jd dks#J d|jf t|t| jks9J dt|t| jf t| j|D ]\}\}}||_||_	q?| S )a  Modify the keypoint coordinates of this instance in-place.

        .. note::

            This currently expects that `xy` contains exactly as many
            coordinates as there are keypoints in this instance. Otherwise,
            an ``AssertionError`` will be raised.

        Added in 0.4.0.

        Parameters
        ----------
        xy : (N, 2) ndarray or iterable of iterable of number
            Coordinates of ``N`` keypoints on an image, given as a ``(N,2)``
            array of xy-coordinates. ``N`` must match the number of keypoints
            in this instance.

        Returns
        -------
        KeypointsOnImage
            This instance itself, with updated keypoint coordinates.
            Note that the instance was modified in-place.

        r'   r   r   rL   r   zxExpected to receive as many keypoint coordinates as there are currently keypoints in this instance. Got %d, expected %d.)
r   rR   r*   r=   rP   r   r   zipr#   r   )r%   r3   r   r#   r   r   r   r   fill_from_xy_array_  s    (z$KeypointsOnImage.fill_from_xy_array_r   c                 C   s:  | j dd \}}tj||t| jftjd}|d dks$J d|f td|d d }t| jD ]h\}}|j}|j	}	t
|	| d|d }
t
|	| d d|}t
|| d|d }t
|| d d|}|
|k r{||k r{d||||
||f< d|  kr|k rn q2d|	  kr|k rn q2d|||	|f< q2|S )a|  Create an ``(H,W,N)`` image with keypoint coordinates set to ``255``.

        This method generates a new ``uint8`` array of shape ``(H,W,N)``,
        where ``H`` is the ``.shape`` height, ``W`` the ``.shape`` width and
        ``N`` is the number of keypoints. The array is filled with zeros.
        The coordinate of the ``n``-th keypoint is set to ``255`` in the
        ``n``-th channel.

        This function can be used as a helper when augmenting keypoints with
        a method that only supports the augmentation of images.

        Parameters
        -------
        size : int
            Size of each (squared) point.

        Returns
        -------
        (H,W,N) ndarray
            Image in which the keypoints are marked. ``H`` is the height,
            defined in ``KeypointsOnImage.shape[0]`` (analogous ``W``).
            ``N`` is the number of keypoints.

        r   r   r'   z5Expected 'size' to have an odd value, got %d instead.r      rI   )r=   r   rc   r   r   rN   r   rd   r2   r0   rS   )r%   rX   r>   r?   r<   Zsizehr   r   r   r#   rZ   r[   r   r\   r   r   r   to_keypoint_image  s&   0z"KeypointsOnImage.to_keypoint_imagerL   r"   Nc                 C   sn  | j dksJ d| j | jf | j\}}}d}|du r"d}d}d}	n6t|ttfrAt|dks8J dt|f |d	 }|d
 }	nt|trO|d }|d }	n	tdt|f g }
t	
|D ]D}t| d|f }t|||f}| |d	 |d
 |f |k}|r|d
 d }|d	 d }|
t||d q_|rq_|
t||	d q_||f}|dur||f7 }t|
|dS )a  Convert ``to_keypoint_image()`` outputs to ``KeypointsOnImage``.

        This is the inverse of :func:`KeypointsOnImage.to_keypoint_image`.

        Parameters
        ----------
        image : (H,W,N) ndarray
            The keypoints image. N is the number of keypoints.

        if_not_found_coords : tuple or list or dict or None, optional
            Coordinates to use for keypoints that cannot be found in `image`.

            * If this is a ``list``/``tuple``, it must contain two ``int``
              values.
            * If it is a ``dict``, it must contain the keys ``x`` and
              ``y`` with each containing one ``int`` value.
            * If this is ``None``, then the keypoint will not be added to the
              final :class:`KeypointsOnImage` object.

        threshold : int, optional
            The search for keypoints works by searching for the argmax in
            each channel. This parameters contains the minimum value that
            the max must have in order to be viewed as a keypoint.

        nb_channels : None or int, optional
            Number of channels of the image on which the keypoints are placed.
            Some keypoint augmenters require that information.
            If set to ``None``, the keypoint's shape will be set
            to ``(height, width)``, otherwise ``(height, width, nb_channels)``.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            The extracted keypoints.

        rK   zHExpected 'image' to have three dimensions, got %d with shape %s instead.FNTrL   r   zRExpected tuple 'if_not_found_coords' to contain exactly two values, got %d values.r   r   r#   r   IExpected if_not_found_coords to be None or tuple or list or dict, got %s..r   r"   r   )rP   r=   rl   tuplerj   r   dictrT   rm   smxranger   argmaxunravel_indexappendr    r   )r<   if_not_found_coords	thresholdnb_channelsr>   r?   nb_keypointsdrop_if_not_foundif_not_found_xif_not_found_yr   r   Zmaxidx_flatZmaxidx_ndimfoundr#   r   	out_shaper   r   r   from_keypoint_imageK  sZ   (





z$KeypointsOnImage.from_keypoint_imagec                 C   s   | j dd \}}tj||t| jftjd}td|}td|}t||\}}t| jD ] \}	}
|
j	|
j
}}|| d || d  |dddd|	f< q0t|}|r^d|d  S |S )a  Generate a ``(H,W,N)`` array of distance maps for ``N`` keypoints.

        The ``n``-th distance map contains at every location ``(y, x)`` the
        euclidean distance to the ``n``-th keypoint.

        This function can be used as a helper when augmenting keypoints with a
        method that only supports the augmentation of images.

        Parameters
        -------
        inverted : bool, optional
            If ``True``, inverted distance maps are returned where each
            distance value d is replaced by ``d/(d+1)``, i.e. the distance
            maps have values in the range ``(0.0, 1.0]`` with ``1.0`` denoting
            exactly the position of the respective keypoint.

        Returns
        -------
        (H,W,N) ndarray
            A ``float32`` array containing ``N`` distance maps for ``N``
            keypoints. Each location ``(y, x, n)`` in the array denotes the
            euclidean distance at ``(y, x)`` to the ``n``-th keypoint.
            If `inverted` is ``True``, the distance ``d`` is replaced
            by ``d/(d+1)``. The height and width of the array match the
            height and width in ``KeypointsOnImage.shape``.

        r   r   r'   Nr   )r=   r   rc   r   r   r*   ZarangeZmeshgridrd   r   r#   sqrt)r%   invertedr>   r?   distance_mapsre   rf   Zgrid_xxZgrid_yyr   r   r   r#   r   r   r   to_distance_maps  s   ,
z!KeypointsOnImage.to_distance_mapsc                 C   s  | j dksJ d| j | jf | j\}}}d}|du r"d}d}	d}
n6t|ttfrAt|dks8J dt|f |d	 }	|d
 }
nt|trO|d }	|d }
n	tdt|f g }t	
|D ]e}|rmt| d|f }n	t| d|f }t|||f}|s|dur| |d	 |d
 |f |k }n|r|dur| |d	 |d
 |f |k}nd}|r|t|d
 |d	 d q_|rq_|t|	|
d q_||f}|dur||f7 }t||dS )a_  Convert outputs of ``to_distance_maps()`` to ``KeypointsOnImage``.

        This is the inverse of :func:`KeypointsOnImage.to_distance_maps`.

        Parameters
        ----------
        distance_maps : (H,W,N) ndarray
            The distance maps. ``N`` is the number of keypoints.

        inverted : bool, optional
            Whether the given distance maps were generated in inverted mode
            (i.e. :func:`KeypointsOnImage.to_distance_maps` was called with
            ``inverted=True``) or in non-inverted mode.

        if_not_found_coords : tuple or list or dict or None, optional
            Coordinates to use for keypoints that cannot be found
            in `distance_maps`.

            * If this is a ``list``/``tuple``, it must contain two ``int``
              values.
            * If it is a ``dict``, it must contain the keys ``x`` and
              ``y`` with each containing one ``int`` value.
            * If this is ``None``, then the keypoint will not be added to the
              final :class:`KeypointsOnImage` object.

        threshold : float, optional
            The search for keypoints works by searching for the
            argmin (non-inverted) or argmax (inverted) in each channel. This
            parameters contains the maximum (non-inverted) or
            minimum (inverted) value to accept in order to view a hit as a
            keypoint. Use ``None`` to use no min/max.

        nb_channels : None or int, optional
            Number of channels of the image on which the keypoints are placed.
            Some keypoint augmenters require that information.
            If set to ``None``, the keypoint's shape will be set
            to ``(height, width)``, otherwise ``(height, width, nb_channels)``.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            The extracted keypoints.

        rK   zAExpected three-dimensional input, got %d dimensions and shape %s.FNTrL   r   zQExpected tuple/list 'if_not_found_coords' to contain exactly two entries, got %d.r   r   r#   r   r   .r"   r   )rP   r=   rl   r   rj   r   r   rT   rm   r   r   r   r   Zargminr   r   r    r   )r   r   r   r   r   r>   r?   r   r   r   r   r   r   Zhitidx_flatZhitidx_ndimr   r   r   r   r   from_distance_maps  sj   1





z#KeypointsOnImage.from_distance_mapsc                 C   rs   )a`  Convert the keypoints to one ``KeypointsOnImage`` instance.

        This method exists for consistency with ``BoundingBoxesOnImage``,
        ``PolygonsOnImage`` and ``LineStringsOnImage``.

        Added in 0.4.0.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Copy of this keypoints instance.

        r_   r/   r   r   r   to_keypoints_on_image9  s   z&KeypointsOnImage.to_keypoints_on_imagec                 C   sb   t | j}t |j|ksJ d|t |jf t| j|jD ]\}}|j|_|j|_q|j| _| S )a-  Invert the output of ``to_keypoints_on_image()`` in-place.

        This function writes in-place into this ``KeypointsOnImage``
        instance.

        Added in 0.4.0.

        Parameters
        ----------
        kpsoi : imgaug.augmentables.kps.KeypointsOnImages
            Keypoints to copy data from, i.e. the outputs of
            ``to_keypoints_on_image()``.

        Returns
        -------
        KeypointsOnImage
            Keypoints container with updated coordinates.
            Note that the instance is also updated in-place.

        z Expected %d coordinates, got %d.)r   r   r   r#   r   r=   )r%   ZkpsoiZnb_points_expZ	kp_targetZ	kp_sourcer   r   r   invert_to_keypoints_on_image_I  s   


z.KeypointsOnImage.invert_to_keypoints_on_image_c                 C   s2   |du r| j dd }|du rt| j}t||S )a.  Create a shallow copy of the ``KeypointsOnImage`` object.

        Parameters
        ----------
        keypoints : None or list of imgaug.Keypoint, optional
            List of keypoints on the image.
            If ``None``, the instance's keypoints will be copied.

        shape : tuple of int, optional
            The shape of the image on which the keypoints are placed.
            If ``None``, the instance's shape will be copied.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Shallow copy.

        Nr   r   r=   r   r   r   r   r   rM   j  s
   

zKeypointsOnImage.copyc                 C   s4   |du rdd | j D }|du rt| j}t||S )a(  Create a deep copy of the ``KeypointsOnImage`` object.

        Parameters
        ----------
        keypoints : None or list of imgaug.Keypoint, optional
            List of keypoints on the image.
            If ``None``, the instance's keypoints will be copied.

        shape : tuple of int, optional
            The shape of the image on which the keypoints are placed.
            If ``None``, the instance's shape will be copied.

        Returns
        -------
        imgaug.augmentables.kps.KeypointsOnImage
            Deep copy.

        Nc                 S   s   g | ]}|  qS r   r_   )r`   r   r   r   r   rb     s    z-KeypointsOnImage.deepcopy.<locals>.<listcomp>r   r   r   r   r   r:     s
   

zKeypointsOnImage.deepcopyc                 C   s
   | j | S )zGet the keypoint(s) with given indices.

        Added in 0.4.0.

        Returns
        -------
        list of imgaug.augmentables.kps.Keypoint
            Keypoint(s) with given indices.

        r   )r%   indicesr   r   r   __getitem__     
zKeypointsOnImage.__getitem__c                 C   
   t | jS )a  Iterate over the keypoints in this container.

        Added in 0.4.0.

        Yields
        ------
        Keypoint
            A keypoint in this container.
            The order is identical to the order in the keypoint list
            provided upon class initialization.

        )iterr   r/   r   r   r   __iter__  s   
zKeypointsOnImage.__iter__c                 C   r   )zGet the number of items in this instance.

        Added in 0.4.0.

        Returns
        -------
        int
            Number of items in this instance.

        )r   r   r/   r   r   r   __len__  r   zKeypointsOnImage.__len__c                 C   rs   r!   rt   r/   r   r   r   rv     rw   zKeypointsOnImage.__repr__c                 C   s   dt | j| jf S )NzKeypointsOnImage(%s, shape=%s))rQ   r   r=   r/   r   r   r   ru     s   zKeypointsOnImage.__str__ry   rx   )r   rz   r{   )*r|   r}   r~   r   r&   r   r   setterr>   r?   r)   r   r   r]   r   r   r   r   rE   rG   r   
deprecatedr   r   staticmethodr   classmethodr   r   r   r   r   r   r   r   rM   r:   r   r   r   rv   ru   r   r   r   r   r   _  sj    





.






,/
V-i
!
r   )Nr   N)r   
__future__r   r   r   numpyr   Zscipy.spatial.distancer   Z	six.movesmovesr    r   r   baser   utilsr	   r
   r   r   objectr    r   r   r   r   r   <module>   s    
8    