
    9iP                         S SK rS SKrS SKJr  S SKJr  S SKrSSK	J
r
JrJrJr  SSKJr  S rS rS	 r " S
 S\R&                  5      rSS jrSS jr\" SS5            SS j5       rg)    N)ndimage)sparse   )measuresegmentationutilcolor)requirec              #      #    U R                   S   nU R                  nU R                  nU R                  n[	        U5       H(  n[	        X5   X5S-      5       H  nXTU   X&   4v   M     M*     g7f)a  Yield weighted edge triples for use by NetworkX from a CSR matrix.

This function is a straight rewrite of
`networkx.convert_matrix._csr_gen_triples`. Since that is a private
function, it is safer to include our own here.

Parameters
----------
csr_array : scipy.sparse.csr_array
    The input matrix. An edge (i, j, w) will be yielded if there is a
    data value for coordinates (i, j) in the matrix, even if that value
    is 0.

Yields
------
i, j, w : (int, int, float) tuples
    Each value `w` in the matrix along with its coordinates (i, j).

Examples
--------

>>> dense = np.eye(2, dtype=float)
>>> csr = sparse.csr_array(dense)
>>> edges = _edge_generator_from_csr(csr)
>>> list(edges)
[(0, 0, 1.0), (1, 1, 1.0)]
r      N)shapedataindptrindicesrange)	csr_arraynrowsvaluesr   col_indicesijs          R/var/www/html/land-doc-ocr/venv/lib/python3.13/site-packages/skimage/graph/_rag.py_edge_generator_from_csrr      sl     8 OOAE^^FF##K5\vy&Q-0A^VY.. 1 s   A,A.c                     S[         R                  0nX   R                  X5      S   nX   R                  X$5      S   nS[        XV5      0$ )a@  Callback to handle merging nodes by choosing minimum weight.

Returns a dictionary with `"weight"` set as either the weight between
(`src`, `n`) or (`dst`, `n`) in `graph` or the minimum of the two when
both exist.

Parameters
----------
graph : RAG
    The graph under consideration.
src, dst : int
    The verices in `graph` to be merged.
n : int
    A neighbor of `src` or `dst` or both.

Returns
-------
data : dict
    A dict with the `"weight"` attribute set the weight between
    (`src`, `n`) or (`dst`, `n`) in `graph` or the minimum of the two when
    both exist.

weight)npinfgetmin)graphsrcdstndefaultw1w2s          r   
min_weightr'   0   sK    4  G	c	#H	-B	c	#H	-Bc"k""    c                     U R                  [        5      n U [        U 5      S-     nU  H3  nX2:w  d  M
  UR                  X#5      (       a  M"  UR	                  X#5        M5     g)a  Create edge in `graph` between central element of `values` and the rest.

Add an edge between the middle element in `values` and
all other elements of `values` into `graph`.  ``values[len(values) // 2]``
is expected to be the central value of the footprint used.

Parameters
----------
values : array
    The array to process.
graph : RAG
    The graph to add edges in.

Returns
-------
0 : float
    Always returns 0. The return value is required so that `generic_filter`
    can put it in the output array, but it is ignored by this filter.
r   g        )astypeintlenhas_edgeadd_edge)r   r    centervalues       r   _add_edge_filterr1   P   sS    ( ]]3FCK1$%F?5>>&#@#@NN6)  r(   c                      ^  \ rS rSrSrSU 4S jjr\SSS4S jrSU 4S jjrSU 4S jjr	U 4S	 jr
S
 rS rU 4S jrSrU =r$ )RAGl   a  The Region Adjacency Graph (RAG) of an image, subclasses :obj:`networkx.Graph`.

Parameters
----------
label_image : array of int
    An initial segmentation, with each region labeled as a different
    integer. Every unique value in ``label_image`` will correspond to
    a node in the graph.
connectivity : int in {1, ..., ``label_image.ndim``}, optional
    The connectivity between pixels in ``label_image``. For a 2D image,
    a connectivity of 1 corresponds to immediate neighbors up, down,
    left, and right, while a connectivity of 2 also includes diagonal
    neighbors. See :func:`scipy.ndimage.generate_binary_structure`.
data : :obj:`networkx.Graph` specification, optional
    Initial or additional edges to pass to :obj:`networkx.Graph`
    constructor. Valid edge specifications include edge list (list of tuples),
    NumPy arrays, and SciPy sparse matrices.
**attr : keyword arguments, optional
    Additional attributes to add to the graph.
Nc           	        > [         TU ]  " U40 UD6  U R                  5       S:X  a  SU l        O[	        U R                  5       5      U l        Ubp  [        R                  " UR                  U5      n[        R                  " SUR                  5      nUR                  SS9  [        R                  " U[        USUU 4S9  g g )Nr         ?T)writenearest)function	footprintmodeoutputextra_arguments)super__init__number_of_nodesmax_idmaxnodesndigenerate_binary_structurendimr   broadcast_tor   setflagsgeneric_filterr1   )selflabel_imageconnectivityr   attrfpr<   	__class__s          r   r?   RAG.__init__   s    &&!Q&DKdjjl+DK"..{/?/?NB __S+*;*;<FOO$O')!% #r(   Tc                    Uc  / nUc  0 n[        U R                  U5      5      n[        U R                  U5      5      nXx-  X1-
  n	U(       a  Un
O!U R                  5       n
U R                  U
5        U	 H   nU" XX+/UQ70 UD6nU R	                  XUS9  M"     U R
                  U   S   U R
                  U   S   -   U R
                  U
   S'   U R                  U5        U(       d  U R                  U5        U
$ )a  Merge node `src` and `dst`.

The new combined node is adjacent to all the neighbors of `src`
and `dst`. `weight_func` is called to decide the weight of edges
incident on the new node.

Parameters
----------
src, dst : int
    Nodes to be merged.
weight_func : callable, optional
    Function to decide the attributes of edges incident on the new
    node. For each neighbor `n` for `src` and `dst`, `weight_func` will
    be called as follows: `weight_func(src, dst, n, *extra_arguments,
    **extra_keywords)`. `src`, `dst` and `n` are IDs of vertices in the
    RAG object which is in turn a subclass of :obj:`networkx.Graph`. It is
    expected to return a dict of attributes of the resulting edge.
in_place : bool, optional
    If set to `True`, the merged node has the id `dst`, else merged
    node has a new id which is returned.
extra_arguments : sequence, optional
    The sequence of extra positional arguments passed to
    `weight_func`.
extra_keywords : dictionary, optional
    The dict of keyword arguments passed to the `weight_func`.

Returns
-------
id : int
    The id of the new node.

Notes
-----
If `in_place` is `False` the resulting node has a new id, rather than
`dst`.
)	attr_dictlabels)set	neighborsnext_idadd_noder.   rC   remove_node)rJ   r!   r"   weight_funcin_placer=   extra_keywordssrc_nbrsdst_nbrsrU   newneighborr   s                r   merge_nodesRAG.merge_nodes   s   Z " O!Nt~~c*+t~~c*+(SJ6	C,,.CMM#!H3+:>LD MM(4M8	 " JJsOH%

3(AA 	

3! 	S!
r(   c                    > Uc  UnOUR                  U5        [        TU ]  " U40 UD6  [        XR                  5      U l        g)z^Add node `n` while updating the maximum node id.

.. seealso:: :obj:`networkx.Graph.add_node`.N)updater>   rW   rB   rA   )rJ   r#   rR   rM   rO   s       r   rW   RAG.add_node   s@     IT"(i(![[)r(   c                    > Uc  UnOUR                  U5        [        TU ]  " X40 UD6  [        XU R                  5      U l        g)ziAdd an edge between `u` and `v` while updating max node id.

.. seealso:: :obj:`networkx.Graph.add_edge`.N)rc   r>   r.   rB   rA   )rJ   uvrR   rM   rO   s        r   r.   RAG.add_edge   sB     IT"++!,r(   c                 F   > [         TU ]  5       nU R                  Ul        U$ )zNCopy the graph with its max node id.

.. seealso:: :obj:`networkx.Graph.copy`.)r>   copyrA   )rJ   grO   s     r   rj   RAG.copy   s      GLN;;r(   c                     [        5       $ )a3  Return a fresh copy graph with the same data structure.

A fresh copy has no nodes, edges or graph attributes. It is
the same data structure as the current graph. This method is
typically used to create an empty version of the graph.

This is required when subclassing Graph with networkx v2 and
does not cause problems for v1. Here is more detail from
the network migrating from 1.x to 2.x document::

    With the new GraphViews (SubGraph, ReversedGraph, etc)
    you can't assume that ``G.__class__()`` will create a new
    instance of the same graph type as ``G``. In fact, the
    call signature for ``__class__`` differs depending on
    whether ``G`` is a view or a base class. For v2.x you
    should use ``G.fresh_copy()`` to create a null graph of
    the correct type---ready to fill with nodes and edges.

)r3   rJ   s    r   
fresh_copyRAG.fresh_copy  s    ( ur(   c                      U R                   S-   $ )zReturns the `id` for the new node to be inserted.

The current implementation returns one more than the maximum `id`.

Returns
-------
id : int
    The `id` of the new node to be inserted.
r   rA   rn   s    r   rV   RAG.next_id  s     {{Qr(   c                 $   > [         TU ]  U5        g)zAdd node `n` without updating the maximum node id.

This is a convenience method used internally.

.. seealso:: :obj:`networkx.Graph.add_node`.N)r>   rW   )rJ   r#   rO   s     r   _add_node_silentRAG._add_node_silent)  s     	r(   rr   )Nr   N)N)__name__
__module____qualname____firstlineno____doc__r?   r'   r`   rW   r.   rj   ro   rV   ru   __static_attributes____classcell__)rO   s   @r   r3   r3   l   sE    *> JX	*	-,
 r(   r3   c           
      *   [        XS9nU HI  nUR                  U   R                  U/S[        R                  " / SQ[        R
                  S9S.5        MK     [        R                  " UR                  5       H=  nX   nUR                  U   S==   S-  ss'   UR                  U   S==   X   -  ss'   M?     U H8  nUR                  U   S   UR                  U   S   -  UR                  U   S	'   M:     UR                  S
S9 H  u  pnUR                  U	   S	   UR                  U
   S	   -
  n[        R                  R                  U5      nUS:X  a  [        R                  US-  * U-  -  US'   Mo  US:X  a  XS'   M{  [        SU S35      e   U$ )a  Compute the Region Adjacency Graph using mean colors.

Given an image and its initial segmentation, this method constructs the
corresponding Region Adjacency Graph (RAG). Each node in the RAG
represents a set of pixels within `image` with the same label in `labels`.
The weight between two adjacent regions represents how similar or
dissimilar two regions are depending on the `mode` parameter.

Parameters
----------
image : ndarray, shape(M, N[, ..., P], 3)
    Input image.
labels : ndarray, shape(M, N[, ..., P])
    The labelled image. This should have one dimension less than
    `image`. If `image` has dimensions `(M, N, 3)` `labels` should have
    dimensions `(M, N)`.
connectivity : int, optional
    Pixels with a squared distance less than `connectivity` from each other
    are considered adjacent. It can range from 1 to `labels.ndim`. Its
    behavior is the same as `connectivity` parameter in
    ``scipy.ndimage.generate_binary_structure``.
mode : {'distance', 'similarity'}, optional
    The strategy to assign edge weights.

        'distance' : The weight between two adjacent regions is the
        :math:`|c_1 - c_2|`, where :math:`c_1` and :math:`c_2` are the mean
        colors of the two regions. It represents the Euclidean distance in
        their average color.

        'similarity' : The weight between two adjacent is
        :math:`e^{-d^2/sigma}` where :math:`d=|c_1 - c_2|`, where
        :math:`c_1` and :math:`c_2` are the mean colors of the two regions.
        It represents how similar two regions are.
sigma : float, optional
    Used for computation when `mode` is "similarity". It governs how
    close to each other two colors should be, for their corresponding edge
    weight to be significant. A very large value of `sigma` could make
    any two colors behave as though they were similar.

Returns
-------
out : RAG
    The region adjacency graph.

Examples
--------
>>> from skimage import data, segmentation, graph
>>> img = data.astronaut()
>>> labels = segmentation.slic(img)
>>> rag = graph.rag_mean_color(img, labels)

References
----------
.. [1] Alain Tremeau and Philippe Colantoni
       "Regions Adjacency Graph Applied To Color Image Segmentation"
       :DOI:`10.1109/83.841950`
)rL   r   )r   r   r   )dtype)rS   pixel counttotal colorr   r   r   z
mean colorTr   
similarityr   r   distancez
The mode 'z' is not recognised)r3   rC   rc   r   arrayfloat64ndindexr   edgeslinalgnormmathe
ValueError)imagerS   rL   r;   sigmar    r#   indexcurrentxyddiffs                r   rag_mean_colorr   2  s   t 2EA# !xx	D	
  FLL)-G]+q0+G]+u|;+ *
 KKN=)EKKN=,II 	A|$ 
 ;;D;)a{{1~l+ekk!n\.JJyy~~d#<&&tQwZ%%78AhKZhKz$/BCDD * Lr(   c                 X   [         R                  " U R                  U5      n[         R                  " XS9n[         R                  " XS9nX@:g  nXP:g  n[
        R                  " XF   X   45      n[
        R                  " X   XW   45      n	[
        R                  " U	5      S-   n
[
        R                  " SUR                  5      n[        R                  " XU	44[        X4S9n[
        R                  " X   X   45      n[        R                  " XU	445      nU=R                  UR                  -  sl        [        5       nUR                  [!        U5      SS9  UR                  [!        U5      SS9  UR#                  5        H$  n
UR"                  U
   R%                  SU
/05        M&     U$ )	a  Comouter RAG based on region boundaries

Given an image's initial segmentation and its edge map this method
constructs the corresponding Region Adjacency Graph (RAG). Each node in the
RAG represents a set of pixels within the image with the same label in
`labels`. The weight between two adjacent regions is the average value
in `edge_map` along their boundary.

labels : ndarray
    The labelled image.
edge_map : ndarray
    This should have the same shape as that of `labels`. For all pixels
    along the boundary between 2 adjacent regions, the average value of the
    corresponding pixels in `edge_map` is the edge weight between them.
connectivity : int, optional
    Pixels with a squared distance less than `connectivity` from each other
    are considered adjacent. It can range from 1 to `labels.ndim`. Its
    behavior is the same as `connectivity` parameter in
    `scipy.ndimage.generate_binary_structure`.

Examples
--------
>>> from skimage import data, segmentation, filters, color, graph
>>> img = data.chelsea()
>>> labels = segmentation.slic(img)
>>> edge_map = filters.sobel(color.rgb2gray(img))
>>> rag = graph.rag_boundary(labels, edge_map)

)r:   r   r6   )r   r   r   )r   countrS   )rD   rE   rF   grey_erosiongrey_dilationr   concatenaterB   rG   r   r   r   r+   r   r3   add_weighted_edges_fromr   rC   rc   )rS   edge_maprL   connerodeddilatedboundaries0boundaries1labels_smalllabels_larger#   onescount_matrixr   graph_matrixrags                   r   rag_boundaryr     s~   > ((lCDf5F7G"K#K>>6#68K"LML>>6#68L"MNL
|q A ??3 2 23D##	l+,CvL >>80(2GHID##T,+G$HIL***
%C 8 FxX 8 FwWYY[		!XsO,  Jr(   
matplotlibz>=3.3c	           	      \   SSK Jn	  SSK Jn
  SSKJn  U(       d  UR                  5       nUc  U
R                  5       u  p[        R                  " USS9nUc?  UR                  S:  d  UR                  S	   S
;  a  Sn[        U5      eUSS2SS2SS24   nO;U
R                  U5      n[        R                  " U5      nU" U5      SS2SS2SS24   nU
R                  U5      nSn[        R                   " U R#                  5       S-   5      nUR%                  SS9 H  u  nnUS    H  nUUU'   M
     US-  nM     UU    n[&        R(                  " U5      n[+        UR%                  SS9U5       H(  u  u  nnn[-        [/        [0        US   5      5      US'   M*     U	R3                  5       nUb'  UR5                  U5      n[6        R8                  " UUUS9nUR;                  U5        UR=                  5        VVs/ s H6  u  nnUR$                  U   S   SSS2   UR$                  U   S   SSS2   /PM8     nnnU" UXES9nUR=                  SS9 VVVs/ s H  u  nnnUS   PM     nnnnUR?                  [        R@                  " U5      5        URC                  U5        U$ s  snnf s  snnnf )a  Show a Region Adjacency Graph on an image.

Given a labelled image and its corresponding RAG, show the nodes and edges
of the RAG on the image with the specified colors. Edges are displayed between
the centroid of the 2 adjacent regions in the image.

Parameters
----------
labels : ndarray, shape (M, N)
    The labelled image.
rag : RAG
    The Region Adjacency Graph.
image : ndarray, shape (M, N[, 3])
    Input image. If `colormap` is `None`, the image should be in RGB
    format.
border_color : color spec, optional
    Color with which the borders between regions are drawn.
edge_width : float, optional
    The thickness with which the RAG edges are drawn.
edge_cmap : :py:class:`matplotlib.colors.Colormap`, optional
    Any matplotlib colormap with which the edges are drawn.
img_cmap : :py:class:`matplotlib.colors.Colormap`, optional
    Any matplotlib colormap with which the image is draw. If set to `None`
    the image is drawn as it is.
in_place : bool, optional
    If set, the RAG is modified in place. For each node `n` the function
    will set a new attribute ``rag.nodes[n]['centroid']``.
ax : :py:class:`matplotlib.axes.Axes`, optional
    The axes to draw on. If not specified, new axes are created and drawn
    on.

Returns
-------
lc : :py:class:`matplotlib.collections.LineCollection`
     A collection of lines that represent the edges of the graph. It can be
     passed to the :meth:`matplotlib.figure.Figure.colorbar` function.

Examples
--------
.. testsetup::
    >>> import pytest; _ = pytest.importorskip('matplotlib')

>>> from skimage import data, segmentation, graph
>>> import matplotlib.pyplot as plt
>>>
>>> img = data.coffee()
>>> labels = segmentation.slic(img)
>>> g =  graph.rag_mean_color(img, labels)
>>> lc = graph.show_rag(labels, g, img)
>>> cbar = plt.colorbar(lc)
r   )colors)pyplot)LineCollectionNT)
force_copy   r   )r      z;If colormap is `None`, an RGB or RGBA image should be givenr   r   rS   centroid)r	   )
linewidthscmapr   )"r   r   r   matplotlib.collectionsr   rj   subplotsr   img_as_floatrF   r   r   get_cmapr	   rgb2grayr   arangerB   rC   r   regionpropsziptuplemapr+   ColorConverterto_rgbr   mark_boundariesimshowr   	set_arrayr   add_collection) rS   r   r   border_color
edge_width	edge_cmapimg_cmaprZ   axr   pltr   figoutmsgoffset	map_arrayr#   r   label
rag_labelsregionsr   regionccn1n2lineslcr   r   edge_weightss                                    r   show_ragr     s   ~ "(5hhj	z,,.


Ed
3C::>U[[^69OCS/!Aq"1"Ho<<)nnU#smAq"1"H%Y'I F		&**,*+I		t	$1x[E%Ie !! %
 6"J!!*-G !5w?	D6 S&*<!=>Z @ 
			 Byy.**3
,OIIcN 		#HR 
2z	"4R4	(#))B-
*CDbD*IJ# 
 
 
*	EB/2yydy/CD/CGAq!AhK/CLDLL,'(bI Es   8=J!J')r   r   g     o@)r   )blackg      ?magmaboneTN)networkxnxnumpyr   scipyr   rD   r   r    r   r   r   r	   _shared.version_requirementsr
   r   r'   r1   Graphr3   r   r   r    r(   r   <module>r      s          1 1 2"/J#@8C"(( CLYx9x 	w
 z  zr(   