+
    Aib                         ^ RI Ht ^ RIt^ RIt^ RIt^ RIt^ RIH	t	 R t
R tR tR tRR ltR	 tRR
 ltRR ltR R ltR tR!R ltR tR"R ltR tR tR tR tR#R ltR$R ltR tR tR%R ltR t R t!R t"R# )&    )ImageNwrapsc                0   a  \        S 4      V 3R l4       pV# )aD  Creates a new function which operates on each channel

Parameters
----------
single_channel_func: function
    Function that acts on a single color channel

Returns
-------
channel_func: function
    The same function that operates on all color channels

Example
-------
>>> from pymatting import *
>>> import numpy as np
>>> from scipy.signal import convolve2d
>>> single_channel_fun = lambda x: convolve2d(x, np.ones((3, 3)), 'valid')
>>> multi_channel_fun = apply_to_channels(single_channel_fun)
>>> I = np.random.rand(480, 320, 3)
>>> multi_channel_fun(I).shape
(478, 318, 3)
c                    < \        V P                  4      ^8X  d   S! V .VO5/ VB # V P                  pV P                  V^ ,          V^,          R4      p \        P                  ! \        V P                  ^,          4       Uu. uF'  pS! V RRV3,          P                  4       .VO5/ VB NK)  	  up^R7      pVP                  \        VP                  R,          4      \        VR,          4      ,           4      # u upi )   NNNaxisNr   N:r   NN)lenshapereshapenpstackrangecopylist)imageargskwargsr   cresultsingle_channel_funcs   &*,   Q/var/www/html/photoedit/myenv/lib/python3.14/site-packages/pymatting/util/util.pymulti_channel_func-apply_to_channels.<locals>.multi_channel_func"   s    u{{q &u>t>v>>KKEMM%(E!Hb9EXX #5;;q>22 (aAg(;(;(=OOO2 F >>$v||B'7"84b	?"JKKs   -C;r   )r   r   s   f r   apply_to_channelsr   	   s'    2 L  L"     c                0    \         P                  ! RW4      # )a  Computes the dot product of two vectors.

Parameters
----------
a: numpy.ndarray
    First vector (if np.ndim(a) > 1 the function calculates the product for the two last axes)
b: numpy.ndarray
    Second vector (if np.ndim(b) > 1 the function calculates the product for the two last axes)

Returns
-------
product: scalar
    Dot product of `a` and `b`

Example
-------
>>> import numpy as np
>>> from pymatting import *
>>> a = np.ones(2)
>>> b = np.ones(2)
>>> vec_vec_dot(a,b)
2.0
z...i,...i->...r   einsumabs   &&r   vec_vec_dotr'   7   s    0 99%q,,r    c                0    \         P                  ! RW4      # )a  Calculates the matrix vector product for two arrays.

Parameters
----------
A: numpy.ndarray
    Matrix (if np.ndim(A) > 2 the function calculates the product for the two last axes)
b: numpy.ndarray
    Vector (if np.ndim(b) > 1 the function calculates the product for the two last axes)

Returns
-------
product: numpy.ndarray
    Matrix vector product of both arrays

Example
-------
>>> import numpy as np
>>> from pymatting import *
>>> A = np.eye(2)
>>> b = np.ones(2)
>>> mat_vec_dot(A,b)
array([1., 1.])
z...ij,...j->...ir"   )Ar&   s   &&r   mat_vec_dotr*   R   s    0 99'..r    c                0    \         P                  ! RW4      # )a  Computes the outer product of two vectors

a: numpy.ndarray
    First vector (if np.ndim(b) > 1 the function calculates the product for the two last axes)
b: numpy.ndarray
    Second vector (if np.ndim(b) > 1 the function calculates the product for the two last axes)

Returns
-------
product: numpy.ndarray
    Outer product of `a` and `b` as numpy.ndarray

Example
-------
>>> import numpy as np
>>> from pymatting import *
>>> a = np.arange(1,3)
>>> b = np.arange(1,3)
>>> vec_vec_outer(a,b)
array([[1, 2],
       [2, 4]])
z	...i,...jr"   r$   s   &&r   vec_vec_outerr,   m   s    . 99[!''r    c                    V^ 8  g   V^8  d   \        R4      hV^ 8  g   V^8  d   \        R4      hW8  d   \        R4      hW8  pW8  pR\        P                  ! V 4      ,          p^WT&   ^ WS&   V# )a  Fixes broken trimap :math:`T` by thresholding the values

.. math::
    T^{\text{fixed}}_{ij}=
    \begin{cases}
        0,&\text{if } T_{ij}<\text{lower\_threshold}\\
        1,&\text{if }T_{ij}>\text{upper\_threshold}\\
        0.5, &\text{otherwise}.\\
    \end{cases}


Parameters
----------
trimap: numpy.ndarray
    Possibly broken trimap
lower_threshold: float
    Threshold used to determine background pixels, defaults to 0.1
upper_threshold: float
    Threshold used to determine foreground pixels, defaults to 0.9

Returns
-------
fixed_trimap: numpy.ndarray
    Trimap having values in :math:`\{0, 0.5, 1\}`

Example
-------
>>> from pymatting import *
>>> import numpy as np
>>> trimap = np.array([0,0.1, 0.4, 0.9, 1])
>>> fix_trimap(trimap, 0.2, 0.8)
array([0. , 0. , 0.5, 1. , 1. ])
zInvalid lower thresholdzInvalid upper thresholdz4Lower threshold must be smaller than upper thresholdg      ?)
ValueErrorr   	ones_like)trimaplower_thresholdupper_thresholdis_bgis_fgfixeds   &&&   r   
fix_trimapr6      s    D o1233o1233(OPP$E$E",,v&&EELELLr    c                B     \        V 4       R#   \         d     R# i ; i)a  Checks if an object is iterable

Parameters
----------
obj: object
    Object to check

Returns
-------
is_iterable: bool
    Boolean variable indicating whether the object is iterable

Example
-------
>>> from pymatting import *
>>> l = []
>>> isiterable(l)
True
TF)iter	TypeError)objs   &r   
isiterabler;      s#    (S	 s    c                    R \         P                  R\         P                  R\         P                  R\         P                  R\         P
                  R\         P                  R\         P                  /p\        V4      '       g9   \        V P                  V,          4      \        V P                  V,          4      3pV P                  WVP                  4       ,          4      p V # )bicubicbilinearboxhamminglanczosnearestnone)r   BICUBICBILINEARBOXHAMMINGLANCZOSNEARESTr;   intwidthheightresizelower)r   sizeresamplefilterss   &&& r   _resize_pil_imagerR      s    5==ENNuyy5==5==5==G dEKK$&'U\\D-@)ABLLx~~'789ELr    c                    \         P                  ! V 4      pVe-   VP                  4       pVR8X  d   RMTpVP                  V4      pVe   \	        WBV4      p\
        P                  ! V4      R,          pV# )zThis function can be used to load an image from a file.

Parameters
----------
path: str
    Path of image to load.
mode: str
    Can be "GRAY", "RGB" or something else (see PIL.convert())

Returns
-------
image: numpy.ndarray
    Loaded image
GRAYLg     o@)r   openupperconvertrR   r   array)pathmoderO   rP   r   s   &&&& r   
load_imager\      sg      JJtEzz|fns$d#!%x8HHUOe#ELr    c                H   VP                   \        P                  \        P                  \        P                  39   g   Q hVP                   \        P                  \        P                  39   d=   \        P
                  ! V^,          ^ ^4      P                  \        P                  4      pV'       dJ   \        P                  P                  V 4      w  r4\        V4      ^ 8  d   \        P                  ! VRR7       \        P                  ! V4      P                  V 4       R# )ax  Given a path, save an image there.

Parameters
----------
path: str
    Where to save the image.
image: numpy.ndarray, dtype in [np.uint8, np.float32, np.float64]
    Image to save.
    Images of float dtypes should be in range [0, 1].
    Images of uint8 dtype should be in range [0, 255]
make_directory: bool
    Whether to create the directories needed for the image path.
T)exist_okN)dtyper   uint8float32float64clipastypeosrZ   splitr   makedirsr   	fromarraysave)rZ   r   make_directory	directory_s   &&&  r   
save_imagerm     s     ;;288RZZ<<<<{{rzz2::..Q,33BHH=ww}}T*	y>AKK	D1	OOE%r    c                   \        V P                  4      R9   g   Q hV P                  \        P                  \        P
                  \        P                  39   g   Q hV P                  \        P
                  \        P                  39   d=   \        P                  ! V ^,          ^ ^4      P                  \        P                  4      p \        V P                  4      ^8X  d!   \        P                  ! V .^,          ^R7      # V P                  ^,          ^8X  d!   \        P                  ! V .^,          ^R7      # V P                  ^,          ^8X  d   V # V P                  ^,          ^8X  d
   V R,          # \        RV P                  4      h)a  Convertes an image to rgb8 color space

Parameters
----------
image: numpy.ndarray
    Image to convert

Returns
-------
image: numpy.ndarray
    Converted image with same height and width as input image but with three color channels
Example
-------
>>> from pymatting import *
>>> import numpy as np
>>> I = np.eye(2)
>>> to_rgb8(I)
array([[[255, 255, 255],
        [  0,   0,   0]],
       [[  0,   0,   0],
        [255, 255, 255]]], dtype=uint8)
r
   zInvalid image shape:)r      )r	   r	   :Nro   N)r   r   r_   r   r`   ra   rb   rc   rd   r   concatenater.   )r   s   &r   to_rgb8rq   "  s   . u{{v%%%;;288RZZ<<<<{{rzz2::..Q,33BHH=
5;;1xx!!,,{{1~~~ugk22	Q1		Q1	X
+U[[
99r    c           	        V  F:  pVf   K	  VP                   \        P                  \        P                  39   d   K:  Q h	  \	        V 4      pV^ 8X  d   R# VfO   VfK   \        \        P                  ! \        P                  ! V4      4      4      pWQ,           ^,
          V,          pM5Vf   WQ,           ^,
          V,          pMVf   WR,           ^,
          V,          pV  Uu. uF  qDf   K  VP                  NK  	  pp\        R V 4       4      p\        R V 4       4      p\        V U	u. uF  p	\	        V	4      ^8  g   K  V	^,          NK   	  up	^R7      p
V
^8  d   \        V 4       F  w  rVf   K  \	        VP                  4      ^8X  d   VRR\        P                  3,          pVP                  ^,          ^8X  d!   \        P                  ! V.V
,          ^R7      pVP                  ^,          ^8X  dE   V
^8X  d>   \        V\        P                  ! VP                  R,          VP                   R7      4      pW@V&   K  	  Vf   \        R	 V  4       4      p\        P                   ! Wr,          W,          V
3VR7      p\#        V4       F  p\#        V4       F  pWV,          ,           pV\	        V 4      8  d    K3  W,          pVf   K3  VP%                  VP                  ^ ,          VP                  ^,          R
4      pVVW,          W,          VP                  ^ ,          ,           1W,          W,          VP                  ^,          ,           13&   K  	  K  	  VP                  ^,          ^8X  d
   VR,          pV# u upi u up	i )a  Plots a grid of images.

Parameters
----------
images : list of numpy.ndarray
    List of images to plot
nx: int
    Number of rows
ny: int
    Number of columns
dtype: type
    Data type of output array

Returns
-------
grid: numpy.ndarray
   Grid of images with datatype `dtype`
Nc              3   2   "   T F  q^ ,          x  K  	  R# 5i)r   N .0r   s   & r   	<genexpr>make_grid.<locals>.<genexpr>v       )&!HH&   c              3   2   "   T F  q^,          x  K  	  R# 5i)   Nrt   ru   s   & r   rw   rx   w  ry   rz   )defaultr	   r
   r   r_   c              3   D   "   T F  qf   K  VP                   x  K  	  R # 5i)Nr~   )rv   r   s   & r   rw   rx     s     JfU[U[[fs     r   )r	   r	   r   )r_   r   ra   rb   r   rJ   ceilsqrtr   max	enumeratenewaxisrp   stack_imagesonesnextzerosr   r   )imagesnxnyr_   r   nshapeshwr   dir   yxs   &&&&           r   	make_gridr   N  s   & ;;2::rzz"::::  	FAAv	zbj$%fqjR	fqjR	fqjR'-CvekekkvFC)&))A)&))A6<6%SZ!^XU1XX6<aHA1u!&)HA u{{#q(!!Q

"23E;;q>Q&NNE7Q;Q?E;;q>Q&16(rwwu{{2ekkJE "q	 * }JfJJXXqvqvq)7F2YrAF
ACKIE ekk!nekk!nbI  EAEEKKN22AEAEEKKPQN<R4RR    ||A!M] D =s    M?*M?)N Nc                    \        V 4      p\        P                  ! V^,          ^ ^4      P                  \        P                  4      p\
        P                  ! V4      pVP                  4        R# )zPlot grid of images.

Parameters
----------
images : list of numpy.ndarray
    List of images to plot
height : int, matrix
    Height in pixels the output grid, defaults to 512

N)r   r   rc   rd   r`   r   rh   show)r   grids   & r   show_imagesr     sJ     VD774#:q#&--bhh7D??4 DIIKr    c                   V'       d   V P                  4       p V P                  4       pV P                  4       pVR8  d    \        P                  ! RV,          ^R7       VR8  d    \        P                  ! RV,          ^R7       V P
                  \        P                  \        P                  39  d*   \        P                  ! RV P
                  ,          ^R7       W8  pW8*  pVP                  4       ^ 8X  d   \        RV,          4      hVP                  4       ^ 8X  d   \        RV,          4      hWg,          pV( p	WgW3# )	a~  This function splits the trimap into foreground pixels, background pixels, and unknown pixels.

Foreground pixels are pixels where the trimap has values larger than or equal to `fg_threshold` (default: 0.9).
Background pixels are pixels where the trimap has values smaller than or equal to `bg_threshold` (default: 0.1).
Pixels with other values are assumed to be unknown.

Parameters
----------
trimap: numpy.ndarray
    Trimap with shape :math:`h \times w`
flatten: bool
    If true np.flatten is called on the trimap

Returns
-------
is_fg: numpy.ndarray
    Boolean array indicating which pixel belongs to the foreground
is_bg: numpy.ndarray
    Boolean array indicating which pixel belongs to the background
is_known: numpy.ndarray
    Boolean array indicating which pixel is known
is_unknown: numpy.ndarray
    Boolean array indicating which pixel is unknown
bg_threshold: float
    Pixels with smaller trimap values will be considered background.
fg_threshold: float
    Pixels with larger trimap values will be considered foreground.


Example
-------
>>> import numpy as np
>>> from pymatting import *
>>> trimap = np.array([[1,0],[0.5,0.2]])
>>> is_fg, is_bg, is_known, is_unknown = trimap_split(trimap)
>>> is_fg
array([ True, False, False, False])
>>> is_bg
array([False,  True, False, False])
>>> is_known
array([ True,  True, False, False])
>>> is_unknown
array([False, False,  True,  True])
        z:Trimap values should be in [0, 1], but trimap.min() is %s.
stacklevel      ?z:Trimap values should be in [0, 1], but trimap.max() is %s.zfUnexpected trimap.dtype %s. Are you sure that you do not want to use np.float32 or np.float64 instead?z7Trimap did not contain background values (values <= %f)z7Trimap did not contain foreground values (values >= %f))flattenminr   warningswarnr_   r   ra   rb   sumr.   )
r0   r   bg_thresholdfg_threshold	min_value	max_valuer4   r3   is_known
is_unknowns
   &&&&      r   trimap_splitr     s   Z !

I

I3H9T	

 3H9T	

 ||BJJ

33tll	
 "E"Eyy{aET
 	
 yy{aET
 	
 }HJ--r    c                Z   \        V P                  4      ^8w  g   V P                  ^,          ^8w  d3   \        P                  ! R\	        V P                  4      ,          ^R7       V P                  4       pV P                  4       pVR8  d    \        P                  ! RV,          ^R7       VR8  d    \        P                  ! RV,          ^R7       V P                  \        P                  \        P                  39  d,   \        P                  ! RV P                  ,          ^R7       R# R# )	aG  Performs a sanity check for input images. Image values should be in the
range [0, 1], the `dtype` should be `np.float32` or `np.float64` and the
image shape should be `(?, ?, 3)`.

Parameters
----------
image: numpy.ndarray
    Image with shape :math:`h \times w \times 3`

Example
-------
>>> import numpy as np
>>> from pymatting import check_image
>>> image = (np.random.randn(64, 64, 2) * 255).astype(np.int32)
>>> sanity_check_image(image)
__main__:1: UserWarning: Expected RGB image of shape (?, ?, 3), but image.shape is (64, 64, 2).
__main__:1: UserWarning: Image values should be in [0, 1], but image.min() is -933.
__main__:1: UserWarning: Image values should be in [0, 1], but image.max() is 999.
__main__:1: UserWarning: Unexpected image.dtype int32. Are you sure that you do not want to use np.float32 or np.float64 instead?

z=Expected RGB image of shape (?, ?, 3), but image.shape is %s.r   r   z8Image values should be in [0, 1], but image.min() is %s.r   z8Image values should be in [0, 1], but image.max() is %s.zeUnexpected image.dtype %s. Are you sure that you do not want to use np.float32 or np.float64 instead?N)r   r   r   r   strr   r   r_   r   ra   rb   )r   r   r   s   &  r   sanity_check_imager     s    . 5;;1A! 3K%++	
 		I		I3FR	

 3FR	

 {{2::rzz22skk	
 3r    c                    \        VP                  4      ^8X  d   VRR\        P                  3,          pW ,          ^V,
          V,          ,           # )a  This function composes a new image for given foreground image, background image and alpha matte.

This is done by applying the composition equation

.. math::
    I = \alpha F + (1-\alpha)B.

Parameters
----------
foreground: numpy.ndarray
    Foreground image
background: numpy.ndarray
    Background image
alpha: numpy.ndarray
    Alpha matte

Returns
-------
image: numpy.ndarray
    Composed image as numpy.ndarray

Example
-------
>>> from pymatting import *
>>> foreground = load_image("data/lemur/lemur_foreground.png", "RGB")
>>> background = load_image("data/lemur/beach.png", "RGB")
>>> alpha = load_image("data/lemur/lemur_alpha.png", "GRAY")
>>> I = blend(foreground, background, alpha)
r	   )r   r   r   r   )
foreground
backgroundalphas   &&&r   blendr   E  sA    < 5;;1aBJJ&'Uj 888r    c                     V  Uu. uF9  p\        VP                  4      ^8X  d   TMVRR\        P                  3,          NK;  	  p p\        P                  ! V ^R7      # u upi )a  This function stacks images along the third axis.
This is useful for combining e.g. rgb color channels or color and alpha channels.

Parameters
----------
*images: numpy.ndarray
    Images to be stacked.

Returns
-------
image: numpy.ndarray
    Stacked images as numpy.ndarray

Example
-------
>>> from pymatting.util.util import stack_images
>>> import numpy as np
>>> I = stack_images(np.random.rand(4,5,3), np.random.rand(4,5,3))
>>> I.shape
(4, 5, 6)
r	   r
   )r   r   r   r   rp   )r   r   s   * r   r   r   i  sa    0 E ekk"a'U1a3C-D	D   >>&q))	s   ?Ac                    V P                  \        P                  ! V P                  ^,          V P                  4      4      pV# )a  Calculate the sum of each row of a matrix

Parameters
----------
A: np.ndarray or scipy.sparse.spmatrix
    Matrix to sum rows of

Returns
-------
row_sums: np.ndarray
    Vector of summed rows

Example
-------
>>> from pymatting import *
>>> import numpy as np
>>> A = np.random.rand(2,2)
>>> A
array([[0.62750946, 0.12917617],
       [0.8599449 , 0.5777254 ]])
>>> row_sum(A)
array([0.75668563, 1.4376703 ])
)dotr   r   r   r_   )r)   row_sumss   & r   row_sumr     s.    0 uuRWWQWWQZ12HOr    c                    \        V 4      pRW"V8  &   RV,          p\        P                  P                  V4      pVP	                  V 4      p V # )a  Normalize the rows of a matrix

Rows with sum below threshold are left as-is.

Parameters
----------
A: scipy.sparse.spmatrix
    Matrix to normalize
threshold: float
    Threshold to avoid division by zero

Returns
-------
A: scipy.sparse.spmatrix
    Matrix with normalized rows

Example
-------
>>> from pymatting import *
>>> import numpy as np
>>> A = np.arange(4).reshape(2,2)
>>> normalize_rows(A)
array([[0. , 1. ],
       [0.4, 0.6]])
r   )r   scipysparsediagsr   )r)   	thresholdr   row_normalization_factorsDs   &&   r   normalize_rowsr     sM    4 qzH &)H	!" #h45A	aAHr    c                R   V'       dZ   \         P                  ! \         P                  ! V 4      V4      p\         P                  ! \         P                  ! V4      V 4      pW43# \         P                  ! V 4      p\         P                  ! V4      p\         P                  ! W44      w  r4W43# )a  Calculates image pixel coordinates for an image with a specified shape

Parameters
----------
width: int
    Width of the input image
height: int
    Height of the input image
flatten: bool
    Whether the array containing the coordinates should be flattened or not, defaults to False

Returns
-------
x: numpy.ndarray
    x coordinates
y: numpy.ndarray
    y coordinates

Example
-------
>>> from pymatting import *
>>> x, y = grid_coordinates(2,2)
>>> x
array([[0, 1],
       [0, 1]])
>>> y
array([[0, 0],
       [1, 1]])
)r   tilearangerepeatmeshgrid)rK   rL   r   r   r   s   &&&  r   grid_coordinatesr     sw    < GGBIIe$f-IIbii'/ 4K IIeIIf{{1 4Kr    c                *   \         P                  ! V4      P                  4       p\        V4      pW,          p\         P                  ! Wv,          \         P
                  R7      p\         P                  ! Wv,          \         P
                  R7      p	\         P                  ! Wv,          \         P                  R7      p
^ p\        WRR7      w  r\        W4V4       F  w  rp\         P                  ! W,           ^ V ^,
          4      p\         P                  ! W,           ^ V^,
          4      pWV ,          ,           WW,           % VVV ,          ,           WW,           % VWW,           % W,          pK  	  \        P                  P                  WV	33Ww3R7      pV# )aj  Calculates a convolution matrix that can be applied to a vectorized image

Additionally, this function allows to specify which pixels should be used for the convoltion, i.e.

.. math:: \left(I * K\right)_{ij} = \sum_k K_k I_{i+{\Delta_y}_k,j+{\Delta_y}_k},

where :math:`K` is the flattened convolution kernel.

Parameters
----------
width: int
    Width of the input image
height: int
    Height of the input image
kernel: numpy.ndarray
    Convolutional kernel
dx: numpy.ndarray
    Offset in x direction
dy: nunpy.ndarray
    Offset in y direction

Returns
-------
M: scipy.sparse.csr_matrix
    Convolution matrix
r~   Tr   )r   )r   asarrayr   r   r   int32rb   r   ziprc   r   r   
csr_matrix)rK   rL   kerneldxdyweightscountr   i_indsj_indsvalueskr   r   dx2dy2weightx2y2r)   s   &&&&&               r   sparse_conv_matrix_with_offsetsr     s)   6 jj ((*GLEAXXairxx0FXXairxx0FXXairzz2F	AE48DA0&WWQWa+WWQWa!,E	M15eO15"15	 1 	&)9 :1&IAHr    c                    VP                   w  r4\        WCRR7      w  rVWT^,          ,          pWc^,          ,          p\        WW%V4      # )a  Calculates a convolution matrix that can be applied to a vectorized image

Parameters
----------
width: int
    Width of the input image
height: int
    Height of the input image
kernel: numpy.ndarray
    Convolutional kernel

Returns
-------
M: scipy.sparse.csr_matrix
    Convolution matrix

Example
-------
>>> from pymatting import *
>>> import numpy as np
>>> sparse_conv_matrix(3,3,np.ones((3,3)))
<9x9 sparse matrix of type '<class 'numpy.float64'>'
with 49 stored elements in Compressed Sparse Row format>
Tr   )r   r   r   )rK   rL   r   khkwr   r   s   &&&    r   sparse_conv_matrixr   '  sB    2 \\FBBD1DAqLAqLA*5&QGGr    c                    V'       d   \        V 4      p V\        V 4      ,           p\        P                  P	                  V4      pW@,
          pV# )a~  Calculates the random walk normalized Laplacian matrix from the weight matrix

Parameters
----------
W: numpy.ndarray
    Array of weights
normalize: bool
    Whether the rows of W should be normalized to 1, defaults to True
regularization: float
    Regularization strength, defaults to 0, i.e. no regularizaion

Returns
-------
L: scipy.sparse.spmatrix
    Laplacian matrix

Example
-------
>>> from pymatting import *
>>> import numpy as np
>>> weights_to_laplacian(np.ones((4,4)))
matrix([[ 0.75, -0.25, -0.25, -0.25],
        [-0.25,  0.75, -0.25, -0.25],
        [-0.25, -0.25,  0.75, -0.25],
        [-0.25, -0.25, -0.25,  0.75]])
)r   r   r   r   r   )W	normalizeregularizationr   r   rU   s   &&&   r   weights_to_laplacianr   H  s?    6 1#A1A	AHr    c                    \         P                  ! V 4      p V P                  4       pV P                  4       pW,
          W!,
          ,          # )aD  Normalizes an array such that all values are between 0 and 1

Parameters
----------
values: numpy.ndarray
    Array to normalize

Returns
-------
result: numpy.ndarray
    Normalized array

Example
-------
>>> from pymatting import *
>>> import numpy as np
>>> normalize(np.array([0, 1, 3, 10]))
array([0. , 0.1, 0.3, 1. ])
)r   r   r   r   )r   r%   r&   s   &  r   r   r   n  s7    ( ZZF

A

AJ15!!r    c                .    W,           ^,
          V,          # )zDivides a number x by another integer n and rounds up the result

Parameters
----------
x: int
    Numerator
n: int
    Denominator

Returns
-------
result: int
    Result

Example
-------
>>> from pymatting import *
>>> div_round_up(3,2)
2
rt   )r   r   s   &&r   div_round_upr     s    * EAI!r    c                   W,
          p\         P                  ! W,
          V,          RR7      \         P                  ! \         P                  ! V4      4      ,          p\         P                  ! VRR4      pVR,          p\         P                  ! V ^V,
          V,          ,
          V\         P
                  ! V 4      VR8g  R7      p\         P                  ! VRR4      p\         P                  ! Wu.4      pV# )a]  Remove background from image with at most two colors.
Might not work if image has more than two colors.

Parameters
----------
image: numpy.ndarray
    RGB input image
fg_color: numpy.ndarray
    RGB Foreground color
bg_color: numpy.ndarray
    RGB Background color

Returns
-------
output: numpy.ndarray
    RGBA output image

Example
-------
>>> from pymatting import *
>>> import numpy as np
>>> image = np.random.rand(480, 320, 3)
>>> fg_color = np.random.rand(3)
>>> bg_color = np.random.rand(3)
>>> output = remove_background_bicolor(image, fg_color, bg_color)
>>> print(output.shape)
(480, 320, 4)
r
   r   r   )outwherer   )r	   r	   N)r   r   squarerc   divide
zeros_likedstack)	r   fg_colorbg_colorfg_bgur   r%   actual_coloroutputs	   &&&      r   remove_background_bicolorr     s    < E 	 E)3bffRYYu=M6NNAGGAsC E
 	jA99	!a%8#	#aR]]5-AcL 77<c2LYY,-FMr    )皙??)r=   )NNr?   )T)NNN)Tr   r   )r   )F)Tr   )#PILr   numpyr   scipy.sparser   re   r   	functoolsr   r   r'   r*   r,   r6   r;   rR   r\   rm   rq   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rt   r    r   <module>r      s       	  +\-6/6(40f6&>&6):XTn$V.r2
j!9H*::%P'T/dHB#L"401r    