Exemplo n.º 1
0
def mosaic(imIn, imOut, imWts, grid=mamba.DEFAULT_GRID):
    """
    Builds the mosaic image of 'imIn' and puts the results into 'imOut'.
    The watershed line (pixel values set to 255) is stored in the 
    greytone image 'imWts'. A mosaic image is a simple image made of various 
    tiles of uniform grey values. It is built using the watershed of 'imIn' 
    gradient and original markers made of gradient minima which are labelled by
    the maximum value of 'imIn' pixels inside them.
    """

    imWrk1 = mamba.imageMb(imIn, 1)
    imWrk2 = mamba.imageMb(imIn)
    mamba.copy(imIn, imWrk2)
    im_mark = mamba.imageMb(imIn, 32)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    mamba.gradient(imIn, imOut, se=se)
    mamba.minima(imOut, imWrk1, grid=grid)
    mamba.add(im_mark, imWrk1, im_mark)
    imWrk1.convert(8)
    mamba.build(imWrk1, imWrk2, grid=grid)
    mamba.add(im_mark, imWrk2, im_mark)
    watershedSegment(imOut, im_mark, grid=grid)
    mamba.copyBytePlane(im_mark, 3, imWts)
    mamba.subConst(im_mark, 1, im_mark)
    mamba.copyBytePlane(im_mark, 0, imOut)
Exemplo n.º 2
0
def hierarchicalLevel(imIn, imOut, grid=mamba.DEFAULT_GRID):
    """
    Computes the next hierarchical level of image 'imIn' in the
    waterfalls transformation and puts the result in 'imOut'.
    This operation makes sure that the next hierarchical level is embedded
    in the previous one.
    'imIn' must be a valued watershed image.
    """

    imWrk0 = mamba.imageMb(imIn)
    imWrk1 = mamba.imageMb(imIn, 1)
    imWrk2 = mamba.imageMb(imIn, 1)
    imWrk3 = mamba.imageMb(imIn, 1)
    imWrk4 = mamba.imageMb(imIn, 32)
    mamba.threshold(imIn, imWrk1, 0, 0)
    mamba.negate(imWrk1, imWrk2)
    hierarchy(imIn, imWrk2, imWrk0, grid=grid)
    mamba.minima(imWrk0, imWrk2, grid=grid)
    mamba.label(imWrk2, imWrk4, grid=grid)
    mamba.watershedSegment(imWrk0, imWrk4, grid=grid)
    mamba.copyBytePlane(imWrk4, 3, imWrk0)
    mamba.threshold(imWrk0, imWrk2, 0, 0)
    mamba.diff(imWrk1, imWrk2, imWrk3)
    mamba.build(imWrk1, imWrk3)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    mamba.dilate(imWrk3, imWrk1, 1, se)
    mamba.diff(imWrk2, imWrk1, imWrk1)
    mamba.logic(imWrk1, imWrk3, imWrk1, "sup")
    mamba.convertByMask(imWrk1, imWrk0, 255, 0)
    mamba.logic(imIn, imWrk0, imOut, "inf")
Exemplo n.º 3
0
def hierarchicalLevel(imIn, imOut, grid=mamba.DEFAULT_GRID):
    """
    Computes the next hierarchical level of image 'imIn' in the
    waterfalls transformation and puts the result in 'imOut'.
    This operation makes sure that the next hierarchical level is embedded
    in the previous one.
    'imIn' must be a valued watershed image.
    """
    
    imWrk0 = mamba.imageMb(imIn)
    imWrk1 = mamba.imageMb(imIn, 1)
    imWrk2 = mamba.imageMb(imIn, 1)
    imWrk3 = mamba.imageMb(imIn, 1)
    imWrk4 = mamba.imageMb(imIn, 32)
    mamba.threshold(imIn,imWrk1, 0, 0)
    mamba.negate(imWrk1, imWrk2)
    hierarchy(imIn, imWrk2, imWrk0, grid=grid)
    mamba.minima(imWrk0, imWrk2, grid=grid)
    mamba.label(imWrk2, imWrk4, grid=grid)
    mamba.watershedSegment(imWrk0, imWrk4, grid=grid)
    mamba.copyBytePlane(imWrk4, 3, imWrk0)
    mamba.threshold(imWrk0, imWrk2, 0, 0)
    mamba.diff(imWrk1, imWrk2, imWrk3)
    mamba.build(imWrk1, imWrk3)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    mamba.dilate(imWrk3, imWrk1, 1, se)
    mamba.diff(imWrk2, imWrk1, imWrk1)
    mamba.logic(imWrk1, imWrk3, imWrk1, "sup")
    mamba.convertByMask(imWrk1, imWrk0, 255, 0)
    mamba.logic(imIn, imWrk0, imOut, "inf")
Exemplo n.º 4
0
def mosaic(imIn, imOut, imWts, grid=mamba.DEFAULT_GRID):
    """
    Builds the mosaic image of 'imIn' and puts the results into 'imOut'.
    The watershed line (pixel values set to 255) is stored in the 
    greytone image 'imWts'. A mosaic image is a simple image made of various 
    tiles of uniform grey values. It is built using the watershed of 'imIn' 
    gradient and original markers made of gradient minima which are labelled by
    the maximum value of 'imIn' pixels inside them.
    """

    imWrk1 = mamba.imageMb(imIn, 1)
    imWrk2 = mamba.imageMb(imIn)
    mamba.copy(imIn, imWrk2)
    im_mark = mamba.imageMb(imIn, 32)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    mamba.gradient(imIn, imOut, se=se)
    mamba.minima(imOut, imWrk1, grid=grid)
    mamba.add(im_mark, imWrk1, im_mark)
    imWrk1.convert(8)
    mamba.build(imWrk1, imWrk2, grid=grid)
    mamba.add(im_mark, imWrk2, im_mark)
    watershedSegment(imOut, im_mark, grid=grid)
    mamba.copyBytePlane(im_mark, 3, imWts)
    mamba.subConst(im_mark, 1, im_mark)
    mamba.copyBytePlane(im_mark, 0, imOut)
Exemplo n.º 5
0
def buildOpen(imIn, imOut, n=1, se=mamba.DEFAULT_SE):
    """
    Performs an opening by reconstruction operation on image 'imIn' and puts the
    result in 'imOut'. 'n' controls the size of the opening.
    """

    imWrk = mamba.imageMb(imIn)
    mamba.copy(imIn, imWrk)
    mamba.erode(imIn, imOut, n, se=se)
    mamba.build(imWrk, imOut, grid=se.getGrid())
Exemplo n.º 6
0
def buildOpen(imIn, imOut, n=1, se=mamba.DEFAULT_SE):
    """
    Performs an opening by reconstruction operation on image 'imIn' and puts the
    result in 'imOut'. 'n' controls the size of the opening.
    """
    
    imWrk = mamba.imageMb(imIn)
    mamba.copy(imIn, imWrk)
    mamba.erode(imIn, imOut, n, se=se)
    mamba.build(imWrk, imOut, grid=se.getGrid())
Exemplo n.º 7
0
def maxPartialBuild(imIn, imMask, imOut, grid=mamba.DEFAULT_GRID):
    """
    Performs the partial reconstruction of 'imIn' with its maxima which are
    contained in the binary mask 'imMask'. The result is put in 'imOut'.
    
    'imIn' and 'imOut' must be different and greyscale images.
    """
    
    imWrk = mamba.imageMb(imIn, 1)
    maxima(imIn, imWrk, 1, grid=grid)
    mamba.logic(imMask, imWrk, imWrk, "inf")
    mamba.convertByMask(imWrk, imOut, 0, mamba.computeMaxRange(imIn)[1])
    mamba.logic(imIn, imOut, imOut, "inf")
    mamba.build(imIn, imOut)
Exemplo n.º 8
0
def firstParticle(imIn, imOut, grid=mamba.DEFAULT_GRID):
    """
    Extraction of the first particle (in scanning order) of binary image imIn.
    The particle is put into image imOut and removed from imIn.
    
    If imIn is empty, imOut is also empty.
    imIn and imOut must be different.
    """

    imWrk = mamba.imageMb(imIn)
    mamba.compare(imIn, imWrk, imWrk)
    mamba.build(imIn, imWrk, grid=grid)
    mamba.diff(imIn, imWrk, imIn)
    mamba.copy(imWrk, imOut) 
Exemplo n.º 9
0
def geodesicSKIZ(imIn, imMask, imOut, grid=mamba.DEFAULT_GRID):
    """
    Geodesic skeleton by zones of influence of binary image 'imIn' inside the
    geodesic mask 'imMask'. The result is in binary image 'imOut'.
    """

    imWrk1 = mamba.imageMb(imIn, 8)
    imWrk2 = mamba.imageMb(imIn)
    mamba.copy(imIn, imWrk2)
    mamba.build(imMask, imWrk2, grid=grid)
    mamba.convertByMask(imWrk2, imWrk1, 2, 1)
    mamba.sub(imWrk1, imIn, imWrk1)
    markerControlledWatershed(imWrk1, imIn, imWrk1, grid=grid)
    mamba.threshold(imWrk1, imOut, 0, 0)
    mamba.logic(imOut, imWrk2, imOut, "inf")
Exemplo n.º 10
0
def geodesicSKIZ(imIn, imMask, imOut, grid=mamba.DEFAULT_GRID):
    """
    Geodesic skeleton by zones of influence of binary image 'imIn' inside the
    geodesic mask 'imMask'. The result is in binary image 'imOut'.
    """

    imWrk1 = mamba.imageMb(imIn, 8)
    imWrk2 = mamba.imageMb(imIn)
    mamba.copy(imIn, imWrk2)
    mamba.build(imMask, imWrk2, grid=grid)
    mamba.convertByMask(imWrk2, imWrk1, 2, 1)
    mamba.sub(imWrk1, imIn, imWrk1)
    markerControlledWatershed(imWrk1, imIn, imWrk1, grid=grid)
    mamba.threshold(imWrk1, imOut, 0, 0)
    mamba.logic(imOut, imWrk2, imOut, "inf")
Exemplo n.º 11
0
def highMaxima(imIn, imOut, h, grid=mamba.DEFAULT_GRID):
    """
    Computes the maxima of the reconstruction of image 'imIn' by imIn - h
    and puts the result in 'imOut'.

    Grid used by the build operation can be specified by 'grid'.
    
    Only works with 8-bit or 32-bit images as input. 'imOut' must be binary.
    """
    
    imWrk = mamba.imageMb(imIn)
    if imIn.getDepth() == 8:
        mamba.subConst(imIn, h, imWrk)
        mamba.hierarBuild(imIn, imWrk, grid=grid)
    else:
        mamba.floorSubConst(imIn, h, imWrk)
        mamba.build(imIn, imWrk, grid=grid)
    maxima(imWrk, imOut, 1, grid=grid)
Exemplo n.º 12
0
def maxDynamics(imIn, imOut, h, grid=mamba.DEFAULT_GRID):
    """
    Extracts the maxima of 'imIn' with a dynamics higher or equal to 'h'
    and puts the result in 'imOut'.
    
    Grid used by the dual build operation can be specified by 'grid'.
    
    Only works with 8-bit or 32-bit images as input. 'imOut' must be binary.
    """
    
    imWrk = mamba.imageMb(imIn)
    if imIn.getDepth() == 8:
        mamba.subConst(imIn, h, imWrk)
        mamba.hierarBuild(imIn, imWrk, grid=grid)
        mamba.sub(imIn, imWrk, imWrk)
    else:
        mamba.floorSubConst(imIn, h, imWrk)
        mamba.build(imIn, imWrk, grid=grid)
        mamba.floorSub(imIn, imWrk, imWrk)
    mamba.threshold(imWrk, imOut, h, mamba.computeMaxRange(imIn)[1])
Exemplo n.º 13
0
def maxima(imIn, imOut, h=1, grid=mamba.DEFAULT_GRID):
    """
    Computes the maxima of 'imIn' using a build operation and puts the result in
    'imOut'. When 'h' is equal to 1 (default value), the operator provides the
    maxima of 'imIn'.
    
    Grid used by the build operation can be specified by 'grid'.
    
    Only works with with 8-bit or 32-bit images as input. 'imOut' must be binary.
    """
    
    imWrk = mamba.imageMb(imIn)
    if imIn.getDepth() == 8:
        mamba.subConst(imIn, h, imWrk)
        mamba.hierarBuild(imIn, imWrk, grid=grid)
        mamba.sub(imIn, imWrk, imWrk)
    else:
        mamba.floorSubConst(imIn, h, imWrk)
        mamba.build(imIn, imWrk, grid=grid)
        mamba.floorSub(imIn, imWrk, imWrk)
    mamba.threshold(imWrk, imOut, 1, mamba.computeMaxRange(imIn)[1])
Exemplo n.º 14
0
def simpleLevelling(imIn, imMask, imOut, grid=mamba.DEFAULT_GRID):
    """
    Performs a simple levelling of image 'imIn' controlled by image 'imMask'
    and puts the result in 'imOut'. This operation is composed of two
    geodesic reconstructions. This filter tends to level regions in the 
    image of homogeneous grey values.
    """
    
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    mask_im = mamba.imageMb(imIn, 1)
    mamba.logic(imIn, imMask, imWrk1, "inf")
    mamba.build(imIn, imWrk1, grid=grid)
    mamba.logic(imIn, imMask, imWrk2, "sup")
    mamba.dualBuild(imIn, imWrk2, grid=grid)
    mamba.generateSupMask(imIn, imMask, mask_im, False)
    mamba.convertByMask(mask_im, imOut, 0, mamba.computeMaxRange(imIn)[1])
    mamba.logic(imOut, imWrk1, imWrk1, "inf")
    mamba.negate(imOut, imOut)
    mamba.logic(imOut, imWrk2, imOut, "inf")
    mamba.logic(imWrk1, imOut, imOut, "sup")
Exemplo n.º 15
0
def strongLevelling(imIn, imOut, n, eroFirst, grid=mamba.DEFAULT_GRID):
    """
    Strong levelling of 'imIn', result in 'imOut'. 'n' defines the size of the
    erosion and dilation of 'imIn' in the operation. If 'eroFirst' is true, the
    operation starts with an erosion, it starts with a dilation otherwise.
    
    This filter is stronger (more efficient) that simpleLevelling. However, the
    order of the initial operations (erosion and dilation) matters.    
    """
    
    imWrk = mamba.imageMb(imIn)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    if eroFirst:
        mamba.erode(imIn, imWrk, n, se=se)
        mamba.build(imIn, imWrk, grid=grid)
        mamba.dilate(imIn, imOut, n, se=se)
        mamba.dualBuild(imWrk, imOut, grid=grid)
    else:
        mamba.dilate(imIn, imWrk, n, se=se)
        mamba.dualBuild(imIn, imWrk, grid=grid)
        mamba.erode(imIn, imOut, n, se=se)
        mamba.build(imWrk, imOut, grid=grid)
Exemplo n.º 16
0
def ultimateErosion(imIn, imOut1, imOut2, grid=mamba.DEFAULT_GRID):
    """
    General ultimate erosion working on greytone image 'imIn'. 'imOut1'
    contains the ultimate eroded function and 'imOut2' contains the 
    associated function.
    
    This ultimate erosion can be applied to greytone images.

    Depth of 'imOut1' is the same as 'imIn', depth of 'imOut2' is 32. 

    The edge is always set to 'FILLED'.
    """

    maskIm = mamba.imageMb(imIn, 1)
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk3 = mamba.imageMb(imIn, 32)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    i = 0
    mamba.copy(imIn, imWrk1)
    v2 = mamba.computeVolume(imWrk1)
    v1 = v2 + 1
    imOut1.reset()
    imOut2.reset()
    while v1 > v2:
        i += 1
        v1 = v2
        mamba.erode(imWrk1, imWrk2, se=se)
        mamba.build(imWrk1, imWrk2, grid=grid)
        mamba.sub(imWrk1, imWrk2, imWrk2)
        _generateMask_(imWrk2, imOut1, maskIm)
        mamba.convertByMask(maskIm, imWrk3, 0, i)
        mamba.logic(imOut1, imWrk2, imOut1, "sup")
        mamba.logic(imOut2, imWrk3, imOut2, "sup")
        mamba.erode(imWrk1, imWrk1, se=se)
        v2 = mamba.computeVolume(imWrk1)
Exemplo n.º 17
0
def feretDiameterLabelling(imIn, imOut, direc):
    """
    The Feret diameter of each connected component of the binary image or the
    partition image 'imIn' is computed and its value labels the corresponding
    component. The labelled image is stored in the 32-bit image 'imOut'.
    If 'direc' is "vertical", the vertical Feret diameter is computed. If it is
    set to "horizontal", the corresponding diameter is used.    
    """

    imWrk1 = mamba.imageMb(imIn, 1)
    imWrk2 = mamba.imageMb(imIn, 32)
    imWrk3 = mamba.imageMb(imIn, 32)
    imWrk4 = mamba.imageMb(imIn, 32)

    imWrk1.fill(1)
    if direc == "horizontal":
        dir = 7
    elif direc == "vertical":
        dir = 1
    else:
        mamba.raiseExceptionOnError(core.MB_ERR_BAD_DIRECTION)
        # The above statement generates an error ('direc' is not horizontal or
        # vertical.
    # An horizontal or vertical distance function is generated.
    mamba.linearErode(imWrk1, imWrk1, dir, grid=mamba.SQUARE, edge=mamba.EMPTY)
    mamba.computeDistance(imWrk1, imOut, grid=mamba.SQUARE, edge=mamba.FILLED)
    mamba.addConst(imOut, 1, imOut)
    if imIn.getDepth() == 1:
        # Each particle is valued with the distance.
        mamba.convertByMask(imIn, imWrk2, 0, mamba.computeMaxRange(imWrk3)[1])
        mamba.logic(imOut, imWrk2, imWrk3, "inf")
        # The valued image is preserved.
        mamba.copy(imWrk3, imWrk4)
        # Each component is labelled by the maximal coordinate.
        mamba.build(imWrk2, imWrk3)
        # Using the dual reconstruction, we label the particles with the
        # minimal ccordinate.
        mamba.negate(imWrk2, imWrk2)
        mamba.logic(imWrk2, imWrk4, imWrk4, "sup")
        mamba.dualBuild(imWrk2, imWrk4)
        # We subtract 1 because the selected coordinate must be outside the particle.
        mamba.subConst(imWrk4, 1, imWrk4)
        mamba.negate(imWrk2, imWrk2)
        mamba.logic(imWrk2, imWrk4, imWrk4, "inf")
        # Then, the subtraction gives the Feret diameter.
        mamba.sub(imWrk3, imWrk4, imOut)
    else:
        mamba.copy(imOut, imWrk3)
        if imIn.getDepth() == 32:
            mamba.copy(imIn, imWrk2)
        else:
            mamba.convert(imIn, imWrk2)

# Using the cells builds (direct and dual to label the cells with the maximum
# and minimum distance.
        mamba.cellsBuild(imWrk2, imWrk3)
        mamba.cellsBuild(imWrk2, imWrk3)
        mamba.negate(imOut, imOut)
        mamba.cellsBuild(imWrk2, imOut)
        mamba.negate(imOut, imOut)
        # Subtracting 1...
        mamba.subConst(imOut, 1, imOut)
        # ... and getting the final result.
        mamba.sub(imWrk3, imOut, imOut)
Exemplo n.º 18
0
def feretDiameterLabelling(imIn, imOut, direc):
    """
    The Feret diameter of each connected component of the binary image or the
    partition image 'imIn' is computed and its value labels the corresponding
    component. The labelled image is stored in the 32-bit image 'imOut'.
    If 'direc' is "vertical", the vertical Feret diameter is computed. If it is
    set to "horizontal", the corresponding diameter is used.    
    """
    
    imWrk1 = mamba.imageMb(imIn, 1)
    imWrk2 = mamba.imageMb(imIn, 32)
    imWrk3 = mamba.imageMb(imIn, 32)
    imWrk4 = mamba.imageMb(imIn, 32)
    
    imWrk1.fill(1)
    if direc == "horizontal":
        dir = 7    
    elif direc == "vertical":
        dir = 1
    else:
        mamba.raiseExceptionOnError(core.MB_ERR_BAD_DIRECTION)
        # The above statement generates an error ('direc' is not horizontal or 
        # vertical.
    # An horizontal or vertical distance function is generated.
    mamba.linearErode(imWrk1, imWrk1, dir, grid=mamba.SQUARE, edge=mamba.EMPTY)
    mamba.computeDistance(imWrk1, imOut, grid=mamba.SQUARE, edge=mamba.FILLED)
    mamba.addConst(imOut, 1, imOut)
    if imIn.getDepth() == 1:
	    # Each particle is valued with the distance.
        mamba.convertByMask(imIn, imWrk2, 0, mamba.computeMaxRange(imWrk3)[1])
        mamba.logic(imOut, imWrk2, imWrk3, "inf")
        # The valued image is preserved.
        mamba.copy(imWrk3, imWrk4)
        # Each component is labelled by the maximal coordinate.
        mamba.build(imWrk2, imWrk3)
        # Using the dual reconstruction, we label the particles with the
        # minimal ccordinate.
        mamba.negate(imWrk2, imWrk2)
        mamba.logic(imWrk2, imWrk4, imWrk4, "sup")
        mamba.dualBuild(imWrk2, imWrk4)
        # We subtract 1 because the selected coordinate must be outside the particle.
        mamba.subConst(imWrk4, 1, imWrk4)
        mamba.negate(imWrk2, imWrk2)
        mamba.logic(imWrk2, imWrk4, imWrk4, "inf")
        # Then, the subtraction gives the Feret diameter.
        mamba.sub(imWrk3, imWrk4, imOut)
    else:
        mamba.copy(imOut, imWrk3)
        if imIn.getDepth() == 32:
            mamba.copy(imIn, imWrk2)
        else:
            mamba.convert(imIn, imWrk2)
	# Using the cells builds (direct and dual to label the cells with the maximum
        # and minimum distance.
        mamba.cellsBuild(imWrk2, imWrk3)
        mamba.cellsBuild(imWrk2, imWrk3)
        mamba.negate(imOut, imOut)
        mamba.cellsBuild(imWrk2, imOut)
        mamba.negate(imOut, imOut)
        # Subtracting 1...
        mamba.subConst(imOut, 1, imOut)
        # ... and getting the final result.
        mamba.sub(imWrk3, imOut, imOut)
Exemplo n.º 19
0
        def _watershed_using_quasi_distance(self):
            """
            疑似ユークリッド距離(Quasi Distance) に基づく
            Watershed 領域分割
            
            Returns
            -------
            numpy.ndarray
                領域分割線の画像
            """

            from mamba import (
                imageMb,
                gradient,
                add,
                negate,
                quasiDistance,
                copyBytePlane,
                subConst,
                build,
                maxima,
                label,
                watershedSegment,
                logic,
                mix,
            )

            from utils.convert import mamba2np, np2mamba

            # Channel Split
            if self.src_img.ndim == 3:
                b, g, r = [np2mamba(self.src_img[:, :, i]) for i in range(3)]
            elif self.src_img.ndim == 2:
                b, g, r = [np2mamba(self.src_img)] * 3

            # We will perform a thick gradient on each color channel (contours in original
            # picture are more or less fuzzy) and we add all these gradients
            gradient = imageMb(r)
            tmp_1 = imageMb(r)
            gradient.reset()
            gradient(r, tmp_1, 2)
            add(tmp_1, gradient, gradient)
            gradient(g, tmp_1, 2)
            add(tmp_1, gradient, gradient)
            gradient(b, tmp_1, 2)
            add(tmp_1, gradient, gradient)

            # Then we invert the gradient image and we compute its quasi-distance
            quasi_dist = imageMb(gradient, 32)
            negate(gradient, gradient)
            quasiDistance(gradient, tmp_1, quasi_dist)

            if self.is_logging:
                self.logger.logging_img(tmp_1, "quasi_dist_gradient")
                self.logger.logging_img(quasi_dist, "quasi_dist")

            # The maxima of the quasi-distance are extracted and filtered (too close maxima,
            # less than 6 pixels apart, are merged)
            tmp_2 = imageMb(r)
            marker = imageMb(gradient, 1)
            copyBytePlane(quasi_dist, 0, tmp_1)
            subConst(tmp_1, 3, tmp_2)
            build(tmp_1, tmp_2)
            maxima(tmp_2, marker)

            # The marker-controlled watershed of the gradient is performed
            watershed = imageMb(gradient)
            label(marker, quasi_dist)
            negate(gradient, gradient)
            watershedSegment(gradient, quasi_dist)
            copyBytePlane(quasi_dist, 3, watershed)

            # The segmented binary and color image are stored
            logic(r, watershed, r, "sup")
            logic(g, watershed, g, "sup")
            logic(b, watershed, b, "sup")

            segmented_image = mix(r, g, b)

            if self.is_logging:
                self.logger.logging_img(segmented_image, "segmented_image")

            watershed = mamba2np(watershed)

            return watershed
def reconstruction(npIm, npMask):
    mbIm = convertNumpy2Mamba(npIm)
    mbMask = convertNumpy2Mamba(npMask)
    mamba.build(mbMask, mbIm, mamba.SQUARE)
    height, width = npIm.shape[-2:]
    return convertMamba2Numpy(mbIm)[:height, :width].astype(npIm.dtype)