
    9iT                        S r SSKrSSKJrJr  SSKJr  SSK	J
r
  SSKJr   SSKJr  \R                  R                   rS	 r\\R                  l        \R                  " 5       r SS
KJr  SrSSKJr  SSKJrJr  S rS rS rS rS r S r!S r"\RF                  " SS9      SSSS.S jj5       r$g! \ a    Sr NZf = f! \ a    Sr N_f = f)a  
Random walker segmentation algorithm

from *Random walks for image segmentation*, Leo Grady, IEEE Trans
Pattern Anal Mach Intell. 2006 Nov;28(11):1768-83.

Installing pyamg and using the 'cg_mg' mode of random_walker improves
significantly the performance.
    N)sparsendimage   )utils)warn)SCIPY_CG_TOL_PARAM_NAME)umfpackc                 <     [        U 5        g ! [         a     g f = f)N)old_delAttributeError)selfs    o/var/www/html/land-doc-ocr/venv/lib/python3.13/site-packages/skimage/segmentation/random_walker_segmentation.pynew_delr      s     	DM 		s    
)ruge_stuben_solverTF)img_as_float)cgspsolvec                    [         R                  " X-  U-  5      R                  XU45      n[         R                  " USSS24   R	                  5       USSS24   R	                  5       45      n[         R                  " USS2SS24   R	                  5       USS2SS24   R	                  5       45      n[         R                  " USS R	                  5       USS R	                  5       45      n[         R
                  " XEU45      nU$ )a  Returns a list of edges for a 3D image.

Parameters
----------
n_x : integer
    The size of the grid in the x direction.
n_y : integer
    The size of the grid in the y direction
n_z : integer
    The size of the grid in the z direction

Returns
-------
edges : (2, N) ndarray
    with the total number of edges::

        N = n_x * n_y * (nz - 1) +
            n_x * (n_y - 1) * nz +
            (n_x - 1) * n_y * nz

    Graph edges with each column describing a node-id pair.
.N   )nparangereshapevstackravelhstack)n_xn_yn_zvertices
edges_deepedges_right
edges_downedgess           r   _make_graph_edges_3dr%   4   s    . yyS)113S/BHHS#2#X.446ab8I8O8O8QRSJ))Xa"f-335x127L7L7NOPKHSbM//18AB<3E3E3GHIJIIz
;<EL    c                    [         R                  " S Vs/ s HC  nU R                  U   S:  d  M  [         R                  " U S   US9R	                  5       X   -  PME     snSS9S-  n[        SU R                  S   5       Ho  nU[         R                  " S Vs/ s HE  nU R                  U   S:  d  M  [         R                  " U SU4   US9R	                  5       X   -  PMG     snSS9S-  -  nMq     U* S	U R                  5       -  -  nU(       a&  U[         R                  " U R                  S   5      -  n[         R                  " X-  5      n	X-  n	U	* $ s  snf s  snf )
N)r   r   r   r   ).r   axisr   r   r   .
   )	r   concatenateshapediffr   rangestdsqrtexp)
dataspacingbetaepsmultichannelax	gradientschannelscale_factorweightss
             r   _compute_weights_3dr<   S   sh    	 $#B::b>A% EV2.446D#
 	
 	  DJJrN+NN ('zz"~) OBGGDg.R8>>@7;N'
  
	
	 , 5BO,L 	

2//ff\-.GNG8O=s   E/EE41Ec                    U R                   S S u  pVn[        XVU5      n[        XUSUS9n	UGb   [        R                  " USS S24   R                  5       US S 2S S24   R                  5       US S R                  5       /5      n
[        R                  " USSS 24   R                  5       US S 2SS 24   R                  5       USS  R                  5       /5      n[        R                  " X5      nUS S 2U4   X   p[        R                  " USS9u  pUR                  UR                   5      nXV-  U-  nUR                  5       nUS S S2   R                  5       n[        R                  " X45      n [        R                  " U UU44X4S	9nUR                  [        R
                  " UR                  S
S95      * 5        U$ )N   g|=)r4   r5   r6   .r   r   Treturn_inverser,   r   r(   )r,   r%   r<   r   r   r   logical_anduniquer   r   	csr_arraysetdiagsum)r2   r3   maskr4   r6   l_xl_yl_zr$   r;   mask0mask1ind_mask_inv_idxpixel_nb	i_indices	j_indiceslaps                      r   _build_laplacianrT   y   s   JJrNMCc 3/E!DgLG  		#ss(^!!#T!SbS&\%7%7%949??;LM
 		#qr']  "DABK$5$5$7ab9IJ
 >>%/q({+W->w YYuT:
, y3HIdd!!#I99g'(D


D9i"89(AU
VCKK#''q'/**+Jr&   c                    Uc  UR                  5       nOX$   n[        R                  " UR                  5      nUS:  nXx)    n	Xx   n
[	        XXEUS9nXSS24   nUSS2U	4   nUSS2U
4   * nX(   n[
        R                  " [        R                  " [        SUS-   5       Vs/ s H%  n[        R                  " X:H  5      R                  PM'     sn5      5      nX-  nUU4$ s  snf )zx
Build the matrix A and rhs B of the linear system to solve.
A and B are two block of the laplacian of the image graph.
Nr   )rG   r4   r6   r   )r   r   r   sizerT   r   	csc_arrayr   r.   
atleast_2dT)r2   r3   labelsnlabelsrG   r4   r6   indices
seeds_maskunlabeled_indicesseeds_indices
lap_sparserowsBseedslabrhss                    r   _build_linear_systemrf      s    
 |ii$G!J,'M!D,J *+Da**+J	a	AE!!
		E!Wq[<QR<QS2==.00<QRSJ .Cs?	 Ss   ",C!c                 x   Uc  SnUS:X  a  [         (       d  [        SSS9  SnUS:X  a%  [        XR                  5       5      R                  nU$ S nUS:X  a  [
        c
  [        SSS9  S nOUS:X  a9  U R                  S	   n[        R                  " S
U R                  5       -  S4Xw4S9nOC[        U [        R                  S5      u  U l        U l        [        U SS9nUR!                  SS9nSn["        U0n	[%        UR                  S   5       V
s/ s H*  n
['        XS S 2U
/4   R                  5       40 U	DSXeS.D6PM,     nn
[        R(                  " U VVs/ s H
  u  pUS:  PM     snn5      (       a
  [        SSS9  [        R*                  " U VVs/ s H  u  pUPM	     snn5      nU$ s  sn
f s  snnf s  snnf )Ncg_jcg_mgz_"cg_mg" not available, it requires pyamg to be installed. The "cg_j" mode will be used instead.r   
stacklevelbfr   z"cg" mode may be slow because UMFPACK is not available. Consider building Scipy with UMFPACK or use a preconditioned version of CG ("cg_j" or "cg_mg" modes).r         ?r   rA   z-index values too large for int32 mode 'cg_mg'pinv)coarse_solverV)cycle   r   )atolMmaxiterzsConjugate gradient convergence to tolerance not achieved. Consider decreasing beta to improve system conditionning.)
amg_loadedr   r   toarrayrY   UmfpackContextr,   r   	dia_arraydiagonal_safe_downcast_indicesr   int32r\   indptrr   aspreconditionerr   r.   r   anyasarray)r`   rb   tolmodeXru   rt   nmlrtolicg_outrN   infoxs                  r   _solve_linear_systemr      s   |wzz4	

 t|J		,..H HE 4<%N  !	 AV^  $A  #
(;(;(="=q!A!PA 5KBHH&U51J
 1 $JfEB####.AG'- 1771:&
& zQV9,,.U$UQ!U& 	 
 666264!86233L
 JJf-fdaf-.H
 3 .s   1F+F0
F6
c                 ~   [         R                  " U5      R                  nU R                  S   U:  a  [	        U5      e[        U R
                  6 U:  a3  [         R                  " U R                  U:  5      (       a  [	        U5      eU R                  R                  USS9nU R                  R                  USS9nXE4$ )Nr   F)copy)	r   iinfomaxr}   
ValueErrorr,   r   r\   astype)Aitypemsg	max_valuer\   r}   s         r   r{   r{      s    ##Ixx|io
AGG}y 66!))i'((S/!iiu51GXX__U_/F?r&   c           	         [         R                  " U SS9u  p[        U5      S::  a  [        S5      eUS:H  R	                  5       (       d  [        SSS9  U S S S S 4$ U S:H  nU S:  nU S:  n[        R                  " X5S9n[         R                  " U[         R                  " U5      5      nS	XG'   US   S:  d  [         R                  " U5      (       a  [         R                  " [         R                  " [        R                  " XES95      U5      nS
X'   [         R                  " Xs   5      (       a  [        SSS9  U S S S S 4$ S	XW'   [         R                  " U5      nOS n[         R                  " US5      n[         R                  " UR                  U R                  5      U-
  5      n XS-   S  R                  S   n	[         R                  " U5      n
X
   nX	XZU4$ )NTr?   r   zWNo seeds provided in label image: please ensure it contains at least one positive valuezRandom walker only segments unlabeled areas, where labels == 0. No zero valued areas in labels were found. Returning provided labels.r   rj   )rG   Fr   z_All unlabeled pixels are isolated, they could not be determined by the random walker algorithm.r   )r   rC   r   r   r   r   ndibinary_propagationrB   logical_notall
atleast_3dsearchsortedr   r,   nonzero)rZ   label_valuesrO   	null_maskpos_maskrG   fillisolatedzero_idxr[   inds_isolated_seedsisolated_valuess               r   _preprocessr      s   IIfTBL
<A6
 	

 A""$$0 		
 tT4--
 !IzHQ;D!!)7D~~ht(<=HH AbffX..>>NN311(FG
 66(%&&=
 4tT11}}T" |Q/H]]7??6<<88CDFa<>*003G**X.1ODFFr&   )multichannel_outputMbP?)prob_tolchannel_axisc          	         US;  a  [        U S35      eU R                  [        R                  :X  a  U R	                  [        R
                  SS9n Uc  [        R                  " S5      nO_[        U5      UR                  :X  a;  [        U5      S:X  a  [        R                  US4   n[        R                  " U5      nO[        S	5      eU	SLn
U
(       ds  U R                  S
;  a  [        S5      eU R                  UR                  :w  a  [        S5      e[        R                  " [        U 5      5      S[        R                  4   n O{U R                  S;  a  [        S5      eU R                  SS UR                  :w  a  [        S5      e[        U 5      n U R                  S:X  a  U SS2SS2[        R                  SS24   n UR                  nUR                  nU(       a  [        R                  " U5      n[!        U5      u  ppnUcb  U(       aY  [        R"                  " [        R$                  " U5       Vs/ s H$  nUS:  d  M  [        R                  " UU:H  5      PM&     snSS9$ U$ ['        XXXU
5      u  nn[)        UUXC5      nUR+                  5       U* :  d  UR-                  5       SU-   :  a  [/        S5        UX'   UR1                  U5      nUS:H  nSX'   U(       aJ  [        R2                  " U4U-   5      n[5        [7        UU5      SS9 H  u  nu  nnUUU'   SUUU:H  '   M     U$ [        R8                  " USS9S-   nUR	                  U5      nUUU'   U$ s  snf )a  Random walker algorithm for segmentation from markers.

Random walker algorithm is implemented for gray-level or multichannel
images.

Parameters
----------
data : (M, N[, P][, C]) ndarray
    Image to be segmented in phases. Gray-level `data` can be two- or
    three-dimensional; multichannel data can be three- or four-
    dimensional with `channel_axis` specifying the dimension containing
    channels. Data spacing is assumed isotropic unless the `spacing`
    keyword argument is used.
labels : (M, N[, P]) array of ints
    Array of seed markers labeled with different positive integers
    for different phases. Zero-labeled pixels are unlabeled pixels.
    Negative labels correspond to inactive pixels that are not taken
    into account (they are removed from the graph). If labels are not
    consecutive integers, the labels array will be transformed so that
    labels are consecutive. In the multichannel case, `labels` should have
    the same shape as a single channel of `data`, i.e. without the final
    dimension denoting channels.
beta : float, optional
    Penalization coefficient for the random walker motion
    (the greater `beta`, the more difficult the diffusion).
mode : string, available options {'cg', 'cg_j', 'cg_mg', 'bf'}
    Mode for solving the linear system in the random walker algorithm.

    - 'bf' (brute force): an LU factorization of the Laplacian is
      computed. This is fast for small images (<1024x1024), but very slow
      and memory-intensive for large images (e.g., 3-D volumes).
    - 'cg' (conjugate gradient): the linear system is solved iteratively
      using the Conjugate Gradient method from scipy.sparse.linalg. This is
      less memory-consuming than the brute force method for large images,
      but it is quite slow.
    - 'cg_j' (conjugate gradient with Jacobi preconditionner): the
      Jacobi preconditionner is applied during the Conjugate
      gradient method iterations. This may accelerate the
      convergence of the 'cg' method.
    - 'cg_mg' (conjugate gradient with multigrid preconditioner): a
      preconditioner is computed using a multigrid solver, then the
      solution is computed with the Conjugate Gradient method. This mode
      requires that the pyamg module is installed.
tol : float, optional
    Tolerance to achieve when solving the linear system using
    the conjugate gradient based modes ('cg', 'cg_j' and 'cg_mg').
copy : bool, optional
    If copy is False, the `labels` array will be overwritten with
    the result of the segmentation. Use copy=False if you want to
    save on memory.
return_full_prob : bool, optional
    If True, the probability that a pixel belongs to each of the
    labels will be returned, instead of only the most likely
    label.
spacing : iterable of floats, optional
    Spacing between voxels in each spatial dimension. If `None`, then
    the spacing between pixels/voxels in each dimension is assumed 1.
prob_tol : float, optional
    Tolerance on the resulting probability to be in the interval [0, 1].
    If the tolerance is not satisfied, a warning is displayed.
channel_axis : int or None, optional
    If None, the image is assumed to be a grayscale (single channel) image.
    Otherwise, this parameter indicates which axis of the array corresponds
    to channels.

    .. versionadded:: 0.19
       ``channel_axis`` was added in 0.19.

Returns
-------
output : ndarray
    * If `return_full_prob` is False, array of ints of same shape
      and data type as `labels`, in which each pixel has been
      labeled according to the marker that reached the pixel first
      by anisotropic diffusion.
    * If `return_full_prob` is True, array of floats of shape
      `(nlabels, labels.shape)`. `output[label_nb, i, j]` is the
      probability that label `label_nb` reaches the pixel `(i, j)`
      first.

See Also
--------
skimage.segmentation.watershed
    A segmentation algorithm based on mathematical morphology
    and "flooding" of regions from markers.

Notes
-----
Multichannel inputs are scaled with all channel data combined. Ensure all
channels are separately normalized prior to running this algorithm.

The `spacing` argument is specifically for anisotropic datasets, where
data points are spaced differently in one or more spatial dimensions.
Anisotropic data is commonly encountered in medical imaging.

The algorithm was first proposed in [1]_.

The algorithm solves the diffusion equation at infinite times for
sources placed on markers of each phase in turn. A pixel is labeled with
the phase that has the greatest probability to diffuse first to the pixel.

The diffusion equation is solved by minimizing x.T L x for each phase,
where L is the Laplacian of the weighted graph of the image, and x is
the probability that a marker of the given phase arrives first at a pixel
by diffusion (x=1 on markers of the phase, x=0 on the other markers, and
the other coefficients are looked for). Each pixel is attributed the label
for which it has a maximal value of x. The Laplacian L of the image
is defined as:

   - L_ii = d_i, the number of neighbors of pixel i (the degree of i)
   - L_ij = -w_ij if i and j are adjacent pixels

The weight w_ij is a decreasing function of the norm of the local gradient.
This ensures that diffusion is easier between pixels of similar values.

When the Laplacian is decomposed into blocks of marked and unmarked
pixels::

    L = M B.T
        B A

with first indices corresponding to marked pixels, and then to unmarked
pixels, minimizing x.T L x for one phase amount to solving::

    A x = - B x_m

where x_m = 1 on markers of the given phase, and 0 on other markers.
This linear system is solved in the algorithm using a direct method for
small images, and an iterative method for larger images.

References
----------
.. [1] Leo Grady, Random walks for image segmentation, IEEE Trans Pattern
    Anal Mach Intell. 2006 Nov;28(11):1768-83.
    :DOI:`10.1109/TPAMI.2006.233`.

Examples
--------
>>> rng = np.random.default_rng()
>>> a = np.zeros((10, 10)) + 0.2 * rng.random((10, 10))
>>> a[5:8, 5:8] += 1
>>> b = np.zeros_like(a, dtype=np.int32)
>>> b[3, 3] = 1  # Marker for first phase
>>> b[6, 6] = 2  # Marker for second phase
>>> random_walker(a, b)  # doctest: +SKIP
array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 2, 2, 2, 1, 1],
       [1, 1, 1, 1, 1, 2, 2, 2, 1, 1],
       [1, 1, 1, 1, 1, 2, 2, 2, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], dtype=int32)

)ri   r   rl   rh   NzK is not a valid mode. Valid modes are 'cg_mg', 'cg', 'cg_j', 'bf', and Nonesafe)castingNr>   r   rm   z`Input argument `spacing` incorrect, should be an iterable with one number per spatial dimension.)r   r>   z=For non-multichannel input, data must be of dimension 2 or 3.z$Incompatible data and labels shapes..)r>      z9For multichannel input, data must have 3 or 4 dimensions.r   r   r(   r   z{The probability range is outside [0, 1] given the tolerance `prob_tol`. Consider decreasing `beta` and/or decreasing `tol`.F)start)r   dtyper   float16r   float32oneslenndimr_r   r,   r   r   newaxisr   r   r+   rC   rf   r   minr   r   r   zeros	enumeratezipargmax)r2   rZ   r4   r   r   r   return_full_probr3   r   r   r6   labels_shapelabels_dtyper[   rG   r   r   rd   r`   rb   r   out
label_probprobs                           r   random_walkerr   <  s,   X 66f + ,
 	

 zzRZZ {{2::v{6 ''!*	W	$w<1eeGSL)G**W%>
 	
  t+L99F"R  ::%CDD}}\$/0bjjA99F"N  ::cr?fll*CDDD!99>1bjj!+,D<<L<<LDOPVDWAVd >>9;69JV9J#cTUg-v}-9JV   )vLMJ 	ZC6Auuw(aeegH4	
 #2F^^L)FQ;D %DhhzL01'0S!A'F#C#*d#Jt()Jv}% (G J	 IIaa 1$mmL)D	JQ Ws   9
M M )   rh   r   TFN)%__doc__numpyr   scipyr   r   r   _sharedr   _shared.utilsr   _shared.compatr   #scipy.sparse.linalg.dsolve.linsolver	   rx   __del__r   r   ImportErrorpyamgr   rv   utilr   scipy.sparse.linalgr   r   r%   r<   rT   rf   r   r{   r   channel_as_last_axisr    r&   r   <module>r      s    (    4;$$,,G &-G"++-N(J   +>#L@@1h <G~ 6 
		T T 7Tq  N  Js$   AB3 $C 3B>=B>CC