U Ph(@s:dZddlmZddlmZddlmZmZmZddl m Z ddl m Z ddl mZddlZddlZdd lmZdd lmZmZdd lmZdd lmZdd lmZmZddlmZm Z m!Z!m"Z"ddl#m$Z$m%Z%ddl&m'Z'm(Z(m)Z)m*Z*m+Z+ddl,m-Z-m.Z.m/Z/ddl0m1Z1ddl2m3Z3m4Z4m5Z5m6Z6ddl7m8Z8m9Z9ddl:m;Z;mZ>e9dde8\Z?Z@ddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;dd?g(ZAGd@dde$ZBGdAdde$ZCGdBdde%ZDGdCdde$ZEGdDdde%ZFGdEdde$ZGGdFdde%ZHGdGd!d!e%ZIGdHd"d"e$ZJGdId d e$ZKGdJdde$ZLGdKd#d#e%ZMGdLd$d$e%ZNGdMd%d%e%ZOGdNd&d&e%ZPGdOd'd'e%ZQGdPd(d(e$ZRGdQd)d)e%ZSGdRd*d*e%ZTGdSd,d,e%ZUGdTd+d+e%ZVGdUd-d-e%ZWGdVd.d.e%ZXGdWd/d/e$ZYGdXd0d0e%ZZGdYd1d1e$Z[GdZd2d2e$Z\Gd[d3d3e%e'Z]Gd\d4d4e$Z^Gd]d5d5e%e'Z_Gd^d6d6e$e'Z`Gd_d7d7e$ZaGd`d8d8eaZbGdad9d9eaZcGdbd:d:e%ZdGdcd;d;e$ZeGddd<dd>e%ZhGdgd?d?e%ZidS)hz@ A collection of "vanilla" transforms for intensity adjustment. ) annotations)abstractmethod)CallableIterableSequence)partial)Any)warnN) DtypeLike)NdarrayOrTensor NdarrayTensor)get_track_meta)UltrasoundConfidenceMap)get_random_patchget_valid_patch_size)GaussianFilterHilbertTransform MedianFilterSavitzkyGolayFilter)RandomizableTransform Transform)Fourier equalize_hist is_positive rescale_array soft_clip)clip percentilewhere)TransformBackends) ensure_tupleensure_tuple_repensure_tuple_sizefall_back_tuple) min_versionoptional_import)convert_data_typeconvert_to_dst_typeconvert_to_tensorget_equivalent_dtypeskimagez0.19.0RandGaussianNoiseRandRicianNoiseShiftIntensityRandShiftIntensityStdShiftIntensityRandStdShiftIntensity RandBiasFieldScaleIntensityRandScaleIntensityScaleIntensityFixedMeanRandScaleIntensityFixedMeanNormalizeIntensityThresholdIntensityScaleIntensityRangeClipIntensityPercentilesAdjustContrastRandAdjustContrastScaleIntensityRangePercentiles MaskIntensityDetectEnvelopeSavitzkyGolaySmooth MedianSmoothGaussianSmoothRandGaussianSmoothGaussianSharpenRandGaussianSharpenRandHistogramShift GibbsNoiseRandGibbsNoiseKSpaceSpikeNoiseRandKSpaceSpikeNoiseRandCoarseTransformRandCoarseDropoutRandCoarseShuffleHistogramNormalizeIntensityRemapRandIntensityRemapForegroundMaskComputeHoVerMaps UltrasoundConfidenceMapTransformcsteZdZdZejejgZdddej dfddddddd d d Z dd dddfdd Z dd ddd dddZ Z S)r+u Add Gaussian noise to image. Args: prob: Probability to add Gaussian noise. mean: Mean or “centre” of the distribution. std: Standard deviation (spread) of distribution. dtype: output data type, if None, same as input image. defaults to float32. sample_std: If True, sample the spread of the Gaussian distribution uniformly from 0 to std. 皙?Tfloatr boolNone)probmeanstddtype sample_stdreturncCs.t||||_||_||_d|_||_dSN)r__init__rYrZr[noiser\)selfrXrYrZr[r\rbU/home/dell461/cl/sdc2/HISourceFinder-master-l/src/monai/transforms/intensity/array.pyr_es  zRandGaussianNoise.__init__Nr float | None)imgrYr]csltd|jsdS|jr,|jd|jn|j}|jj|dkrF|jn|||j d}t ||j d^|_ }dS)Nrsizer[) super randomize _do_transformr\RuniformrZnormalrYshaper&r[r`)rarerYrZr`_ __class__rbrcrjts  "zRandGaussianNoise.randomize)rerYrjr]cCstt|td}|r.|j||dkr&|jn|d|js8|S|jdkrJtdt||jd^}}t |j|^}}||S)/ Apply the transform to `img`.  track_metaN)rerY-please call the `randomize()` function first.rh) r(r rjrYrkr` RuntimeErrorr&r[r')rarerYrjrpr`rbrbrc__call__}s zRandGaussianNoise.__call__)N)NT__name__ __module__ __qualname____doc__rTORCHNUMPYbackendnpfloat32r_rjrx __classcell__rbrbrqrcr+Vs  c sxeZdZdZejejgZddddddej fdddd d d d d d d dZ ddddddZ ddd ddfdd Z Z S)r,a Add Rician noise to image. Rician noise in MRI is the result of performing a magnitude operation on complex data with Gaussian noise of the same variance in both channels, as described in `Noise in Magnitude Magnetic Resonance Images `_. This transform is adapted from `DIPY `_. See also: `The rician distribution of noisy mri data `_. Args: prob: Probability to add Rician noise. mean: Mean or "centre" of the Gaussian distributions sampled to make up the Rician noise. std: Standard deviation (spread) of the Gaussian distributions sampled to make up the Rician noise. channel_wise: If True, treats each channel of the image separately. relative: If True, the spread of the sampled Gaussian distributions will be std times the standard deviation of the image or channel's intensity histogram. sample_std: If True, sample the spread of the Gaussian distributions uniformly from 0 to std. dtype: output data type, if None, same as input image. defaults to float32. rSrT?FTrUSequence[float] | floatrVr rW)rXrYrZ channel_wiserelativer\r[r]cCsBt||||_||_||_||_||_||_||_||dSr^) rr_rXrYrZrrr\r[)rarXrYrZrrr\r[rbrbrcr_s zRandRicianNoise.__init__r )rerYrZc Cst|jtj}|j}|jr(|jd|n|}|jj|||dj |dd|_ |jj|||dj |dd|_ t |t jrt j|j |jd}t j|j |jd}t ||d|dSt||j d|j dS)NrrfFcopydevice)r)r[rndarrayror\rlrmrnastypeZ_noise1Z_noise2 isinstancetorchTensortensorrsqrt) rarerYrZZdtype_npZim_shape_stdn1n2rbrbrc _add_noises zRandRicianNoise._add_noisererjr]cs<t|t|jd}|r"td|js,|S|jrt|jt |}t|j t |}t |D]:\}}|j ||||j r||| n||d||<qZnt|jttfstdt|jdt|j ttfstdt|j d|j r|j | n|j }t|ttfs&tdt|d|j ||j|d}|S)rsrur[N)rYrZz;If channel_wise is False, mean must be a float or int, got .z:If channel_wise is False, std must be a float or int, got z'std must be a float or int number, got )r(r r[rirjrkrr!rYlenrZ enumeraterrrintrUrwtypeitem)rarerj_meanridrZrqrbrcrxs& 6zRandRicianNoise.__call__)T)rzr{r|r}rr~rrrrr_rrxrrbrbrqrcr,s  c@sDeZdZdZejejgZdddddddZdd d d d d dZ d S)r-aq Shift intensity uniformly for the entire image with specified `offset`. Args: offset: offset value to shift the intensity of image. safe: if `True`, then do safe dtype convert when intensity overflow. default to `False`. E.g., `[256, -12]` -> `[array(0), array(244)]`. If `True`, then `[256, -12]` -> `[array(255), array(0)]`. FrUrVrW)offsetsafer]cCs||_||_dSr^)rr)rarrrbrbrcr_szShiftIntensity.__init__Nr rd)rerr]cCsBt|td}|dkr|jn|}||}t||j|jd^}}|S)rsrtN)datar[r)r(r rr&r[r)rareroutrprbrbrcrxs zShiftIntensity.__call__)F)N rzr{r|r}rr~rrr_rxrbrbrbrcr-s csdeZdZdZejejgZdddddddd d Zdd dd fdd Z ddddddddZ Z S)r.z? Randomly shift intensity with randomly picked offset. FrStuple[float, float] | floatrVrUrW)offsetsrrXrr]cCst||t|ttfr6t| |t| |f|_n0t|dkrTt d|dnt|t|f|_|jd|_ ||_ t |j ||_ dS)a Args: offsets: offset range to randomly shift. if single number, offset value is picked from (-offsets, offsets). safe: if `True`, then do safe dtype convert when intensity overflow. default to `False`. E.g., `[256, -12]` -> `[array(0), array(244)]`. If `True`, then `[256, -12]` -> `[array(255), array(0)]`. prob: probability of shift. channel_wise: if True, shift intensity on each channel separately. For each channel, a random offset will be chosen. Please ensure that the first dimension represents the channel of the image if True. rz3offsets should be a number or pair of numbers, got rrN)rr_rrrUminmaxrr ValueError_offsetrr-_shifter)rarrrXrrbrbrcr_ s   zRandShiftIntensity.__init__N Any | Nonerr]cs^tdjsdSjr<fddt|jdD_njjj dj dd_dS)Ncs(g|] }jjjdjddqSrlowhigh)rlrmr.0rprarbrc )sz0RandShiftIntensity.randomize..rrr) rirjrkrrangerorrlrmrrarrqrrcrj$s   zRandShiftIntensity.randomizeTr rd)refactorrjr]c Cst|td}|r|||js&|S|jrg}t|D]:\}}|||dkrX|j|n |j||}||q8t |}n |||dkr|jn|j|}|S)a  Apply the transform to `img`. Args: img: input image to shift intensity. factor: a factor to multiply the random offset, then shift. can be some image specific value at runtime, like: max(img), etc. rtN) r(r rjrkrrrrappendrstack) rarerrjrrr out_channelretrbrbrcrx-s  (   zRandShiftIntensity.__call__)FrSF)N)NT) rzr{r|r}rr~rrr_rjrxrrbrbrqrcr.s  c@s\eZdZdZejejgZddej fdddddddd Z d d d d d Z d d d ddZ dS)r/a Shift intensity for the image with a factor and the standard deviation of the image by: ``v = v + factor * std(v)``. This transform can focus on only non-zero values or the entire image, and can also calculate the std on each channel separately. Args: factor: factor shift by ``v = v + factor * std(v)``. nonzero: whether only count non-zero values. channel_wise: if True, calculate on each channel separately. Please ensure that the first dimension represents the channel of the image if True. dtype: output data type, if None, same as input image. defaults to float32. FrUrVr rW)rnonzerorr[r]cCs||_||_||_||_dSr^rrrr[)rarrrr[rbrbrcr_[szStdShiftIntensity.__init__r rer]cCsxt|tjr"tj}ttjdd}n tj}tj}|jr<|dkn ||jt d}| rt|j |||}|||||<|S)NFunbiasedrrh) rrronesrrZrrrorVanyr)rarerrZslicesrrbrbrc _stdshiftcs zStdShiftIntensity._stdshiftcCsHt|t|jd}|jr:t|D]\}}||||<q n ||}|S)rsr)r(r r[rrr)rarerrrbrbrcrxss  zStdShiftIntensity.__call__N) rzr{r|r}rr~rrrrr_rrxrbrbrbrcr/Js csneZdZdZejejgZdddej fddddddd d d Z dd ddfdd Z dddddddZ Z S)r0z Shift intensity for the image with a factor and the standard deviation of the image by: ``v = v + factor * std(v)`` where the `factor` is randomly picked. rSFrrUrVr rW)factorsrXrrr[r]cCst||t|ttfr6t| |t| |f|_n0t|dkrTt d|dnt|t|f|_|jd|_ ||_ ||_ ||_ dS)a Args: factors: if tuple, the randomly picked range is (min(factors), max(factors)). If single number, the range is (-factors, factors). prob: probability of std shift. nonzero: whether only count non-zero values. channel_wise: if True, calculate on each channel separately. dtype: output data type, if None, same as input image. defaults to float32. r3factors should be a number or pair of numbers, got rrN)rr_rrrUrrrrrrrrr[)rarrXrrr[rbrbrcr_s   zRandStdShiftIntensity.__init__Nrrcs8td|jsdS|jj|jd|jdd|_dSNrrrrirjrkrlrmrrrrqrbrcrjs zRandStdShiftIntensity.randomizeTr rcCsJt|t|jd}|r||js(|St|j|j|j|jd}||dS)rsrrre) r(r r[rjrkr/rrr)rarerjshifterrbrbrcrxszRandStdShiftIntensity.__call__)N)Tryrbrbrqrcr0s c@sReZdZdZejejgZddddej fdddddd d d d Z d d dddZ dS)r2z Scale the intensity of input image to the given value range (minv, maxv). If `minv` and `maxv` not provided, use `factor` to scale image by ``v = v * (1 + factor)``. rTrNFrdrVr rW)minvmaxvrrr[r]cCs"||_||_||_||_||_dS)a Args: minv: minimum value of output data. maxv: maximum value of output data. factor: factor scale by ``v = v * (1 + factor)``. In order to use this parameter, please set both `minv` and `maxv` into None. channel_wise: if True, scale on each channel separately. Please ensure that the first dimension represents the channel of the image if True. dtype: output data type, if None, same as input image. defaults to float32. N)rrrrr[)rarrrrr[rbrbrcr_s zScaleIntensity.__init__r rcst|td}t|dd}jdk s.jdk rjjrRfdd|D}t|}qt|jjjd}nj dk r|dj n|}t ||jp|jdd }|S) z Apply the transform to `img`. Raises: ValueError: When ``self.minv=None`` or ``self.maxv=None`` and ``self.factor=None``. Incompatible values. rtFNcs"g|]}t|jjjdqS)rh)rrrr[rrrrbrcrsz+ScaleIntensity.__call__..rhrdstr[r) r(r rrrrrrr[rr')rareimg_trrrbrrcrxs  zScaleIntensity.__call__ rzr{r|r}rr~rrrrr_rxrbrbrbrcr2s c@sTeZdZdZejejgZddddej fddddddd d d Z dd d dddZ d S)r4z Scale the intensity of input image by ``v = v * (1 + factor)``, then shift the output so that the output image has the same mean as the input. rFTrUrVr rW)rpreserve_range fixed_meanrr[r]cCs"||_||_||_||_||_dS)a Args: factor: factor scale by ``v = v * (1 + factor)``. preserve_range: clips the output array/tensor to the range of the input array/tensor fixed_mean: subtract the mean intensity before scaling with `factor`, then add the same value after scaling to ensure that the output has the same mean as the input. channel_wise: if True, scale on each channel separately. `preserve_range` and `fixed_mean` are also applied on each channel separately if `channel_wise` is True. Please ensure that the first dimension represents the channel of the image if True. dtype: output data type, if None, same as input image. defaults to float32. N)rrrrr[)rarrrrr[rbrbrcr_s z ScaleIntensityFixedMean.__init__Nr rc Cs(|dk r |n|j}t|td}t|dd}|jrg}|D]f}|jrT|}|}|jrj|}||}|d|} |jr| |} |jrt | ||} | | q:t |} nZ|jr|}|}|jr|}||}|d|} |jr| |} |jrt | ||} t | ||jp|jdd} | S)z Apply the transform to `img`. Args: img: the input tensor/array factor: factor scale by ``v = v * (1 + factor)`` NrtFrrr)rr(r rrrrrrYrrrrr'r[) rarerrrrZclip_minZclip_maxmnrrrbrbrcrxs@        z ScaleIntensityFixedMean.__call__)Nrrbrbrbrcr4s csjeZdZdZejZddddejfddddd d d d d Zddd dfdd Z dddddddZ Z S)r5a Randomly scale the intensity of input image by ``v = v * (1 + factor)`` where the `factor` is randomly picked. Subtract the mean intensity before scaling with `factor`, then add the same value after scaling to ensure that the output has the same mean as the input. rSrTFrUrrVr rW)rXrrrr[r]cCst||t|ttfr6t| |t| |f|_n(t|dkrLt dnt|t|f|_|jd|_ ||_ ||_ ||_ t|j |j |j |j d|_dS)aQ Args: factors: factor range to randomly scale by ``v = v * (1 + factor)``. if single number, factor value is picked from (-factors, factors). preserve_range: clips the output array/tensor to the range of the input array/tensor fixed_mean: subtract the mean intensity before scaling with `factor`, then add the same value after scaling to ensure that the output has the same mean as the input. channel_wise: if True, scale on each channel separately. `preserve_range` and `fixed_mean` are also applied on each channel separately if `channel_wise` is True. Please ensure that the first dimension represents the channel of the image if True. dtype: output data type, if None, same as input image. defaults to float32. rz.factors should be a number or pair of numbers.r)rrrr[N)rr_rrrUrrrrrrrrr[r4scaler)rarXrrrr[rbrbrcr_Vs     z$RandScaleIntensityFixedMean.__init__Nrrcs8td|jsdS|jj|jd|jdd|_dSrrrrqrbrcrj{s z%RandScaleIntensityFixedMean.randomizer rcCs@t|td}|r||js2t||jddS|||jS)rsrtrhr)r(r rjrkr&r[rrrarerjrbrbrcrxs z$RandScaleIntensityFixedMean.__call__)N)T) rzr{r|r}r4rrrr_rjrxrrbrbrqrcr5Ms%csdeZdZdZejZddejfdddddd d d Zdd ddfdd Z dddddddZ Z S)r3z| Randomly scale the intensity of input image by ``v = v * (1 + factor)`` where the `factor` is randomly picked. rSFrrUrVr rW)rrXrr[r]cCst||t|ttfr6t| |t| |f|_n0t|dkrTt d|dnt|t|f|_|jd|_ ||_ ||_ dS)a Args: factors: factor range to randomly scale by ``v = v * (1 + factor)``. if single number, factor value is picked from (-factors, factors). prob: probability of scale. channel_wise: if True, scale on each channel separately. Please ensure that the first dimension represents the channel of the image if True. dtype: output data type, if None, same as input image. defaults to float32. rrrrN) rr_rrrUrrrrrrrr[)rarrXrr[rbrbrcr_s   zRandScaleIntensity.__init__Nrrcs^tdjsdSjr<fddt|jdD_njjj dj dd_dS)Ncs(g|] }jjjdjddqSr)rlrmrrrrbrcrsz0RandScaleIntensity.randomize..rrr) rirjrkrrrorrlrmrrrqrrcrjs   zRandScaleIntensity.randomizeTr rcCst|td}|r|||js4t||jddS|jrg}t|D].\}}tdd|j ||jd|}| |qFt |}ntdd|j |jd|}|S)rsrtrhrN)rrrr[) r(r rjrkr&r[rrr2rrrr)rarerjrrrrrrbrbrcrxs   zRandScaleIntensity.__call__)N)T) rzr{r|r}r2rrrr_rjrxrrbrbrqrcr3s csxeZdZdZejgZddejdfddddd d d d Z d dddddZ d d dfdd Z dddddddZ Z S)r1a Random bias field augmentation for MR images. The bias field is considered as a linear combination of smoothly varying basis (polynomial) functions, as described in `Automated Model-Based Tissue Classification of MR Images of the Brain `_. This implementation adapted from `NiftyNet `_. Referred to `Longitudinal segmentation of age-related white matter hyperintensities `_. Args: degree: degree of freedom of the polynomials. The value should be no less than 1. Defaults to 3. coeff_range: range of the random coefficients. Defaults to (0.0, 0.1). dtype: output data type, if None, same as input image. defaults to float32. prob: probability to do random bias field. )rTrSrSrtuple[float, float]r rUrW)degree coeff_ranger[rXr]cCsBt|||dkr$td|d||_||_||_dg|_dS)Nrz%degree should be no less than 1, got rr)rr_rrrr[_coeff)rarrr[rXrbrbrcr_s zRandBiasField.__init__ Sequence[int]zSequence[float] spatial_shapercoeffc CsFt|}t|df|}dd|D}|dkr^||t|d<tjj|d|d|S|dkr:dddgg}t|dD]D}t|d|D].} t|d|| D]} ||| | gqqqt|dkr|dd}t |} ||| dddf| dddf| dddff<tjj |d|d|d|St ddS) zC products of polynomials as bias field estimations rcSs g|]}tjdd|tjdqS)rrh)rlinspacer)rdimrbrbrcrsz8RandBiasField._generate_random_field..rrrNzonly supports 2D or 3D fields) rrzeros tril_indices polynomiallegendre leggrid2drrr leggrid3dNotImplementedError) rarrrrankZ coeff_matcoordsptsrjkZnp_ptsrbrbrc_generate_random_fields$     2 z$RandBiasField._generate_random_fieldimg_sizer]cs^tdjsdSttfddtdt|dD}jj j |f _ dS)Ncsg|]}j||qSrb)rrrrrbrcrsz+RandBiasField.randomize..r) rirjrkrrprodrrrlrmrtolistr)rarZn_coeffrqrrcrjs  *zRandBiasField.randomizeTr rVrcst|td}|r(j|jdddjs2|S|j^}tjfddt|Ddd}t|tj ^}}|t |}t ||j p|j d ^}}|S) rsrtrN)rcs g|]}jjjdqS)r)rrrrrarrbrcr$sz*RandBiasField.__call__..raxissrcrr[) r(r rjrorkrrrr&rexpr'r[)rarerj num_channelsZ _bias_fieldsimg_nprprrbrrcrxs   zRandBiasField.__call__)T)rzr{r|r}rrrrrr_rrjrxrrbrbrqrcr1sc@s|eZdZdZejejgZddddej fdddddddd d Z e d d Z e d dZ ddddddZdddddZdS)r6a Normalize input based on the `subtrahend` and `divisor`: `(img - subtrahend) / divisor`. Use calculated mean or std value of the input image if no `subtrahend` or `divisor` provided. This transform can normalize only non-zero values or entire image, and can also calculate mean and std on each channel separately. When `channel_wise` is True, the first dimension of `subtrahend` and `divisor` should be the number of image channels if they are not None. Args: subtrahend: the amount to subtract by (usually the mean). divisor: the amount to divide by (usually the standard deviation). nonzero: whether only normalize non-zero values. channel_wise: if True, calculate on each channel separately, otherwise, calculate on the entire image directly. default to False. dtype: output data type, if None, same as input image. defaults to float32. NFz!Sequence | NdarrayOrTensor | NonerVr rW) subtrahenddivisorrrr[r]cCs"||_||_||_||_||_dSr^)rrrrr[)rarrrrr[rbrbrcr_Ds zNormalizeIntensity.__init__cCs<t|tjrt|St|}|dkr8|S|S)Nr)rrrrYrrUnumelrxrbrbrcrRs  zNormalizeIntensity._meancCs@t|tjrt|Stj|dd}|dkr<|S|S)NFrr)rrrrZrrUrrrrbrbrcrYs  zNormalizeIntensity._stdr rc Cst|tjd^}}|jr6|dk}||}|s>|Snd}|}|dk rJ|n||}t|tjtj frt ||^}}|dk r||}|dk r|n| |}t |r|dkrd}nt|ttfs(tdt|d|d||_||_||_dS)Nz-threshold must be a float or int number, got  r)rrrUrrrrr)rarrrrbrbrcr_s zThresholdIntensity.__init__r rcCsLt|td}|jr||jkn||jk}t|||j}t||jd^}}|S)rsrtrh)r(r rrrrr&r[)raremaskresrprbrbrcrxs zThresholdIntensity.__call__N)TrTrrbrbrbrcr7s c @sReZdZdZejejgZdddej fdddddddd d d Z d d d ddZ dS)r8a Apply specific intensity scaling to the whole numpy array. Scaling from [a_min, a_max] to [b_min, b_max] with clip option. When `b_min` or `b_max` are `None`, `scaled_array * (b_max - b_min) + b_min` will be skipped. If `clip=True`, when `b_min`/`b_max` is None, the clipping is not performed on the corresponding edge. Args: a_min: intensity original range min. a_max: intensity original range max. b_min: intensity target range min. b_max: intensity target range max. clip: whether to perform clip after scaling. dtype: output data type, if None, same as input image. defaults to float32. NFrUrdrVr rW)a_mina_maxb_minb_maxrr[r]cCs(||_||_||_||_||_||_dSr^rrrrrr[)rarrrrrr[rbrbrcr_s zScaleIntensityRange.__init__r rcCst|td}|jp|j}|j|jdkrXtdt|jdkrH||jS||j|jS||j|j|j}|jdk r|jdk r||j|j|j}|j rt ||j|j}t ||dd}|S)rsrtrTzDivide by zero (a_min == a_max)Nrhr) r(r r[rrr Warningrrrr&)rarer[rrbrbrcrxs    zScaleIntensityRange.__call__rrbrbrbrcr8s c @sbeZdZdZejejgZdddej fddddddddd d Z d d d d dZ d d d ddZ dS)r9a Apply clip based on the intensity distribution of input image. If `sharpness_factor` is provided, the intensity values will be soft clipped according to f(x) = x + (1/sharpness_factor)*softplus(- c(x - minv)) - (1/sharpness_factor)*softplus(c(x - maxv)) From https://medium.com/life-at-hopper/clip-it-clip-it-good-1f1bf711b291 Soft clipping preserves the order of the values and maintains the gradient everywhere. For example: .. code-block:: python :emphasize-lines: 11, 22 image = torch.Tensor( [[[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]]) # Hard clipping from lower and upper image intensity percentiles hard_clipper = ClipIntensityPercentiles(30, 70) print(hard_clipper(image)) metatensor([[[2., 2., 3., 4., 4.], [2., 2., 3., 4., 4.], [2., 2., 3., 4., 4.], [2., 2., 3., 4., 4.], [2., 2., 3., 4., 4.], [2., 2., 3., 4., 4.]]]) # Soft clipping from lower and upper image intensity percentiles soft_clipper = ClipIntensityPercentiles(30, 70, 10.) print(soft_clipper(image)) metatensor([[[2.0000, 2.0693, 3.0000, 3.9307, 4.0000], [2.0000, 2.0693, 3.0000, 3.9307, 4.0000], [2.0000, 2.0693, 3.0000, 3.9307, 4.0000], [2.0000, 2.0693, 3.0000, 3.9307, 4.0000], [2.0000, 2.0693, 3.0000, 3.9307, 4.0000], [2.0000, 2.0693, 3.0000, 3.9307, 4.0000]]]) See Also: - :py:class:`monai.transforms.ScaleIntensityRangePercentiles` NFrdrVr rW)loweruppersharpness_factorrreturn_clipping_valuesr[r]cCs|dkr|dkrtd|dk r8|dks0|dkr8td|dk rX|dksP|dkrXtd|dk rx|dk rx||krxtd|dk r|dkrtd||_||_||_||_|rg|_||_||_dS) a Args: lower: lower intensity percentile. In the case of hard clipping, None will have the same effect as 0 by not clipping the lowest input values. However, in the case of soft clipping, None and zero will have two different effects: None will not apply clipping to low values, whereas zero will still transform the lower values according to the soft clipping transformation. Please check for more details: https://medium.com/life-at-hopper/clip-it-clip-it-good-1f1bf711b291. upper: upper intensity percentile. The same as for lower, but this time with the highest values. If we are looking to perform soft clipping, if None then there will be no effect on this side whereas if set to 100, the values will be passed via the corresponding clipping equation. sharpness_factor: if not None, the intensity values will be soft clipped according to f(x) = x + (1/sharpness_factor)*softplus(- c(x - minv)) - (1/sharpness_factor)*softplus(c(x - maxv)). defaults to None. channel_wise: if True, compute intensity percentile and normalize every channel separately. default to False. return_clipping_values: whether to return the calculated percentiles in tensor meta information. If soft clipping and requested percentile is None, return None as the corresponding clipping values in meta information. Clipping values are stored in a list with each element corresponding to a channel if channel_wise is set to True. defaults to False. dtype: output data type, if None, same as input image. defaults to float32. Nz+lower or upper percentiles must be providedrTY@)Percentiles must be in the range [0, 100]z,upper must be greater than or equal to lowerrz'sharpness_factor must be greater than 0)rrrrrclipping_valuesrr[)rarrrrrr[rbrbrcr_$s$z!ClipIntensityPercentiles.__init__r rcCs|jdk rT|jdk r t||jnd}|jdk r:t||jnd}t||j|||j}nL|jdk rjt||jnt|d}|jdk rt||jnt|d}t|||}|jr|j |dkr|nt |dr| n||dkr|nt |dr| n|ft |dd}|S)NrdrFrt) rrrrrr[rrr rhasattrrr()rareZlower_percentileZupper_percentilerbrbrc_clipVs&     zClipIntensityPercentiles._clipcslt|td}t|dd}jr:tfdd|D}n j|d}t||dd}jrhj|j d<|S) rsrtFcsg|]}j|dqSr)r#rrrbrcrysz5ClipIntensityPercentiles.__call__..rrrr ) r(r rrrr#r'rr metararerrbrrcrxrs   z!ClipIntensityPercentiles.__call__) rzr{r|r}rr~rrrrr_r#rxrbrbrbrcr9s. 2c@sDeZdZdZejejgZddddddddZdd d d d d Z d S)r:aN Changes image intensity with gamma transform. Each pixel/voxel intensity is updated as:: x = ((x - min) / intensity_range) ^ gamma * intensity_range + min Args: gamma: gamma value to adjust the contrast as function. invert_image: whether to invert the image before applying gamma augmentation. If True, multiply all intensity values with -1 before the gamma transform and again after the gamma transform. This behaviour is mimicked from `nnU-Net `_, specifically `this `_ function. retain_stats: if True, applies a scaling factor and an offset to all intensity values after gamma transform to ensure that the output intensity distribution has the same mean and standard deviation as the intensity distribution of the input. This behaviour is mimicked from `nnU-Net `_, specifically `this `_ function. FrUrVrW)gamma invert_image retain_statsr]cCs>t|ttfs(tdt|d|d||_||_||_dS)Nz)gamma must be a float or int number, got rr)rrrUrrr(r)r*)rar(r)r*rbrbrcr_s zAdjustContrast.__init__Nr rc Cst|td}|dk r|n|j}|jr,| }|jrB|}|}d}|}||}||t |||||}|jr||}||d}|||}|jr| }|S)zn Apply the transform to `img`. gamma: gamma value to adjust the contrast as function. rtNgHz>g:0yE>) r(r r(r)r*rYrZrrrU) rarer(rsdepsilonimg_minZ img_rangerrbrbrcrxs$    zAdjustContrast.__call__)FF)Nrrbrbrbrcr:s cs\eZdZdZejZddddddd d d Zdd ddfdd ZdddddddZZ S)r;a Randomly changes image intensity with gamma transform. Each pixel/voxel intensity is updated as: x = ((x - min) / intensity_range) ^ gamma * intensity_range + min Args: prob: Probability of adjustment. gamma: Range of gamma values. If single number, value is picked from (0.5, gamma), default is (0.5, 4.5). invert_image: whether to invert the image before applying gamma augmentation. If True, multiply all intensity values with -1 before the gamma transform and again after the gamma transform. This behaviour is mimicked from `nnU-Net `_, specifically `this `_ function. retain_stats: if True, applies a scaling factor and an offset to all intensity values after gamma transform to ensure that the output intensity distribution has the same mean and standard deviation as the intensity distribution of the input. This behaviour is mimicked from `nnU-Net `_, specifically `this `_ function. rS?g@FrUrrVrW)rXr(r)r*r]cCst||t|ttfr<|dkr0td|d|f|_n(t|dkrRtdnt|t |f|_d|_ ||_ ||_ t |j |j |j d|_dS)Nr/zWif gamma is a number, must greater than 0.5 and value is picked from (0.5, gamma), got rz,gamma should be a number or pair of numbers.r)r)r*)rr_rrrUrr(rrr gamma_valuer)r*r:adjust_contrast)rarXr(r)r*rbrbrcr_s$    zRandAdjustContrast.__init__Nrrcs8td|jsdS|jj|jd|jdd|_dSr)rirjrkrlrmr(r0rrqrbrcrjs zRandAdjustContrast.randomizeTr rcCsDt|td}|r||js$|S|jdkr6td|||jS)rsrtNz?gamma_value is not set, please call `randomize` function first.)r(r rjrkr0rwr1rrbrbrcrxs zRandAdjustContrast.__call__)rSr.FF)N)T) rzr{r|r}r:rr_rjrxrrbrbrqrcr;sc @s`eZdZdZejZdddejfdddddddddd d d Zd d d d dZ d d d ddZ dS)r<a Apply range scaling to a numpy array based on the intensity distribution of the input. By default this transform will scale from [lower_intensity_percentile, upper_intensity_percentile] to `[b_min, b_max]`, where {lower,upper}_intensity_percentile are the intensity values at the corresponding percentiles of ``img``. The ``relative`` parameter can also be set to scale from [lower_intensity_percentile, upper_intensity_percentile] to the lower and upper percentiles of the output range [b_min, b_max]. For example: .. code-block:: python :emphasize-lines: 11, 22 image = torch.Tensor( [[[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]]) # Scale from lower and upper image intensity percentiles # to output range [b_min, b_max] scaler = ScaleIntensityRangePercentiles(10, 90, 0, 200, False, False) print(scaler(image)) metatensor([[[ 0., 50., 100., 150., 200.], [ 0., 50., 100., 150., 200.], [ 0., 50., 100., 150., 200.], [ 0., 50., 100., 150., 200.], [ 0., 50., 100., 150., 200.], [ 0., 50., 100., 150., 200.]]]) # Scale from lower and upper image intensity percentiles # to lower and upper percentiles of the output range [b_min, b_max] rel_scaler = ScaleIntensityRangePercentiles(10, 90, 0, 200, False, True) print(rel_scaler(image)) metatensor([[[ 20., 60., 100., 140., 180.], [ 20., 60., 100., 140., 180.], [ 20., 60., 100., 140., 180.], [ 20., 60., 100., 140., 180.], [ 20., 60., 100., 140., 180.], [ 20., 60., 100., 140., 180.]]]) See Also: - :py:class:`monai.transforms.ScaleIntensityRange` Args: lower: lower intensity percentile. upper: upper intensity percentile. b_min: intensity target range min. b_max: intensity target range max. clip: whether to perform clip after scaling. relative: whether to scale to the corresponding percentiles of [b_min, b_max]. channel_wise: if True, compute intensity percentile and normalize every channel separately. default to False. dtype: output data type, if None, same as input image. defaults to float32. FrUrdrVr rW) rrrrrrrr[r]c Csd|dks|dkrtd|dks(|dkr0td||_||_||_||_||_||_||_||_dS)NrTrr) rrrrrrrrr[) rarrrrrrrr[rbrbrcr_Ps z'ScaleIntensityRangePercentiles.__init__r rcCst||j}t||j}|j}|j}|jr~|jdks>|jdkrFtd|j|j|jd|j}|j|j|jd|j}t|||||j|j d}||}t |dd}|S)Nz6If it is relative, b_min and b_max should not be None.rrFrt) rrrrrrrr8rr[r()rarerrrrscalarrbrbrcr hs(   z)ScaleIntensityRangePercentiles._normalizecsVt|td}t|dd}jr:tfdd|D}n j|d}t||ddS)rsrtFcsg|]}j|dqSr$)r rrrbrcrsz;ScaleIntensityRangePercentiles.__call__..rr%r)r(r rrrr r'r'rbrrcrx{s   z'ScaleIntensityRangePercentiles.__call__N) rzr{r|r}r8rrrr_r rxrbrbrbrcr<s> c@sHeZdZdZejejgZdefddddddZ d d dd d d d Z dS)r=aP Mask the intensity values of input image with the specified mask data. Mask data must have the same spatial size as the input image, and all the intensity values of input image corresponding to the selected values in the mask data will keep the original value, others will be set to `0`. Args: mask_data: if `mask_data` is single channel, apply to every channel of input image. if multiple channels, the number of channels must match the input data. the intensity values of input image corresponding to the selected values in the mask data will keep the original value, others will be set to `0`. if None, must specify the `mask_data` at runtime. select_fn: function to select valid values of the `mask_data`, default is to select `values > 0`. NNdarrayOrTensor | NonerrW) mask_data select_fnr]cCs||_||_dSr^)r4r5)rar4r5rbrbrcr_szMaskIntensity.__init__r )rer4r]cCst|td}|dkr|jn|}|dkr0tdt||d^}}||}|jddkr|jd|jdkrtd|jdd|jdd t|||d dS) a& Args: mask_data: if mask data is single channel, apply to every channel of input image. if multiple channels, the channel number must match input data. mask_data will be converted to `bool` values by `mask_data > 0` before applying transform to input image. Raises: - ValueError: When both ``mask_data`` and ``self.mask_data`` are None. - ValueError: When ``mask_data`` and ``img`` channels differ and ``mask_data`` is not single channel. rtNzImust provide the mask_data when initializing the transform or at runtime.rrrrzZWhen mask_data is not single channel, mask_data channels must match img, got img channels=z mask_data channels=rr%)r(r r4rr'r5ro)rarer4Z mask_data_rprbrbrcrxs  "zMaskIntensity.__call__)N) rzr{r|r}rr~rrrr_rxrbrbrbrcr=s c@s>eZdZdZejgZddddddddZd d d d d Zd S)r?aQ Smooth the input data along the given axis using a Savitzky-Golay filter. Args: window_length: Length of the filter window, must be a positive odd integer. order: Order of the polynomial to fit to each window, must be less than ``window_length``. axis: Optional axis along which to apply the filter kernel. Default 1 (first spatial dimension). mode: Optional padding mode, passed to convolution class. ``'zeros'``, ``'reflect'``, ``'replicate'`` or ``'circular'``. Default: ``'zeros'``. See ``torch.nn.Conv1d()`` for more information. rrrstr) window_lengthorderrmodecCs8|dkrtd||_||_||_||_td|_dS)Nraxis must be zero or positive.rT)rr8r9rr:rrr)rar8r9rr:rbrbrcr_szSavitzkyGolaySmooth.__init__r rcCs`t|td}t|dd|_t|j|j|jd|j}||jd d}t ||d^}}|S)z Args: img: array containing input data. Must be real and in shape [channels, spatial1, spatial2, ...]. Returns: array containing smoothed result. rtFrrr%) r(r rrr8r9rr: unsqueezesqueezer')rare savgol_filterZsmoothedrrprbrbrcrxs zSavitzkyGolaySmooth.__call__N)rr rzr{r|r}rr~rr_rxrbrbrbrcr?s  c@s:eZdZdZejgZddddddd Zd d d d ZdS)r>aU Find the envelope of the input data along the requested axis using a Hilbert transform. Args: axis: Axis along which to detect the envelope. Default 1, i.e. the first spatial dimension. n: FFT size. Default img.shape[axis]. Input will be zero-padded or truncated to this size along dimension ``axis``. rNr int | NonerW)rnr]cCs |dkrtd||_||_dS)Nrr;)rrrA)rarrArbrbrcr_szDetectEnvelope.__init__r rcCs\t|td}t|tj^}}t|jd|j}||d d }t ||d^}}|S)z Args: img: numpy.ndarray containing input data. Must be real and in shape [channels, spatial1, spatial2, ...]. Returns: np.ndarray containing envelope of data in img along the specified axis. rtrrr6) r(r r&rrrrrAr<r=absr')rarerrpZhilbert_transformrrbrbrcrxs zDetectEnvelope.__call__)rNr?rbrbrbrcr>s c@s:eZdZdZejgZd dddddZddd d d Zd S)r@a Apply median filter to the input data based on specified `radius` parameter. A default value `radius=1` is provided for reference. See also: :py:func:`monai.networks.layers.median_filter` Args: radius: if a list of values, must match the count of spatial dimensions of input data, and apply every value in the list to 1 spatial dimension. if only 1 value provided, use it for all spatial dimensions. rSequence[int] | intrW)radiusr]cCs ||_dSr^)rD)rarDrbrbrcr_$szMedianSmooth.__init__r rc Csft|td}t|tjtjd^}}|jd}t|j|}t ||d}||}t |||j d^}}|S)Nrtrhr) spatial_dimsr) r(r r&rrrUndimr!rDrr'r[) rarerrprErZmedian_filter_instanceout_trrbrbrcrx's   zMedianSmooth.__call__N)rr?rbrbrbrcr@s c@s<eZdZdZejgZddddddd Zd d d d d ZdS)rAa: Apply Gaussian smooth to the input data based on specified `sigma` parameter. A default value `sigma=1.0` is provided for reference. Args: sigma: if a list of values, must match the count of spatial dimensions of input data, and apply every value in the list to 1 spatial dimension. if only 1 value provided, use it for all spatial dimensions. approx: discrete Gaussian kernel type, available options are "erf", "sampled", and "scalespace". see also :py:meth:`monai.networks.layers.GaussianFilter`. rerfrr7rW)sigmaapproxr]cCs||_||_dSr^rJrK)rarJrKrbrbrcr_BszGaussianSmooth.__init__r rcst|td}t|tjtjd^}t|jtrFfdd|jD}ntj |jj d}t j d||j d}|dd}t|||jd ^}}|S) Nrtrhcsg|]}tj|jdqS)r)r as_tensorr)rsrrbrcrKsz+GaussianSmooth.__call__..rrrKrr)r(r r&rrrUrrJrrMrrrFrKr<r=r'r[)rarerprJgaussian_filterrHrrbrOrcrxFs zGaussianSmooth.__call__N)rrIr?rbrbrbrcrA2s cs^eZdZdZejZdddddddd d d Zdd ddfdd ZdddddddZZ S)rBaD Apply Gaussian smooth to the input data based on randomly selected `sigma` parameters. Args: sigma_x: randomly select sigma value for the first spatial dimension. sigma_y: randomly select sigma value for the second spatial dimension if have. sigma_z: randomly select sigma value for the third spatial dimension if have. prob: probability of Gaussian smooth. approx: discrete Gaussian kernel type, available options are "erf", "sampled", and "scalespace". see also :py:meth:`monai.networks.layers.GaussianFilter`. g?g?rSrIrrUr7rW)sigma_xsigma_ysigma_zrXrKr]cCsLt||||_||_||_||_|jd|_|jd|_|jd|_dS)Nr) rr_rSrTrUrKryz)rarSrTrUrXrKrbrbrcr_es   zRandGaussianSmooth.__init__Nrrcsttd|jsdS|jj|jd|jdd|_|jj|jd|jdd|_|jj|j d|j dd|_ dSr) rirjrkrlrmrSrrTrVrUrWrrqrbrcrjws  zRandGaussianSmooth.randomizeTr rVrcCsTt|td}|r||js$|St|j|j|jf|jdd}t ||j d|S)NrtrvalsrrL) r(r rjrkr"rrVrWrFrArK)rarerjrJrbrbrcrxszRandGaussianSmooth.__call__)rRrRrRrSrI)N)T) rzr{r|r}rArr_rjrxrrbrbrqrcrBUs c@s@eZdZdZejgZdddddd d d d Zd d dddZdS)rCa& Sharpen images using the Gaussian Blur filter. Referring to: http://scipy-lectures.org/advanced/image_processing/auto_examples/plot_sharpen.html. The algorithm is shown as below .. code-block:: python blurred_f = gaussian_filter(img, sigma1) filter_blurred_f = gaussian_filter(blurred_f, sigma2) img = blurred_f + alpha * (blurred_f - filter_blurred_f) A set of default values `sigma1=3.0`, `sigma2=1.0` and `alpha=30.0` is provide for reference. Args: sigma1: sigma parameter for the first gaussian kernel. if a list of values, must match the count of spatial dimensions of input data, and apply every value in the list to 1 spatial dimension. if only 1 value provided, use it for all spatial dimensions. sigma2: sigma parameter for the second gaussian kernel. if a list of values, must match the count of spatial dimensions of input data, and apply every value in the list to 1 spatial dimension. if only 1 value provided, use it for all spatial dimensions. alpha: weight parameter to compute the final result. approx: discrete Gaussian kernel type, available options are "erf", "sampled", and "scalespace". see also :py:meth:`monai.networks.layers.GaussianFilter`. @r>@rIrrUr7rW)sigma1sigma2alpharKr]cCs||_||_||_||_dSr^r\r]r^rK)rar\r]r^rKrbrbrcr_szGaussianSharpen.__init__r rc st|td}t|tjtjd^}fddjjfD\}}|d}||}|j || d}t |||j d^}}|S)Nrtrhc3s,|]$}tjd|jdjVqdS)rrPN)rrFrKtor)rrJrrarbrc sz+GaussianSharpen.__call__..rr) r(r r&rrrr\r]r<r^r=r'r[) rarerpZgf1Zgf2Z blurred_fZfilter_blurred_frHrrbrarcrxs  zGaussianSharpen.__call__N)rZrr[rIr?rbrbrbrcrCs c sfeZdZdZejZddddddddd d d d d dZddd dfdd ZdddddddZZ S)rDa Sharpen images using the Gaussian Blur filter based on randomly selected `sigma1`, `sigma2` and `alpha`. The algorithm is :py:class:`monai.transforms.GaussianSharpen`. Args: sigma1_x: randomly select sigma value for the first spatial dimension of first gaussian kernel. sigma1_y: randomly select sigma value for the second spatial dimension(if have) of first gaussian kernel. sigma1_z: randomly select sigma value for the third spatial dimension(if have) of first gaussian kernel. sigma2_x: randomly select sigma value for the first spatial dimension of second gaussian kernel. if only 1 value `X` provided, it must be smaller than `sigma1_x` and randomly select from [X, sigma1_x]. sigma2_y: randomly select sigma value for the second spatial dimension(if have) of second gaussian kernel. if only 1 value `Y` provided, it must be smaller than `sigma1_y` and randomly select from [Y, sigma1_y]. sigma2_z: randomly select sigma value for the third spatial dimension(if have) of second gaussian kernel. if only 1 value `Z` provided, it must be smaller than `sigma1_z` and randomly select from [Z, sigma1_z]. alpha: randomly select weight parameter to compute the final result. approx: discrete Gaussian kernel type, available options are "erf", "sampled", and "scalespace". see also :py:meth:`monai.networks.layers.GaussianFilter`. prob: probability of Gaussian sharpen. r/rr/g$@r[rIrSrrr7rUrW) sigma1_xsigma1_ysigma1_zsigma2_xsigma2_ysigma2_zr^rKrXr]c Csjt|| ||_||_||_||_||_||_||_||_ d|_ d|_ d|_ d|_ d|_d|_d|_dSr^)rr_rerfrgrhrirjr^rKx1y1z1x2y2z2a) rarerfrgrhrirjr^rKrXrbrbrcr_s zRandGaussianSharpen.__init__Nrrcs:td|jsdS|jj|jd|jdd|_|jj|jd|jdd|_|jj|j d|j dd|_ t |j t s|j |jfn|j }t |jt s|j|jfn|j}t |jt s|j|j fn|j}|jj|d|dd|_|jj|d|dd|_|jj|d|dd|_|jj|jd|jdd|_dSr)rirjrkrlrmrerkrfrlrgrmrrhrrirjrnrorpr^rq)rarrhrirjrqrbrcrjs zRandGaussianSharpen.randomizeTr rVrcCst|td}|r||js$|S|jdksL|jdksL|jdksL|jdkrTtdt |j |j |j f|j dd}t |j|j|jf|j dd}t|||j|jd|S)NrtrvrrXr_)r(r rjrkrnrorprqrwr"rkrlrmrFrCrK)rarerjr\r]rbrbrcrxs(zRandGaussianSharpen.__call__) rcrcrcr/r/r/rdrIrS)N)T) rzr{r|r}rCrr_rjrxrrbrbrqrcrDs"csreZdZdZejejgZddddddd Zd d d d d d d Z ddddfdd Z dd dd dddZ Z S)rEa Apply random nonlinear transform to the image's intensity histogram. Args: num_control_points: number of control points governing the nonlinear intensity mapping. a smaller number of control points allows for larger intensity shifts. if two values provided, number of control points selecting from range (min_value, max_value). prob: probability of histogram shift. rSztuple[int, int] | intrUrW)num_control_pointsrXr]cCsxt||t|tr2|dkr&td||f|_n:t|dkrFtdt|dkrZtdt|t|f|_||dS)Nrz7num_control_points should be greater than or equal to 3z:num_control points should be a number or a pair of numbers) rr_rrrrsrrr)rarsrXrbrbrcr_#s     zRandHistogramShift.__init__r )rxpfpr]c Cst|tjrtnt}t|tjr.t|||S|dd|dd|dd|dd}|dd||dd}||d|dd}||dt |d}|||d|||j }|d|||dk<|d|||dk<|S)Nrr) rrrrrinterp searchsortedreshaperrro) rarrtrunsmbindicesfrbrbrcrw3s 0"zRandHistogramShift.interpNrrcstd|jsdS|j|jd|jdd}tdd||_t |j|_ t d|dD],}|j |j |d|j |d|j |<q`dS)Nrr) rirjrkrlrandintrsrrreference_control_pointsrfloating_control_pointsrrm)rarZnum_control_pointrrqrbrcrjDs  zRandHistogramShift.randomizeTrVrc Cst|td}|r||js$|S|jdks8|jdkr@tdt|dd}||}}||krzt d|d|St |j|d^}}t |j|d^}}||||} ||||} | || | }t ||ddS)NrtrvFz(The image's intensity is a single value zD. The original image is simply returned, no histogram shift is done.r%r) r(r rjrkrrrwrrr r'rw) rarerjrr-Zimg_maxrtrpypZreference_control_points_scaledZfloating_control_points_scaledrbrbrcrxPs(  zRandHistogramShift.__call__)rrrS)N)T) rzr{r|r}rr~rrr_rwrjrxrrbrbrqrcrEs   c@sNeZdZdZejejgZddddddZddd d d Z ddd d dZ dS)rFa The transform applies Gibbs noise to 2D/3D MRI images. Gibbs artifacts are one of the common type of type artifacts appearing in MRI scans. The transform is applied to all the channels in the data. For general information on Gibbs artifacts, please refer to: `An Image-based Approach to Understanding the Physics of MR Artifacts `_. `The AAPM/RSNA Physics Tutorial for Residents `_ Args: alpha: Parametrizes the intensity of the Gibbs noise filter applied. Takes values in the interval [0,1] with alpha = 0 acting as the identity mapping. rSrUrW)r^r]cCs"|dks|dkrtd||_dS)Nrrz.alpha must take values in the interval [0, 1].)rr^)rar^rbrbrcr_szGibbsNoise.__init__r rcCsft|td}t|dd}t|jdd}|||}||}|||}t|||jd^}}|S)NrtFrr) r(r rro shift_fourier _apply_maskinv_shift_fourierr'r[)rarern_dimsrrrprbrbrcrxs    zGibbsNoise.__call__)rr]c Cs|jdd}d|jt|tdd}t|dd}tjtdd|D}ddt||D}tt |}||k}tj |d|jd d d }t |t j rt|t j |jd ^}} ||} | S) zBuilds and applies a mask on the spatial dimensions. Args: k: k-space version of the image. Returns: masked version of the k-space image. rNr@css|]}td|VqdSrN)slicerrrbrbrcrbsz)GibbsNoise._apply_mask..cSsg|]\}}||dqS)rrb)rcoordcrbrbrcrsz*GibbsNoise._apply_mask..rrr)ror^rrrarrayogridtuplezipsumrepeatrrrr&r) rarrorGcenterrZcoords_from_center_sqZdist_from_centerrrpZk_maskedrbrbrcrs" zGibbsNoise._apply_maskN)rS) rzr{r|r}rr~rrr_rxrrbrbrbrcrFjs  csTeZdZdZejZddddddd Zd dd fd d ZddddddZZ S)rGa Naturalistic image augmentation via Gibbs artifacts. The transform randomly applies Gibbs noise to 2D/3D MRI images. Gibbs artifacts are one of the common type of type artifacts appearing in MRI scans. The transform is applied to all the channels in the data. For general information on Gibbs artifacts, please refer to: https://pubs.rsna.org/doi/full/10.1148/rg.313105115 https://pubs.rsna.org/doi/full/10.1148/radiographics.22.4.g02jl14949 Args: prob (float): probability of applying the transform. alpha (float, Sequence(float)): Parametrizes the intensity of the Gibbs noise filter applied. Takes values in the interval [0,1] with alpha = 0 acting as the identity mapping. If a length-2 list is given as [a,b] then the value of alpha will be sampled uniformly from the interval [a,b]. 0 <= a <= b <= 1. If a float is given, then the value of alpha will be sampled uniformly from the interval [0, alpha]. rSrTrrUzfloat | Sequence[float]rW)rXr^r]cCst|trd|f}t|}t|dkr.td|ddksF|ddkrNtd|d|dkrftd||_d|_tj||ddS) Nrrzalpha length must be 2.rz-alpha must take values in the interval [0, 1]z!When alpha = [a,b] we need a < b.rrX) rrUr rrr^ sampled_alpharr_)rarXr^rbrbrcr_s  zRandGibbsNoise.__init__rrcs6td|jsdS|j|jd|jd|_dS)zr (1) Set random variable to apply the transform. (2) Get alpha from uniform distribution. Nrr)rirjrkrlrmr^rrrqrbrcrjs zRandGibbsNoise.randomizeTr rVrerjcCs4t|td}|r|d|js&|St|j|S)Nrt)r(r rjrkrFrrrbrbrcrxs  zRandGibbsNoise.__call__)rSr)T) rzr{r|r}rFrr_rjrxrrbrbrqrcrGs  c@s^eZdZdZejejgZddddddZddd d d Z d d ddZ ddddddZ dS)rHa Apply localized spikes in `k`-space at the given locations and intensities. Spike (Herringbone) artifact is a type of data acquisition artifact which may occur during MRI scans. For general information on spike artifacts, please refer to: `AAPM/RSNA physics tutorial for residents: fundamental physics of MR imaging `_. `Body MRI artifacts in clinical practice: A physicist's and radiologist's perspective `_. Args: loc: spatial location for the spikes. For images with 3D spatial dimensions, the user can provide (C, X, Y, Z) to fix which channel C is affected, or (X, Y, Z) to place the same spike in all channels. For 2D cases, the user can provide (C, X, Y) or (X, Y). k_intensity: value for the log-intensity of the `k`-space version of the image. If one location is passed to ``loc`` or the channel is not specified, then this argument should receive a float. If ``loc`` is given a sequence of locations, then this argument should receive a sequence of intensities. This value should be tested as it is data-dependent. The default values are the 2.5 the mean of the log-intensity for each channel. Example: When working with 4D data, ``KSpaceSpikeNoise(loc = ((3,60,64,32), (64,60,32)), k_intensity = (13,14))`` will place a spike at `[3, 60, 64, 32]` with `log-intensity = 13`, and one spike per channel located respectively at `[: , 64, 60, 32]` with `log-intensity = 14`. Nztuple | Sequence[tuple]zSequence[float] | float | None)loc k_intensitycCsxt||_||_t|trHt|dts0tdt|t|krHtdt|jdtrt|dk rtt|jtsttddS)NrzZIf a sequence is passed to k_intensity, then a sequence of locations must be passed to loczJThere must be one intensity_factor value for each tuple of indices in loc.)r rrrrrr)rarrrbrbrcr_s  $zKSpaceSpikeNoise.__init__r rc Cst|td}||t|jdkr.tdt|jdtrbt|jdkrbt|jdkrbtdt|jdt rt|jdkrt t t|jdkrtdt|jdd }| ||}t|t jrt nt}|||d }||}|j}|d krt|j|tt| dd d }t|jdt r\t|jt|D]\}} |||| q@n|||j||||d |}t||||d^}} |S)zX Args: img: image with dimensions (C, H, W) or (C, H, W, D) rtrz Image needs a channel direction.rrzCInput images of dimension 4 need location tuple to be length 3 or 4rN绽|=r@y?r%)r(r _check_indicesrrorwrrrrrmaprrrrlogrBanglerrrYrrr _set_spikerr'r) rarerrliblog_absphaseridxvalrprbrbrcrx(s. ,2   "zKSpaceSpikeNoise.__call__rW)r]cst|j}t|dts|g}tt|D]0t|t|jkr*dgt||<q*tt|jD]<|jtfdd|Dkrjtdd|jdqjdS)zHelper method to check consistency of self.loc and input image. Raises assertion error if any index in loc is out of bounds.rc3s|]}|VqdSr^rb)rrrrbrcrb^sz2KSpaceSpikeNoise._check_indices..zThe index value at position z of one of the tuples in loc = z$ is out of bounds for current image.N) listrrrrrrorr)rarerrbrrcrQs  zKSpaceSpikeNoise._check_indicesrr)rrrcCst|jt|kr2t|tr(||dn|||<npt|jdkrnt|dkrn||dd|d|d|df<n4t|jdkrt|dkr||dd|d|df<dS)z Helper function to introduce a given intensity at given location. Args: k: intensity array to alter. idx: index of location where to apply change. val: value of intensity to write in. rrrNrr)rrorr)rarrrrbrbrcrcs  "zKSpaceSpikeNoise._set_spike)N) rzr{r|r}rr~rrr_rxrrrbrbrbrcrHs " )cszeZdZdZejZdddddfd d Zdd dd d dZd dddfdd Zd ddddZ d ddddZ Z S)rIaF Naturalistic data augmentation via spike artifacts. The transform applies localized spikes in `k`-space, and it is the random version of :py:class:`monai.transforms.KSpaceSpikeNoise`. Spike (Herringbone) artifact is a type of data acquisition artifact which may occur during MRI scans. For general information on spike artifacts, please refer to: `AAPM/RSNA physics tutorial for residents: fundamental physics of MR imaging `_. `Body MRI artifacts in clinical practice: A physicist's and radiologist's perspective `_. Args: prob: probability of applying the transform, either on all channels at once, or channel-wise if ``channel_wise = True``. intensity_range: pass a tuple (a, b) to sample the log-intensity from the interval (a, b) uniformly for all channels. Or pass sequence of intervals ((a0, b0), (a1, b1), ...) to sample for each respective channel. In the second case, the number of 2-tuples must match the number of channels. Default ranges is `(0.95x, 1.10x)` where `x` is the mean log-intensity for each channel. channel_wise: treat each channel independently. True by default. Example: To apply `k`-space spikes randomly with probability 0.5, and log-intensity sampled from the interval [11, 12] for each channel independently, one uses ``RandKSpaceSpikeNoise(prob=0.5, intensity_range=(11, 12), channel_wise=True)`` rSNTrUz(Sequence[Sequence[float] | float] | NonerV)rXintensity_rangercsJ||_||_g|_g|_|dk r:t|dtr:|s:tdt|dS)NrzSWhen channel_wise = False, intensity_range should be a 2-tuple (low, high) or None.) rrsampled_k_intensity sampled_locsrrrrir_)rarXrrrqrbrcr_szRandKSpaceSpikeNoise.__init__r rcCs|jdk r6t|jdtr6t|j|jdkr6tdt|td}g|_g|_ |rj| |}| |||j st|St |j |j|S)z Apply transform to `img`. Assumes data is in channel-first form. Args: img: image with dimensions (C, H, W) or (C, H, W, D) NrziIf intensity_range is a sequence of sequences, then there must be one (low, high) tuple for each channel.rt)rrrrrorwr(r rr_make_sequencerjrkrH)rarerjrrbrbrcrxs$   zRandKSpaceSpikeNoise.__call__zSequence[Sequence[float]]rW)rerr]cstdjsdSjr|t|D]T\}}j|ftfdd|jDj j ||d||dq$ntfdd|jddDfddt |jdD_t |dtrއfd d|D_ n"j |d|dgt|_ dS) a Helper method to sample both the location and intensity of the spikes. When not working channel wise (channel_wise=False) it use the random variable ``self._do_transform`` to decide whether to sample a location and intensity. When working channel wise, the method randomly samples a location and intensity for each channel depending on ``self._do_transform``. Nc3s|]}jd|VqdSrrlrrrrbrcrbsz1RandKSpaceSpikeNoise.randomize..rrc3s|]}jd|VqdSrrrrrbrcrbscsg|]}|fqSrbrbr)spatialrbrcrsz2RandKSpaceSpikeNoise.randomize..cs"g|]}j|d|dqS)rr)rlrm)rprrbrcrs)rirjrkrrrrrrorrlrmrrrr)rarerrchanrq)rarrcrjs &* zRandKSpaceSpikeNoise.randomize)rr]cCsD|jdkr||St|jdts:t|jf|jdSt|jS)zZ Formats the sequence of intensities ranges to Sequence[Sequence[float]]. Nr)r_set_default_rangerrr ro)rarrbrbrcrs   z#RandKSpaceSpikeNoise._make_sequencercCst|jdd}|||}t|tjr.tnt}|||d}| |t t | dd}t|tjrx| d}t dd|DS) zr Sets default intensity ranges to be sampled. Args: img: image to transform. rNrrrcpucss|]}|d|dfVqdS)gffffff?g?Nrbrrbrbrcrbsz:RandKSpaceSpikeNoise._set_default_range..) rrorrrrrrabsoluterYrrr`)rarerrmodrZ shifted_meansrbrbrcrs   z'RandKSpaceSpikeNoise._set_default_range)rSNT)T) rzr{r|r}rHrr_rxrjrrrrbrbrqrcrIts" csreZdZdZejgZddddddd d d d Zd d dfdd Ze dddddZ dddddddZ Z S)rJa Randomly select coarse regions in the image, then execute transform operations for the regions. It's the base class of all kinds of region transforms. Refer to papers: https://arxiv.org/abs/1708.04552 Args: holes: number of regions to dropout, if `max_holes` is not None, use this arg as the minimum number to randomly select the expected number of regions. spatial_size: spatial size of the regions to dropout, if `max_spatial_size` is not None, use this arg as the minimum spatial size to randomly select size for every region. if some components of the `spatial_size` are non-positive values, the transform will use the corresponding components of input img size. For example, `spatial_size=(32, -1)` will be adapted to `(32, 64)` if the second spatial dimension size of img is `64`. max_holes: if not None, define the maximum number to randomly select the expected number of regions. max_spatial_size: if not None, define the maximum spatial size to randomly select size for every region. if some components of the `max_spatial_size` are non-positive values, the transform will use the corresponding components of input img size. For example, `max_spatial_size=(32, -1)` will be adapted to `(32, 64)` if the second spatial dimension size of img is `64`. prob: probability of applying the transform. NrSrrCr@Sequence[int] | int | NonerUrW)holes spatial_size max_holesmax_spatial_sizerXr]cCs>t|||dkrtd||_||_||_||_g|_dS)Nrz'number of holes must be greater than 0.)rr_rrrrr hole_coords)rarrrrrXrbrbrcr_ s zRandCoarseTransform.__init__rrcstdjsdStj|g_jdkr8jnj jjd}t |D]f}j dk rtj |t fddt t |Dt|}jtdft||jqVdS)Nrc3s*|]"}jj||ddVqdS)rrNrrmax_sizerargrbrcrb3 sz0RandCoarseTransform.randomize..)rirjrkr#rrrrrlrrrrrrrrr)rarZ num_holesrp valid_sizerqrrcrj) s  &   " zRandCoarseTransform.randomize np.ndarrayrcCstd|jjddS)zV Transform the randomly selected `self.hole_coords` in input images. z Subclass z must implement this method.N)rrrrzrarerbrbrc_transform_holes7 sz$RandCoarseTransform._transform_holesTr rVrcCs`t|td}|r&||jdd|js0|St|tj^}}|j|d}t ||d^}}|S)Nrtrrr6) r(r rjrorkr&rrrr')rarerjrrprrrbrbrcrx? s zRandCoarseTransform.__call__)NNrS)T) rzr{r|r}rrrr_rjrrrxrrbrbrqrcrJsc sDeZdZdZdddddd d d d d fdd ZddddZZS)rKa Randomly coarse dropout regions in the image, then fill in the rectangular regions with specified value. Or keep the rectangular regions and fill in the other areas with specified value. Refer to papers: https://arxiv.org/abs/1708.04552, https://arxiv.org/pdf/1604.07379 And other implementation: https://albumentations.ai/docs/api_reference/augmentations/transforms/ #albumentations.augmentations.transforms.CoarseDropout. Args: holes: number of regions to dropout, if `max_holes` is not None, use this arg as the minimum number to randomly select the expected number of regions. spatial_size: spatial size of the regions to dropout, if `max_spatial_size` is not None, use this arg as the minimum spatial size to randomly select size for every region. if some components of the `spatial_size` are non-positive values, the transform will use the corresponding components of input img size. For example, `spatial_size=(32, -1)` will be adapted to `(32, 64)` if the second spatial dimension size of img is `64`. dropout_holes: if `True`, dropout the regions of holes and fill value, if `False`, keep the holes and dropout the outside and fill value. default to `True`. fill_value: target value to fill the dropout regions, if providing a number, will use it as constant value to fill all the regions. if providing a tuple for the `min` and `max`, will randomly select value for every pixel / voxel from the range `[min, max)`. if None, will compute the `min` and `max` value of input image then randomly select value to fill, default to None. max_holes: if not None, define the maximum number to randomly select the expected number of regions. max_spatial_size: if not None, define the maximum spatial size to randomly select size for every region. if some components of the `max_spatial_size` are non-positive values, the transform will use the corresponding components of input img size. For example, `max_spatial_size=(32, -1)` will be adapted to `(32, 64)` if the second spatial dimension size of img is `64`. prob: probability of applying the transform. TNrSrrCrVz"tuple[float, float] | float | Noner@rrUrW)rr dropout_holes fill_valuerrrXr]csHtj|||||d||_t|ttfr>t|dkr>td||_dS)N)rrrrrXrzEfill value should contain 2 numbers if providing the `min` and `max`.) rir_rrrrrrr)rarrrrrrrXrqrbrcr_l s  zRandCoarseDropout.__init__rrcCs|jdkr||fn|j}|jrt|jD]@}t|ttfrd|jj |d|d||j d||<q,|||<q,|}n\t|ttfr|jj |d|d|j dj |j dd}n t ||}|jD]}||||<q|S)z Fill the randomly selected `self.hole_coords` in input images. Please note that we usually only use `self.R` in `randomize()` method, here is a special case. NrrrfFr)rrrrrrrrrlrmrorr[r full_like)rarerhrrbrbrcr s  & *  z"RandCoarseDropout._transform_holes)TNNNrS)rzr{r|r}r_rrrbrbrqrcrKM s""c@seZdZdZddddZdS)rLa Randomly select regions in the image, then shuffle the pixels within every region. It shuffles every channel separately. Refer to paper: Kang, Guoliang, et al. "Patchshuffle regularization." arXiv preprint arXiv:1707.07103 (2017). https://arxiv.org/abs/1707.07103 Args: holes: number of regions to dropout, if `max_holes` is not None, use this arg as the minimum number to randomly select the expected number of regions. spatial_size: spatial size of the regions to dropout, if `max_spatial_size` is not None, use this arg as the minimum spatial size to randomly select size for every region. if some components of the `spatial_size` are non-positive values, the transform will use the corresponding components of input img size. For example, `spatial_size=(32, -1)` will be adapted to `(32, 64)` if the second spatial dimension size of img is `64`. max_holes: if not None, define the maximum number to randomly select the expected number of regions. max_spatial_size: if not None, define the maximum spatial size to randomly select size for every region. if some components of the `max_spatial_size` are non-positive values, the transform will use the corresponding components of input img size. For example, `max_spatial_size=(32, -1)` will be adapted to `(32, 64)` if the second spatial dimension size of img is `64`. prob: probability of applying the transform. rrcCsN|jD]B}t||D]0\}}|}|j|||j|||<qq|S)z Shuffle the content of randomly selected `self.hole_coords` in input images. Please note that we usually only use `self.R` in `randomize()` method, here is a special case. )rrflattenrlshuffleryro)rarerrrZ patch_channelrbrbrcr s   z"RandCoarseShuffle._transform_holesN)rzr{r|r}rrbrbrbrcrL sc@sReZdZdZejgZddddejfdddddd d d d Z dd dd dddZ dS)rMa? Apply the histogram normalization to input image. Refer to: https://github.com/facebookresearch/CovidPrognosis/blob/master/covidprognosis/data/transforms.py#L83. Args: num_bins: number of the bins to use in histogram, default to `256`. for more details: https://numpy.org/doc/stable/reference/generated/numpy.histogram.html. min: the min value to normalize input image, default to `0`. max: the max value to normalize input image, default to `255`. mask: if provided, must be ndarray of bools or 0s and 1s, and same shape as `image`. only points at which `mask==True` are used for the equalization. can also provide the mask along with img at runtime. dtype: data type of the output, if None, same as input image. default to `float32`. rNrr3r rW)num_binsrrrr[r]cCs"||_||_||_||_||_dSr^)rrrrr[)rarrrrr[rbrbrcr_ s zHistogramNormalize.__init__r rerr]cCst|td}t|tj^}}|dk r*|n|j}d}|dk rLt|tj^}}t|||j|j|j d}t |||j pt|j d^}}|S)Nrt)rerrrrr) r(r r&rrrrrrrr'r[)rarerrrpmask_nprrrbrbrcrx szHistogramNormalize.__call__)N) rzr{r|r}rrrrrr_rxrbrbrbrcrM scs:eZdZdZd dddfdd Zd d d d d ZZS)rNa Transform for intensity remapping of images. The intensity at each pixel is replaced by a new values coming from an intensity remappping curve. The remapping curve is created by uniformly sampling values from the possible intensities for the input image and then adding a linear component. The curve is the rescaled to the input image intensity range. Intended to be used as a means to data augmentation via: :py:class:`monai.transforms.RandIntensityRemap`. Implementation is described in the work: `Intensity augmentation for domain transfer of whole breast segmentation in MRI `_. Args: kernel_size: window size for averaging operation for the remapping curve. slope: slope of the linear component. Easiest to leave default value and tune the kernel_size parameter instead. ffffff?rrU) kernel_sizeslopecst||_||_dSr^)rir_rr)rarrrqrbrcr_ s zIntensityRemap.__init__ torch.TensorrcCst|td}t|dd}t|}t|j|t|d|j }tj j |j dd| d }tt|t|}||j|7}||||||}t|t|}t|||d^}}|S)8 Args: img: image to remap. rtFr)striderr%)r(r runiquer from_numpyrlchoicerrnn AvgPool1dr<r=arangerrr bucketizerr')rareimg_Zvals_to_sampler`gridZ index_imgrprbrbrcrx s " ,zIntensityRemap.__call__)rrrzr{r|r}r_rxrrbrbrqrcrN scs>eZdZdZdddddd d d Zd d d fdd ZZS)rOa Transform for intensity remapping of images. The intensity at each pixel is replaced by a new values coming from an intensity remappping curve. The remapping curve is created by uniformly sampling values from the possible intensities for the input image and then adding a linear component. The curve is the rescaled to the input image intensity range. Implementation is described in the work: `Intensity augmentation for domain transfer of whole breast segmentation in MRI `_. Args: prob: probability of applying the transform. kernel_size: window size for averaging operation for the remapping curve. slope: slope of the linear component. Easiest to leave default value and tune the kernel_size parameter instead. channel_wise: set to True to treat each channel independently. rSrrTrUrrV)rXrrrcCs$tj||d||_||_||_dS)Nr)rr_rrr)rarXrrrrbrbrcr_= szRandIntensityRemap.__init__rrcsptdttdjrljrJtfddtt Dn"t j j j jgS)rNrtcs2g|]*}tjjj jg|qSrb)rNrrlrrrrerarbrcrM sz/RandIntensityRemap.__call__..)rirjr(r rkrrrrrrNrrlrrrrqrrcrxC s   "zRandIntensityRemap.__call__)rSrrTrrbrbrqrcrO& sc@sPeZdZdZejejgZdddddd d d Zd d Z ddZ ddddZ dS)rPa Creates a binary mask that defines the foreground based on thresholds in RGB or HSV color space. This transform receives an RGB (or grayscale) image where by default it is assumed that the foreground has low values (dark) while the background has high values (white). Otherwise, set `invert` argument to `True`. Args: threshold: an int or a float number that defines the threshold that values less than that are foreground. It also can be a callable that receives each dimension of the image and calculate the threshold, or a string that defines such callable from `skimage.filter.threshold_...`. For the list of available threshold functions, please refer to https://scikit-image.org/docs/stable/api/skimage.filters.html Moreover, a dictionary can be passed that defines such thresholds for each channel, like {"R": 100, "G": "otsu", "B": skimage.filter.threshold_mean} hsv_threshold: similar to threshold but HSV color space ("H", "S", and "V"). Unlike RBG, in HSV, value greater than `hsv_threshold` are considered foreground. invert: invert the intensity range of the input image, so that the dtype maximum is now the dtype minimum, and vice-versa. otsuNFz#dict | Callable | str | float | intz*dict | Callable | str | float | int | NonerVrW)r hsv_thresholdinvertr]cCsi|_|dk r`t|tr<|D]\}}|||q n$||d||d||d|dk rt|tr|D]\}}|||qzn$||d||d||ddd|jD|_|jtd rt d |jd ||_ dS) NrlGBHSVcSsi|]\}}|dk r||qSr^rb)rrvrbrbrc sz+ForegroundMask.__init__..ZRGBHSVzBThreshold for at least one channel of RGB or HSV needs to be set. z is provided.) thresholdsrdictitems_set_thresholdrkeys isdisjointsetrr)rarrrr:thrbrbrcr_n s*         zForegroundMask.__init__cCspt|r||j|<nXt|tr:ttjd||j|<n2t|tt frXt||j|<nt dt |ddS)N threshold_zB`threshold` should be either a callable, string, or float number, z was given.) callablerrr7getattrr*filtersrrUrrr)rarr:rbrbrcr s  zForegroundMask._set_thresholdcCs |j|}t|r||S|Sr^)rgetr)raimager:rrbrbrc_get_threshold s zForegroundMask._get_thresholdr )rc Cs0t|td}t|tj^}}|jr0tj|}g}|j t dst |dd}t |dD](\}}|||}|rdt|||k}qd|||j t dstjj|dd} t |dd} t | dD](\}}|||}|rt| ||k} q|| t|jdd} t| |ddS) NrtRGBrHSVr) channel_axisrr6)r(r r&rrrr*utilrrrr zeros_likerr logical_orrcolorrgb2hsvrallr') rarZimg_rgbrpZ foregroundsZrgb_foregroundrer:rZimg_hsvZhsv_foregroundrrbrbrcrx s,     zForegroundMask.__call__)rNF) rzr{r|r}rr~rrr_rrrxrbrbrbrcrPX s  cs8eZdZdZd dddfdd Zdd d d ZZS) rQaCompute horizontal and vertical maps from an instance mask It generates normalized horizontal and vertical distances to the center of mass of each region. Input data with the size of [1xHxW[xD]], which channel dim will temporarily removed for calculating coordinates. Args: dtype: the data type of output Tensor. Defaults to `"float32"`. Return: A torch.Tensor with the size of [2xHxW[xD]], which is stack horizontal and vertical maps rr rW)r[r]cst||_dSr^)rir_r[)rar[rqrbrcr_ s zComputeHoVerMaps.__init__r )rc Cs(t|tjd}|j|jdd}|j|jdd}|d}tj|D]}|j dddf|j d}|j dddf|j d}||dkt | <||dkt |<||dkt | <||dkt |<||||j k<||||j k<qFtt||gtd}|S)NrTrrrt)r&rrrr[r=r*measure regionpropsrcentroidaminamaxlabelr( concatenater ) rarZ instance_maskh_mapZv_mapregionZv_disth_distZhv_mapsrbrbrcrx s zComputeHoVerMaps.__call__)rrrbrbrqrcrQ s c@s:eZdZdZdddddd d d Zdd dd dddZd S)rRa#Compute confidence map from an ultrasound image. This transform uses the method introduced by Karamalis et al. in https://doi.org/10.1016/j.media.2012.07.005. It generates a confidence map by setting source and sink points in the image and computing the probability for random walks to reach the source for each pixel. Args: alpha (float, optional): Alpha parameter. Defaults to 2.0. beta (float, optional): Beta parameter. Defaults to 90.0. gamma (float, optional): Gamma parameter. Defaults to 0.05. mode (str, optional): 'RF' or 'B' mode data. Defaults to 'B'. sink_mode (str, optional): Sink mode. Defaults to 'all'. If 'mask' is selected, a mask must be when calling the transform. Can be one of 'all', 'mid', 'min', 'mask'. rV@皙?rrrUrW)r^betar(r]cCsv||_||_||_||_||_|jdkr:td|jd|jdkrVtd|jdt|j|j|j|j|j|_dS)N)rRFzUnknown mode: z#. Supported modes are 'B' and 'RF'.)rmidrrzUnknown sink mode: z5. Supported modes are 'all', 'mid', 'min' and 'mask'.)r^r r(r: sink_moderr_compute_conf_map)rar^r r(r:rrbrbrcr_ s   z)UltrasoundConfidenceMapTransform.__init__Nr r3rcCs|jdkr|dkrtd|jddkr0tdt|td}t|tj^}}|d}d}|dk rt|tj td}t|tj^}}|d}t |jd krtj |dd }|dk r|j|jkrtd | ||}t |tjkrt|}|S) a+Compute confidence map from an ultrasound image. Args: img (ndarray or Tensor): Ultrasound image of shape [1, H, W] or [1, D, H, W]. If the image has channels, they will be averaged before computing the confidence map. mask (ndarray or Tensor, optional): Mask of shape [1, H, W]. Defaults to None. Must be provided when sink mode is 'mask'. The non-zero values of the mask are used as sink points. Returns: ndarray or Tensor: Confidence map of shape [1, H, W]. rNz1A mask must be provided when sink mode is 'mask'.rrzr@rArBrCrDrErFrGrHrIrJrKrLrMrNrOrPrQrRrbrbrbrc s         ,9YE6=7YBD]k9?Lz6-)#68STL> NK(/72a)