o
    er                     @   s
  d Z ddlmZmZmZ ddlZddlZddl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 dd	lmZ G d
d dejZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZ dS )a   
Augmenters that are based on applying convolution kernels to images.

List of augmenters:

    * :class:`Convolve`
    * :class:`Sharpen`
    * :class:`Emboss`
    * :class:`EdgeDetect`
    * :class:`DirectedEdgeDetect`

For MotionBlur, see ``blur.py``.

    )print_functiondivisionabsolute_importN)_normalize_cv2_input_arr_   )meta   )
parameters)dtypesc                       s8   e Zd ZdZ			d
 fdd	Zdd Zdd	 Z  ZS )Convolvea*  
    Apply a convolution to input images.

    **Supported dtypes**:

        * ``uint8``: yes; fully tested
        * ``uint16``: yes; tested
        * ``uint32``: no (1)
        * ``uint64``: no (2)
        * ``int8``: yes; tested (3)
        * ``int16``: yes; tested
        * ``int32``: no (2)
        * ``int64``: no (2)
        * ``float16``: yes; tested (4)
        * ``float32``: yes; tested
        * ``float64``: yes; tested
        * ``float128``: no (1)
        * ``bool``: yes; tested (4)

        - (1) rejected by ``cv2.filter2D()``.
        - (2) causes error: cv2.error: OpenCV(3.4.2) (...)/filter.cpp:4487:
              error: (-213:The function/feature is not implemented)
              Unsupported combination of source format (=1), and destination
              format (=1) in function 'getLinearFilter'.
        - (3) mapped internally to ``int16``.
        - (4) mapped internally to ``float32``.

    Parameters
    ----------
    matrix : None or (H, W) ndarray or imgaug.parameters.StochasticParameter or callable, optional
        The weight matrix of the convolution kernel to apply.

            * If ``None``, the input images will not be changed.
            * If a 2D numpy array, that array will always be used for all
              images and channels as the kernel.
            * If a callable, that method will be called for each image
              via ``parameter(image, C, random_state)``. The function must
              either return a list of ``C`` matrices (i.e. one per channel)
              or a 2D numpy array (will be used for all channels) or a
              3D ``HxWxC`` numpy array. If a list is returned, each entry may
              be ``None``, which will result in no changes to the respective
              channel.

    seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
        See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.

    name : None or str, optional
        See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.

    random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
        Old name for parameter `seed`.
        Its usage will not yet cause a deprecation warning,
        but it is still recommended to use `seed` now.
        Outdated since 0.4.0.

    deterministic : bool, optional
        Deprecated since 0.4.0.
        See method ``to_deterministic()`` for an alternative and for
        details about what the "deterministic mode" actually does.

    Examples
    --------
    >>> import imgaug.augmenters as iaa
    >>> matrix = np.array([[0, -1, 0],
    >>>                    [-1, 4, -1],
    >>>                    [0, -1, 0]])
    >>> aug = iaa.Convolve(matrix=matrix)

    Convolves all input images with the kernel shown in the ``matrix``
    variable.

    >>> def gen_matrix(image, nb_channels, random_state):
    >>>     matrix_A = np.array([[0, -1, 0],
    >>>                          [-1, 4, -1],
    >>>                          [0, -1, 0]])
    >>>     matrix_B = np.array([[0, 1, 0],
    >>>                          [1, -4, 1],
    >>>                          [0, 1, 0]])
    >>>     if image.shape[0] % 2 == 0:
    >>>         return [matrix_A] * nb_channels
    >>>     else:
    >>>         return [matrix_B] * nb_channels
    >>> aug = iaa.Convolve(matrix=gen_matrix)

    Convolves images that have an even height with matrix A and images
    having an odd height with matrix B.

    N
deprecatedc                    s   t t| j||||d |d u rd | _d| _d S t|r4|jdks,J d|j|jf || _d| _d S t	|rA|| _d| _d S t
dt|f )N)seednamerandom_statedeterministicNoner   zNExpected convolution matrix to have exactly two dimensions, got %d (shape %s).constantfunctionzNExpected float, int, tuple/list with 2 entries or StochasticParameter. Got %s.)superr   __init__matrixmatrix_typeiais_np_arrayndimshapeZis_callable	Exceptiontype)selfr   r   r   r   r   	__class__ OD:\Projects\ConvertPro\env\Lib\site-packages\imgaug/augmenters/convolutional.pyr   {   s0   






zConvolve.__init__c                 C   s  |j d u r|S |j }tj|g dg d| d |t|}t|D ]\}}|j\}	}
}|jdkr2q"|j}|jj	dv rD|j
tjdd}n|jj	dkrR|j
tjdd}| jd	kr]d g| }nl| jd
kri| jg| }n`| jdkr| || ||| }t|r|jdkrt|dtjf dd|f}t|tot||k}t|o|jdko|jd |k}|s|sJ dt|f t|r|d}ntd|}t|D ]}|| d urtt|d|f d|| |d|f< q|j	dkr|dk}n|j	dv rt||}||j |< q"|S )N)boolZuint8Zuint16int8int16float16float32Zfloat64)Zuint32Zuint64Zuint128Zuint256Zint32Zint64Zint128Zint256Zfloat96Zfloat128Zfloat256)allowedZ
disallowedZ	augmenterr   )r#   r&   F)copyr$   r   r   r   r   .r      zCallable provided to Convole must return either a list of 2D matrices (one per image channel) or a 2D numpy array or a 3D numpy array where the last dimension's size matches the number of image channels. Got type %s.)r   r   r   zInvalid matrix typer#         ?)r$   r&   ) imagesiadtZgate_dtypesZ	duplicatelen	enumerater   sizedtyper   Zastypenpr'   r%   r   r   r   r   r   ZtileZnewaxis
isinstancelistr   Z	transposer   smxrangecv2Zfilter2Dr   Zrestore_dtypes_)r   batchr   parentshooksr-   Zrssiimage_height_widthnb_channelsZinput_dtypeZmatricesZis_valid_listZis_valid_arrayZ	image_augZchannelr!   r!   r"   _augment_batch_   sz   
	











zConvolve._augment_batch_c                 C   s   | j | jgS )z=See :func:`~imgaug.augmenters.meta.Augmenter.get_parameters`.)r   r   )r   r!   r!   r"   get_parameters   s   zConvolve.get_parameters)NNNr   r   )__name__
__module____qualname____doc__r   rA   rB   __classcell__r!   r!   r   r"   r   !   s    YWr   c                       (   e Zd ZdZ			d fdd	Z  ZS )	Sharpena  
    Sharpen images and alpha-blend the result with the original input images.

    **Supported dtypes**:

    See :class:`~imgaug.augmenters.convolutional.Convolve`.

    Parameters
    ----------
    alpha : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
        Blending factor of the sharpened image. At ``0.0``, only the original
        image is visible, at ``1.0`` only its sharpened version is visible.

            * If a number, exactly that value will always be used.
            * If a tuple ``(a, b)``, a random value will be sampled from the
              interval ``[a, b]`` per image.
            * If a list, a random value will be sampled from that list
              per image.
            * If a ``StochasticParameter``, a value will be sampled from that
              parameter per image.

    lightness : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
        Lightness/brightness of the sharped image.
        Sane values are somewhere in the interval ``[0.5, 2.0]``.
        The value ``0.0`` results in an edge map. Values higher than ``1.0``
        create bright images. Default value is ``1.0``.

            * If a number, exactly that value will always be used.
            * If a tuple ``(a, b)``, a random value will be sampled from the
              interval ``[a, b]`` per image.
            * If a list, a random value will be sampled from that list
              per image.
            * If a ``StochasticParameter``, a value will be sampled from that
              parameter per image.

    seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
        See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.

    name : None or str, optional
        See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.

    random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
        Old name for parameter `seed`.
        Its usage will not yet cause a deprecation warning,
        but it is still recommended to use `seed` now.
        Outdated since 0.4.0.

    deterministic : bool, optional
        Deprecated since 0.4.0.
        See method ``to_deterministic()`` for an alternative and for
        details about what the "deterministic mode" actually does.

    Examples
    --------
    >>> import imgaug.augmenters as iaa
    >>> aug = iaa.Sharpen(alpha=(0.0, 1.0))

    Sharpens input images and blends the sharpened image with the input image
    using a random blending factor between ``0%`` and ``100%`` (uniformly
    sampled).

    >>> aug = iaa.Sharpen(alpha=(0.0, 1.0), lightness=(0.75, 2.0))

    Sharpens input images with a variable `lightness` sampled uniformly from
    the interval ``[0.75, 2.0]`` and with a fully random blending factor
    (as in the above example).

            g?g?g333333?Nr   c           
         P   t j|ddddd}t j|ddddd}t||}	tt| j|	||||d d S )Nalphar         ?TZvalue_rangeZtuple_to_uniformZlist_to_choice	lightnessr   Nr   r   r   r   r   )iaphandle_continuous_param_SharpeningMatrixGeneratorr   rI   r   )
r   rN   rR   r   r   r   r   alpha_paramZlightness_param
matrix_genr   r!   r"   r   6     


zSharpen.__init__)rJ   rL   NNr   r   rC   rD   rE   rF   r   rG   r!   r!   r   r"   rI      s    DrI   c                   @      e Zd Zdd Zdd ZdS )rW   c                 C      || _ || _d S N)rN   rR   )r   rN   rR   r!   r!   r"   r   I     
z#_SharpeningMatrixGenerator.__init__c           	      C   s   | j j|d}d|  krdksn J d|f | jj|d}tjg dg dg dgtjd}tjg dd	d
| d	gg dgtjd}d| | ||  }|g| S )Nr   r   rP   <Expected 'alpha' to be in the interval [0.0, 1.0], got %.4f.r   r   r   r   r   r   r2   )r+   r+   r+   r+      r   )rN   draw_samplerR   r3   arrayr'   )	r   _imager@   r   alpha_sampleZlightness_samplematrix_nochangematrix_effectr   r!   r!   r"   __call__M  s4   

z#_SharpeningMatrixGenerator.__call__NrC   rD   rE   r   rl   r!   r!   r!   r"   rW   H      rW   c                       rH   )	Embossa  
    Emboss images and alpha-blend the result with the original input images.

    The embossed version pronounces highlights and shadows,
    letting the image look as if it was recreated on a metal plate ("embossed").

    **Supported dtypes**:

    See :class:`~imgaug.augmenters.convolutional.Convolve`.

    Parameters
    ----------
    alpha : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
        Blending factor of the embossed image. At ``0.0``, only the original
        image is visible, at ``1.0`` only its embossed version is visible.

            * If a number, exactly that value will always be used.
            * If a tuple ``(a, b)``, a random value will be sampled from the
              interval ``[a, b]`` per image.
            * If a list, a random value will be sampled from that list
              per image.
            * If a ``StochasticParameter``, a value will be sampled from that
              parameter per image.

    strength : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
        Parameter that controls the strength of the embossing.
        Sane values are somewhere in the interval ``[0.0, 2.0]`` with ``1.0``
        being the standard embossing effect. Default value is ``1.0``.

            * If a number, exactly that value will always be used.
            * If a tuple ``(a, b)``, a random value will be sampled from the
              interval ``[a, b]`` per image.
            * If a list, then a random value will be sampled from that list
              per image.
            * If a ``StochasticParameter``, a value will be sampled from the
              parameter per image.

    seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
        See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.

    name : None or str, optional
        See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.

    random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
        Old name for parameter `seed`.
        Its usage will not yet cause a deprecation warning,
        but it is still recommended to use `seed` now.
        Outdated since 0.4.0.

    deterministic : bool, optional
        Deprecated since 0.4.0.
        See method ``to_deterministic()`` for an alternative and for
        details about what the "deterministic mode" actually does.

    Examples
    --------
    >>> import imgaug.augmenters as iaa
    >>> aug = iaa.Emboss(alpha=(0.0, 1.0), strength=(0.5, 1.5))

    Emboss an image with a strength sampled uniformly from the interval
    ``[0.5, 1.5]`` and alpha-blend the result with the original input image
    using a random blending factor between ``0%`` and ``100%``.

    rK   rP   g      ?rP   Nr   c           
         rM   )NrN   rO   TrQ   strengthrS   rT   )rU   rV   _EmbossMatrixGeneratorr   ro   r   )
r   rN   rr   r   r   r   r   rX   Zstrength_paramrY   r   r!   r"   r     rZ   zEmboss.__init__)rp   rq   NNr   r   r[   r!   r!   r   r"   ro   d  s    @ro   c                   @   r\   )rs   c                 C   r]   r^   )rN   rr   )r   rN   rr   r!   r!   r"   r     r_   z_EmbossMatrixGenerator.__init__c           	      C   s   | j j|d}d|  krdksn J d|f | jj|d}tjg dg dg dgtjd}tjd| d| dgd| d	d| gdd| d	| ggtjd}d	| | ||  }|g| S )
Nr`   r   rP   ra   rb   rc   rd   r+   r   )rN   rf   rr   r3   rg   r'   )	r   rh   r@   r   ri   Zstrength_samplerj   rk   r   r!   r!   r"   rl     s4   

z_EmbossMatrixGenerator.__call__Nrm   r!   r!   r!   r"   rs     rn   rs   c                       s(   e Zd ZdZ			d fdd	Z  ZS )
EdgeDetecta  
    Generate a black & white edge image and alpha-blend it with the input image.

    **Supported dtypes**:

    See :class:`~imgaug.augmenters.convolutional.Convolve`.

    Parameters
    ----------
    alpha : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
        Blending factor of the edge image. At ``0.0``, only the original
        image is visible, at ``1.0`` only the edge image is visible.

            * If a number, exactly that value will always be used.
            * If a tuple ``(a, b)``, a random value will be sampled from the
              interval ``[a, b]`` per image.
            * If a list, a random value will be sampled from that list
              per image.
            * If a ``StochasticParameter``, a value will be sampled from that
              parameter per image.

    seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
        See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.

    name : None or str, optional
        See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.

    random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
        Old name for parameter `seed`.
        Its usage will not yet cause a deprecation warning,
        but it is still recommended to use `seed` now.
        Outdated since 0.4.0.

    deterministic : bool, optional
        Deprecated since 0.4.0.
        See method ``to_deterministic()`` for an alternative and for
        details about what the "deterministic mode" actually does.

    Examples
    --------
    >>> import imgaug.augmenters as iaa
    >>> aug = iaa.EdgeDetect(alpha=(0.0, 1.0))

    Detect edges in an image, mark them as black (non-edge) and white (edges)
    and alpha-blend the result with the original input image using a random
    blending factor between ``0%`` and ``100%``.

    rK   g      ?Nr   c                    s:   t j|ddddd}t|}tt| j|||||d d S )NrN   rO   TrQ   rT   )rU   rV   _EdgeDetectMatrixGeneratorr   rt   r   )r   rN   r   r   r   r   rX   rY   r   r!   r"   r     s   

zEdgeDetect.__init__)ru   NNr   r   r[   r!   r!   r   r"   rt     s    0rt   c                   @   r\   )rv   c                 C   s
   || _ d S r^   )rN   )r   rN   r!   r!   r"   r     s   
z#_EdgeDetectMatrixGenerator.__init__c                 C   s   | j j|d}d|  krdksn J d|f tjg dg dg dgtjd}tjg dg dg dgtjd}d	| | ||  }|g| S )
Nr`   r   rP   ra   rb   rc   rd   )r   r   r   )rN   rf   r3   rg   r'   )r   rh   r@   r   ri   rj   rk   r   r!   r!   r"   rl     s2   

z#_EdgeDetectMatrixGenerator.__call__Nrm   r!   r!   r!   r"   rv     s    rv   c                       rH   )	DirectedEdgeDetecta)  
    Detect edges from specified angles and alpha-blend with the input image.

    This augmenter first detects edges along a certain angle.
    Usually, edges are detected in x- or y-direction, while here the edge
    detection kernel is rotated to match a specified angle.
    The result of applying the kernel is a black (non-edges) and white (edges)
    image. That image is alpha-blended with the input image.

    **Supported dtypes**:

    See :class:`~imgaug.augmenters.convolutional.Convolve`.

    Parameters
    ----------
    alpha : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
        Blending factor of the edge image. At ``0.0``, only the original
        image is visible, at ``1.0`` only the edge image is visible.

            * If a number, exactly that value will always be used.
            * If a tuple ``(a, b)``, a random value will be sampled from the
              interval ``[a, b]`` per image.
            * If a list, a random value will be sampled from that list
              per image.
            * If a ``StochasticParameter``, a value will be sampled from that
              parameter per image.

    direction : number or tuple of number or list of number or imgaug.parameters.StochasticParameter, optional
        Angle (in degrees) of edges to pronounce, where ``0`` represents
        ``0`` degrees and ``1.0`` represents 360 degrees (both clockwise,
        starting at the top). Default value is ``(0.0, 1.0)``, i.e. pick a
        random angle per image.

            * If a number, exactly that value will always be used.
            * If a tuple ``(a, b)``, a random value will be sampled from the
              interval ``[a, b]`` will be sampled per image.
            * If a list, then a random value will be sampled from that list
              per image.
            * If a ``StochasticParameter``, a value will be sampled from the
              parameter per image.

    seed : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
        See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.

    name : None or str, optional
        See :func:`~imgaug.augmenters.meta.Augmenter.__init__`.

    random_state : None or int or imgaug.random.RNG or numpy.random.Generator or numpy.random.BitGenerator or numpy.random.SeedSequence or numpy.random.RandomState, optional
        Old name for parameter `seed`.
        Its usage will not yet cause a deprecation warning,
        but it is still recommended to use `seed` now.
        Outdated since 0.4.0.

    deterministic : bool, optional
        Deprecated since 0.4.0.
        See method ``to_deterministic()`` for an alternative and for
        details about what the "deterministic mode" actually does.

    Examples
    --------
    >>> import imgaug.augmenters as iaa
    >>> aug = iaa.DirectedEdgeDetect(alpha=1.0, direction=0)

    Turn input images into edge images in which edges are detected from
    the top side of the image (i.e. the top sides of horizontal edges are
    part of the edge image, while vertical edges are ignored).

    >>> aug = iaa.DirectedEdgeDetect(alpha=1.0, direction=90/360)

    Same as before, but edges are detected from the right. Horizontal edges
    are now ignored.

    >>> aug = iaa.DirectedEdgeDetect(alpha=1.0, direction=(0.0, 1.0))

    Same as before, but edges are detected from a random angle sampled
    uniformly from the interval ``[0deg, 360deg]``.

    >>> aug = iaa.DirectedEdgeDetect(alpha=(0.0, 0.3), direction=0)

    Similar to the previous examples, but here the edge image is alpha-blended
    with the input image. The result is a mixture between the edge image and
    the input image. The blending factor is randomly sampled between ``0%``
    and ``30%``.

    ru   rp   Nr   c           
         sP   t j|ddddd}t j|dd ddd}t||}	tt| j|	||||d d S )NrN   rO   TrQ   	directionrT   )rU   rV   "_DirectedEdgeDetectMatrixGeneratorr   rx   r   )
r   rN   ry   r   r   r   r   rX   Zdirection_paramrY   r   r!   r"   r     s    

zDirectedEdgeDetect.__init__)ru   rp   NNr   r   r[   r!   r!   r   r"   rx   5  s    Urx   c                   @   r\   )rz   c                 C   r]   r^   )rN   ry   )r   rN   ry   r!   r!   r"   r     r_   z+_DirectedEdgeDetectMatrixGenerator.__init__c                 C   s  | j j|d}d|  krdksn J d|f | jj|d}t|d d }t|}t|dtj  }t|dtj  }	t	||	g}
tj	g dg dg dgtj
d}tg d	g d	D ].\}}	||	fd
krt	||	g}tt||
}|d }d| d }|||	d |d f< qc|t| }|d }d|d< tj	g dg dg dgtj
d}d| | ||  }|g| S )Nr`   r   rP   ra   ih  r,   rb   rd   )r+   r   r   )r   r      r      r+   )r   r   rc   )rN   rf   ry   intr3   Zdeg2radcospisinrg   r'   	itertoolsproductZrad2degr   Zangle_between_vectorssum)r   rh   r@   r   ri   Zdirection_sampledegZradxyZdirection_vectorrk   Zcell_vectorZdistance_degZdistanceZ
similarityrj   r   r!   r!   r"   rl     s\   


z+_DirectedEdgeDetectMatrixGenerator.__call__Nrm   r!   r!   r!   r"   rz     rn   rz   )!rF   
__future__r   r   r   r   numpyr3   r8   Z	six.movesmovesr6   Zimgaugr   Zimgaug.imgaugr    r   r	   rU   r
   r.   Z	Augmenterr   rI   objectrW   ro   rs   rt   rv   rx   rz   r!   r!   r!   r"   <module>   s*     QWS@ i