
    0-Phr0                         d dl 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 ddd	Zd
ddZdddddZd ZdddddZddddZdS )    N)ndimage   )_supported_float_type)mean_squared_error)img_as_floatFmultichannelc                   |s| j         n	| j         dz
  }t          j        |d                              | j                  }d|                                |j        dz  <   ||                                z  }|rVt          j	        |           }t          | j        d                   D ]&}t          j        | d|f         |d          |d|f<   'nt          j        | |d          }|S )a  Replacing each pixel in ``image`` with the average of its neighbors.

    Parameters
    ----------
    image : ndarray
        Input data to be interpolated.
    multichannel : bool, optional
        Whether the last axis of the image is to be interpreted as multiple
        channels or another spatial dimension.

    Returns
    -------
    interp : ndarray
        Interpolated version of `image`.
       r   r   .mirror)mode)ndimndigenerate_binary_structureastypedtyperavelsizesumnp
zeros_likerangeshapeconvolve)imager	   spatialdimsconv_filterinterpis         _/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/skimage/restoration/j_invariant.py_interpolate_imager"      s      %1D%**ej1nK/Q??FFu{SSK12K(A-.;??$$$K Au%%u{2'' 	U 	UA \%Q-8TTTF36NN	U e[x@@@M       )stridec                    t          j        |ft          |           z            }t          fd|D                       }|S )a'  Generate slices of uniformly-spaced points in an array.

    Parameters
    ----------
    shape : tuple of int
        Shape of the mask.
    offset : int
        The offset of the grid of ones. Iterating over ``offset`` will cover
        the entire array. It should be between 0 and ``stride ** ndim``, not
        inclusive, where ``ndim = len(shape)``.
    stride : int, optional
        The spacing between ones, used in each dimension.

    Returns
    -------
    mask : ndarray
        The mask.

    Examples
    --------
    >>> shape = (4, 4)
    >>> array = np.zeros(shape, dtype=int)
    >>> grid_slice = _generate_grid_slice(shape, offset=0, stride=2)
    >>> array[grid_slice] = 1
    >>> print(array)
    [[1 0 1 0]
     [0 0 0 0]
     [1 0 1 0]
     [0 0 0 0]]

    Changing the offset moves the location of the 1s:

    >>> array = np.zeros(shape, dtype=int)
    >>> grid_slice = _generate_grid_slice(shape, offset=3, stride=2)
    >>> array[grid_slice] = 1
    >>> print(array)
    [[0 0 0 0]
     [0 1 0 1]
     [0 0 0 0]
     [0 1 0 1]]
    c              3   :   K   | ]}t          |d           V  d S )N)slice).0pr%   s     r!   	<genexpr>z'_generate_grid_slice.<locals>.<genexpr>U   s/      88Aq$''888888r#   )r   unravel_indexlentuple)r   offsetr%   phasesmasks     `  r!   _generate_grid_slicer2   *   sL    T fvi#e**&<==F888888888DKr#      )r%   masksdenoiser_kwargsc                    t                      t           j                  }                     |d           |i }|                    dd          du}t           |          }t          j                   }|5|s j        n	 j        dz
  z  }	 fdt          |	          D             }|D ]3}
 
                                }||
         ||
<    ||fi ||
         ||
<   4|S )a	  Apply a J-invariant version of a denoising function.

    Parameters
    ----------
    image : ndarray (M[, N[, ...]][, C]) of ints, uints or floats
        Input data to be denoised. `image` can be of any numeric type,
        but it is cast into a ndarray of floats (using `img_as_float`) for the
        computation of the denoised image.
    denoise_function : function
        Original denoising function.
    stride : int, optional
        Stride used in masking procedure that converts `denoise_function`
        to J-invariance.
    masks : list of ndarray, optional
        Set of masks to use for computing J-invariant output. If `None`,
        a full set of masks covering the image will be used.
    denoiser_kwargs:
        Keyword arguments passed to `denoise_function`.

    Returns
    -------
    output : ndarray
        Denoised image, of same shape as `image`.

    Notes
    -----
    A denoising function is J-invariant if the prediction it makes for each
    pixel does not depend on the value of that pixel in the original image.
    The prediction for each pixel may instead use all the relevant information
    contained in the rest of the image, which is typically quite significant.
    Any function can be converted into a J-invariant one using a simple masking
    procedure, as described in [1].

    The pixel-wise error of a J-invariant denoiser is uncorrelated to the noise,
    so long as the noise in each pixel is independent. Consequently, the average
    difference between the denoised image and the oisy image, the
    *self-supervised loss*, is the same as the difference between the denoised
    image and the original clean image, the *ground-truth loss* (up to a
    constant).

    This means that the best J-invariant denoiser for a given image can be found
    using the noisy data alone, by selecting the denoiser minimizing the self-
    supervised loss.

    References
    ----------
    .. [1] J. Batson & L. Royer. Noise2Self: Blind Denoising by Self-Supervision,
       International Conference on Machine Learning, p. 524-533 (2019).

    Examples
    --------
    >>> import skimage
    >>> from skimage.restoration import denoise_invariant, denoise_tv_chambolle
    >>> image = skimage.util.img_as_float(skimage.data.chelsea())
    >>> noisy = skimage.util.random_noise(image, var=0.2 ** 2)
    >>> denoised = denoise_invariant(noisy, denoise_function=denoise_tv_chambolle)
    F)copyNchannel_axisr   r   c              3   V   K   | ]#}t          j        d          |          V  $d S )Nr/   r%   )r2   r   )r)   idxr   r   r%   s     r!   r+   z$denoise_invariant.<locals>.<genexpr>   sQ       
 
 !\k\!:3vVVV
 
 
 
 
 
r#   )r   r   r   r   getr"   r   r   r   r   r7   )r   denoise_functionr%   r4   r5   float_dtyper	   r   outputn_masksr1   input_imager   s   ` `         @r!   denoise_invariantrB   Z   s4   x E (44KLL5L11E"&&~t<<DHLLAAAF]5!!F}(4Hejj%*q.+%
 
 
 
 
 
W~~
 
 

  N Njjll"4LD''GGGGMtMr#   c              #      K   |                                  }t          j        |                                  D ]!}t	          t          ||                    V  "dS )a  Utility function to convert parameter ranges to parameter combinations.

    Converts a dict of lists into a list of dicts whose values consist of the
    cartesian product of the values in the original dict.

    Parameters
    ----------
    dictionary : dict of lists
        Dictionary of lists to be multiplied.

    Yields
    ------
    selections : dicts of values
        Dicts containing individual combinations of the values in the input
        dict.
    N)keys	itertoolsproductvaluesdictzip)
dictionaryrD   elements      r!   _product_from_dictrL      se      " ??D$j&7&7&9&9: ' '3tW%%&&&&&&' 'r#   T)r%   approximate_lossextra_outputc                    t          | ||||          \  }}t          j        |          }||         }	t          j        t
          |||	          }
|r|
||ffS |
S )a$  Calibrate a denoising function and return optimal J-invariant version.

    The returned function is partially evaluated with optimal parameter values
    set for denoising the input image.

    Parameters
    ----------
    image : ndarray
        Input data to be denoised (converted using `img_as_float`).
    denoise_function : function
        Denoising function to be calibrated.
    denoise_parameters : dict of list
        Ranges of parameters for `denoise_function` to be calibrated over.
    stride : int, optional
        Stride used in masking procedure that converts `denoise_function`
        to J-invariance.
    approximate_loss : bool, optional
        Whether to approximate the self-supervised loss used to evaluate the
        denoiser by only computing it on one masked version of the image.
        If False, the runtime will be a factor of `stride**image.ndim` longer.
    extra_output : bool, optional
        If True, return parameters and losses in addition to the calibrated
        denoising function

    Returns
    -------
    best_denoise_function : function
        The optimal J-invariant version of `denoise_function`.

    If `extra_output` is True, the following tuple is also returned:

    (parameters_tested, losses) : tuple (list of dict, list of int)
        List of parameters tested for `denoise_function`, as a dictionary of
        kwargs
        Self-supervised loss for each set of parameters in `parameters_tested`.


    Notes
    -----

    The calibration procedure uses a self-supervised mean-square-error loss
    to evaluate the performance of J-invariant versions of `denoise_function`.
    The minimizer of the self-supervised loss is also the minimizer of the
    ground-truth loss (i.e., the true MSE error) [1]. The returned function
    can be used on the original noisy image, or other images with similar
    characteristics.

    Increasing the stride increases the performance of `best_denoise_function`
     at the expense of increasing its runtime. It has no effect on the runtime
     of the calibration.

    References
    ----------
    .. [1] J. Batson & L. Royer. Noise2Self: Blind Denoising by Self-Supervision,
           International Conference on Machine Learning, p. 524-533 (2019).

    Examples
    --------
    >>> from skimage import color, data
    >>> from skimage.restoration import denoise_tv_chambolle
    >>> import numpy as np
    >>> img = color.rgb2gray(data.astronaut()[:50, :50])
    >>> rng = np.random.default_rng()
    >>> noisy = img + 0.5 * img.std() * rng.standard_normal(img.shape)
    >>> parameters = {'weight': np.arange(0.01, 0.3, 0.02)}
    >>> denoising_function = calibrate_denoiser(noisy, denoise_tv_chambolle,
    ...                                         denoise_parameters=parameters)
    >>> denoised_img = denoising_function(img)

    )denoise_parametersr%   rM   )r=   r%   r5   )_calibrate_denoiser_searchr   argmin	functoolspartialrB   )r   r=   rP   r%   rM   rN   parameters_testedlossesr;   best_parametersbest_denoise_functions              r!   calibrate_denoiserrY      s    ^ !;-)! ! !v )F

C',O%-)'	    %$'8&&AAA$$r#   )r%   rM   c                   t          |           } t          t          |                    }g }|D ]}|                    dd          du}|s$t	          | |||          }	t          | |	          }
nj|s| j        n	| j        dz
  }||z  }t          | j        d|         |dz  |          }t	          | ||g|          }t          | |         ||                   }
|	                    |
           ||fS )a  Return a parameter search history with losses for a denoise function.

    Parameters
    ----------
    image : ndarray
        Input data to be denoised (converted using `img_as_float`).
    denoise_function : function
        Denoising function to be calibrated.
    denoise_parameters : dict of list
        Ranges of parameters for `denoise_function` to be calibrated over.
    stride : int, optional
        Stride used in masking procedure that converts `denoise_function`
        to J-invariance.
    approximate_loss : bool, optional
        Whether to approximate the self-supervised loss used to evaluate the
        denoiser by only computing it on one masked version of the image.
        If False, the runtime will be a factor of `stride**image.ndim` longer.

    Returns
    -------
    parameters_tested : list of dict
        List of parameters tested for `denoise_function`, as a dictionary of
        kwargs.
    losses : list of int
        Self-supervised loss for each set of parameters in `parameters_tested`.
    r8   N)r%   r5   r   r   r:   )r4   r5   )
r   listrL   r<   rB   r   r   r2   r   append)r   r=   rP   r%   rM   rU   rV   r5   r	   denoisedlossr   r@   r1   masked_denoiseds                  r!   rQ   rQ   /  s7   : E/0BCCDDF,  &**>4@@L 	J('  H &eX66DD,8L%**ej1nKk)G'L[L)'Q,v  D 0'v  O &eDk?43HIIDdf$$r#   )rE   rS   numpyr   scipyr   r   _shared.utilsr   metricsr   utilr   r"   r2   rB   rL   rY   rQ    r#   r!   <module>rf      s9                           1 1 1 1 1 1 ( ( ( ( ( (       /4     < 34 - - - - -b ()dU U U U Up' ' '6 d% d% d% d% d%P <=t7% 7% 7% 7% 7% 7% 7%r#   