Example #1
0
def quasiDistance(imIn, imOut1, imOut2, grid=mamba.DEFAULT_GRID):
    """
    Quasi-distance of image 'imIn'. 'imOut1' contains the residues image
    and 'imOut2' contains the quasi-distance (associated function).
    
    The quasi-distance of a greytone image is made of a patch of distance
    functions of some almost flat regions in the image. When the image is a
    simple indicator function of a set, the quasi-distance and the distance
    function are identical.

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

    imWrk1 = mamba.imageMb(imIn, 32)
    imWrk2 = mamba.imageMb(imIn, 32)
    imWrk3 = mamba.imageMb(imIn, 32)
    maskIm = mamba.imageMb(imIn, 1) 
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    _initialQuasiDist_(imIn, imOut1, imOut2, grid=grid)
    mamba.copy(imOut2, imWrk1)
    v1 = mamba.computeVolume(imOut2)
    v2 = v1 + 1
    while v2 > v1:
        v2 = v1
        mamba.erode(imWrk1, imWrk2, se=se)
        mamba.sub(imWrk1, imWrk2, imWrk2)
        mamba.threshold(imWrk2, maskIm, 2, mamba.computeMaxRange(imWrk2)[1])
        mamba.convertByMask(maskIm, imWrk3, 0, mamba.computeMaxRange(imWrk3)[1])
        mamba.logic(imWrk2, imWrk3, imWrk2, "inf")
        mamba.subConst(imWrk2, 1, imWrk3)
        mamba.logic(imWrk2, imWrk3, imWrk2, "inf") # Patch non saturated subtraction
        mamba.sub(imWrk1, imWrk2, imWrk1)
        v1 = mamba.computeVolume(imWrk1)
    mamba.copy(imWrk1, imOut2)
Example #2
0
def upperGeodesicDilate(imIn, imMask, imOut, n=1, se=mamba.DEFAULT_SE):
    """
    Performs an upper geodesic dilation of image 'imIn' above 'imMask'.
    The result is put inside 'imOut', 'n' controls the size of the dilation.
    'se' specifies the type of structuring element used to perform the 
    computation (DEFAULT_SE by default). 
    
    Warning! 'imMask' and 'imOut' must be different.
    """
    
    mamba.logic(imIn, imMask, imOut, "sup")
    if imIn.getDepth() == 1:
        for i in range(n):
            mamba.diff(imOut, imMask, imOut)
            mamba.dilate(imOut, imOut, se=se)
            mamba.logic(imMask, imOut, imOut, "sup")
    else:
        imWrk1 = mamba.imageMb(imIn)
        imWrk2 = mamba.imageMb(imIn, 1)
        for i in range(n):
            mamba.generateSupMask(imOut, imMask, imWrk2, True)
            mamba.convertByMask(imWrk2, imWrk1, 0, mamba.computeMaxRange(imWrk1)[1])
            mamba.logic(imOut, imWrk1, imOut, "inf")
            mamba.dilate(imOut, imOut, se=se)
            mamba.logic(imOut, imMask, imOut, "sup")
Example #3
0
def infClose(imIn, imOut, n, grid=mamba.DEFAULT_GRID):
    """
    Performs the infimum of directional closings. A black particle is preserved
    if its length is larger than 'n' in at least one direction.
    
    This operator is a closing. The image edge is set to 'FILLED' in order to 
    take into account particles touching the edge (they are supposed not to 
    extend outside the image window).
    
    When square grid is used, the size in oblique directions are reduced to be
    similar to the horizontal and vertical size.    
    """
    
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk1.fill(mamba.computeMaxRange(imIn)[1])
    if grid == mamba.SQUARE:
        size = int((1.4142 * n + 1)/2)
        linearClose(imIn, imWrk2, 2, size, grid=grid)
        mamba.logic(imWrk1, imWrk2, imWrk1, "inf")
        linearClose(imIn, imWrk2, 4, size, grid=grid)
        mamba.logic(imWrk1, imWrk2, imWrk1, "inf")
        d = 4
    else:
        d = 6
    for i in range(1, d, 2):
        linearClose(imIn, imWrk2, i, n, grid=grid)
        mamba.logic(imWrk1, imWrk2, imWrk1, "inf")
    mamba.copy(imWrk1, imOut)
Example #4
0
def conjugateDirectionalErode(imIn,
                              imOut,
                              d,
                              size,
                              grid=mamba.DEFAULT_GRID,
                              edge=mamba.FILLED):
    """
    Performs the erosion of image 'imIn' in the conjugate direction 'd' of the
    grid and puts the result in image 'imOut'. The images can be binary, greyscale
    or 32-bit images. 'size' is a multiple of the distance between two adjacent
    points in the conjugate directions. 'edge' is set to FILLED by default (can
    be changed).
    Note that this operator is not equivalent to successive erosions by a doublet
    of points.
    """

    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    mamba.copy(imIn, imOut)

    j3 = mamba.transposeDirection(d, grid=grid)
    j2 = mamba.rotateDirection(d, grid=grid)
    j1 = mamba.transposeDirection(j2, grid=grid)
    val = mamba.computeMaxRange(imIn)[1] * int(edge == mamba.FILLED)
    for i in range(size):
        mamba.copy(imOut, imWrk1)
        mamba.copy(imOut, imWrk2)
        mamba.linearErode(imWrk1, imWrk1, d, n=1, grid=grid, edge=edge)
        mamba.shift(imWrk1, imWrk1, j1, 1, val, grid=grid)
        mamba.logic(imWrk1, imOut, imWrk1, "inf")
        mamba.linearErode(imWrk2, imWrk2, j2, n=1, grid=grid, edge=edge)
        mamba.shift(imWrk2, imWrk2, j3, 1, val, grid=grid)
        mamba.logic(imWrk2, imOut, imWrk2, "inf")
        mamba.logic(imWrk1, imWrk2, imOut, "sup")
Example #5
0
def cellsBuild(imIn, imInOut, grid=mamba.DEFAULT_GRID):
    """
    Geodesic reconstruction of the cells of the partition image 'imIn' which
    are marked by the image 'imInOut'. The marked cells take the value of
    their corresponding marker. Note that the background cells (labelled by 0)
    are also modified if they are marked.
    The result is stored in 'imInOut'.
    The images can be 8-bit or 32-bit images.
    'grid' can be set to HEXAGONAL or SQUARE.
    """
    
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk3 = mamba.imageMb(imIn, 1)
    vol = 0
    prec_vol = -1
    dirs = mamba.getDirections(grid)[1:]
    while (prec_vol!=vol):
        prec_vol = vol
        for d in dirs:
            ed = 1<<d
            mamba.copy(imIn, imWrk1)
            mamba.copy(imIn, imWrk2)
            mamba.supNeighbor(imWrk1, imWrk1, ed, grid=grid)
            mamba.infNeighbor(imWrk2, imWrk2, ed, grid=grid)
            mamba.generateSupMask(imWrk2, imWrk1, imWrk3, False)
            mamba.convertByMask(imWrk3, imWrk1, 0, mamba.computeMaxRange(imIn)[1])
            mamba.linearDilate(imInOut, imWrk2, d, 1, grid=grid)
            mamba.logic(imWrk2, imWrk1, imWrk2, "inf")
            v = mamba.buildNeighbor(imWrk1, imWrk2, d, grid=grid)
            mamba.logic(imWrk2, imInOut, imInOut, "sup")
        vol = mamba.computeVolume(imInOut)
Example #6
0
def infClose(imIn, imOut, n, grid=mamba.DEFAULT_GRID):
    """
    Performs the infimum of directional closings. A black particle is preserved
    if its length is larger than 'n' in at least one direction.
    
    This operator is a closing. The image edge is set to 'FILLED' in order to 
    take into account particles touching the edge (they are supposed not to 
    extend outside the image window).
    
    When square grid is used, the size in oblique directions are reduced to be
    similar to the horizontal and vertical size.    
    """

    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk1.fill(mamba.computeMaxRange(imIn)[1])
    if grid == mamba.SQUARE:
        size = int((1.4142 * n + 1) / 2)
        linearClose(imIn, imWrk2, 2, size, grid=grid)
        mamba.logic(imWrk1, imWrk2, imWrk1, "inf")
        linearClose(imIn, imWrk2, 4, size, grid=grid)
        mamba.logic(imWrk1, imWrk2, imWrk1, "inf")
        d = 4
    else:
        d = 6
    for i in range(1, d, 2):
        linearClose(imIn, imWrk2, i, n, grid=grid)
        mamba.logic(imWrk1, imWrk2, imWrk1, "inf")
    mamba.copy(imWrk1, imOut)
Example #7
0
def partitionLabel(imIn, imOut):
    """
    This procedure labels each cell of image 'imIn' and puts the result in
    'imOut'. The number of cells is returned. 'imIn' can be a 1-bit, 8-bit or a
    32-bit image. 'imOut' is a 32-bit image. When 'imIn' is a binary image, all the
    connected components of the background are also labelled. When 'imIn' is a grey
    image, the 0-valued cells are also labelled (which is not the case with the label
    operator.
    Warning! The label values of adjacent cells are not necessarily consecutive.
    """
    
    imWrk1 = mamba.imageMb(imIn, 1)
    imWrk2 = mamba.imageMb(imIn, 32)
    
    if imIn.getDepth() == 1:
        mamba.negate(imIn, imWrk1)
    else:
        mamba.threshold(imIn, imWrk1, 0, 0)
    nb1 = mamba.label(imWrk1, imWrk2)
    mamba.convertByMask(imWrk1, imOut, mamba.computeMaxRange(imOut)[1], 0)
    mamba.logic(imOut, imWrk2, imOut, "sup")
    nb2 = mamba.label(imIn, imWrk2)
    mamba.addConst(imWrk2, nb1, imWrk2)
    mamba.logic(imOut, imWrk2, imOut, "inf")
    return nb1 + nb2
def _sparseConjugateHexagonDilate(imIn, imOut, size, edge=mamba.EMPTY):
    """
    Dilation by a conjugate hexagon. The structuring element used by this operation
    is not complete. Some holes appear inside the structuring element. Therefore, this
    operation should not be used to obtain true conjugate hexagons dilations (for
    internal use only).
    """

    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    mamba.copy(imIn, imOut)
    val = mamba.computeMaxRange(imIn)[1] * int(edge != mamba.EMPTY)
    for i in _sizeSplit(size):
        mamba.copy(imOut, imWrk1)
        j = 2 * i
        supFarNeighbor(imWrk1, imOut, 1, j, grid=mamba.SQUARE, edge=edge)
        mamba.shift(imWrk1, imWrk2, 2, i, val, grid=mamba.HEXAGONAL)
        supFarNeighbor(imWrk2, imOut, 4, i, grid=mamba.HEXAGONAL, edge=edge)
        supFarNeighbor(imWrk2, imOut, 6, i, grid=mamba.HEXAGONAL, edge=edge)
        supFarNeighbor(imWrk1, imOut, 5, j, grid=mamba.SQUARE, edge=edge)
        mamba.shift(imWrk1, imWrk2, 5, i, val, grid=mamba.HEXAGONAL)
        supFarNeighbor(imWrk2, imOut, 1, i, grid=mamba.HEXAGONAL, edge=edge)
        supFarNeighbor(imWrk2, imOut, 3, i, grid=mamba.HEXAGONAL, edge=edge)
        j = 3 * i // 2
        supFarNeighbor(imWrk1, imOut, 2, j, grid=mamba.HEXAGONAL, edge=edge)
        supFarNeighbor(imWrk1, imOut, 5, j, grid=mamba.HEXAGONAL, edge=edge)
Example #9
0
def binaryUltimateErosion(imIn, imOut1, imOut2, grid=mamba.DEFAULT_GRID, edge=mamba.FILLED):
    """
    Ultimate erosion of binary image 'imIn'. 'imOut1' contains the ultimate 
    eroded set and 'imOut2' contains the associated function (that is the 
    height of each connected component of the ultimate erosion).
    
    An ultimate erosion is composed of the union of the last connected
    components of the successive erosions of the initial set. The associated
    function provides the size of the corresponding erosion.
    
    Depth of 'imOut1' is 1, depth of 'imOut2' is 32. 

    The operation is fast because it is computed using the distance function
    of 'imIn' (the ultimate erosion is identical to the maxima of this
    distance function).

    The edge is set to 'FILLED' by default.
    """

    imWrk1 = mamba.imageMb(imIn, 32)
    imWrk2 = mamba.imageMb(imIn, 32)
    mamba.computeDistance(imIn, imWrk1, grid=grid, edge=edge)
    mamba.maxima(imWrk1, imOut1, grid=grid)
    mamba.convertByMask(imOut1, imWrk2, 0, mamba.computeMaxRange(imWrk2)[1])
    mamba.logic(imWrk1, imWrk2, imOut2, "inf")
Example #10
0
def conjugateDirectionalDilate(imIn, imOut, d, size, grid=mamba.DEFAULT_GRID, edge=mamba.EMPTY):
    """
    Performs the dilation of image 'imIn' in the conjugate direction 'd' of the
    grid and puts the result in image 'imOut'. The images can be binary, greyscale
    or 32-bit images. 'size' is a multiple of the distance between two adjacent
    points in the conjugate directions. 'edge' is set to EMPTY by default (can
    be changed).
    Note that the linear structuring element is not connected. Points connecting
    adjacent points in the conjugate directions are not present. This is normal
    if we want to insure that the result is identical when we iterate n size 1
    operations to get a size n one (the same remark applies to the erosion).
    """

    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    mamba.copy(imIn, imOut)

    j3 = mamba.transposeDirection(d, grid=grid)
    j2 = mamba.rotateDirection(d, grid=grid)
    j1 = mamba.transposeDirection(j2, grid=grid)
    val = mamba.computeMaxRange(imIn)[1] * int(edge == mamba.FILLED)
    for i in range(size):
        mamba.copy(imOut, imWrk1)
        mamba.copy(imOut, imWrk2)
        mamba.linearDilate(imWrk1, imWrk1, d, 1, grid=grid, edge=edge)
        mamba.shift(imWrk1, imWrk1, j1, 1, val, grid=grid)
        mamba.logic(imWrk1, imOut, imWrk1, "sup")
        mamba.linearDilate(imWrk2, imWrk2, j2, 1, grid=grid, edge=edge)
        mamba.shift(imWrk2, imWrk2, j3, 1, val, grid=grid)
        mamba.logic(imWrk2, imOut, imWrk2, "sup")
        mamba.logic(imWrk1, imWrk2, imOut, "inf")
Example #11
0
def conjugateDirectionalErode(imIn, imOut, d, size, grid=mamba.DEFAULT_GRID, edge=mamba.FILLED):
    """
    Performs the erosion of image 'imIn' in the conjugate direction 'd' of the
    grid and puts the result in image 'imOut'. The images can be binary, greyscale
    or 32-bit images. 'size' is a multiple of the distance between two adjacent
    points in the conjugate directions. 'edge' is set to FILLED by default (can
    be changed).
    Note that this operator is not equivalent to successive erosions by a doublet
    of points.
    """

    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    mamba.copy(imIn, imOut)

    j3 = mamba.transposeDirection(d, grid=grid)
    j2 = mamba.rotateDirection(d, grid=grid)
    j1 = mamba.transposeDirection(j2, grid=grid)
    val = mamba.computeMaxRange(imIn)[1] * int(edge == mamba.FILLED)
    for i in range(size):
        mamba.copy(imOut, imWrk1)
        mamba.copy(imOut, imWrk2)
        mamba.linearErode(imWrk1, imWrk1, d, n=1, grid=grid, edge=edge)
        mamba.shift(imWrk1, imWrk1, j1, 1, val, grid=grid)
        mamba.logic(imWrk1, imOut, imWrk1, "inf")
        mamba.linearErode(imWrk2, imWrk2, j2, n=1, grid=grid, edge=edge)
        mamba.shift(imWrk2, imWrk2, j3, 1, val, grid=grid)
        mamba.logic(imWrk2, imOut, imWrk2, "inf")
        mamba.logic(imWrk1, imWrk2, imOut, "sup")
Example #12
0
def cellsBuild(imIn, imInOut, grid=mamba.DEFAULT_GRID):
    """
    Geodesic reconstruction of the cells of the partition image 'imIn' which
    are marked by the image 'imInOut'. The marked cells take the value of
    their corresponding marker. Note that the background cells (labelled by 0)
    are also modified if they are marked.
    The result is stored in 'imInOut'.
    The images can be 8-bit or 32-bit images.
    'grid' can be set to HEXAGONAL or SQUARE.
    """

    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk3 = mamba.imageMb(imIn, 1)
    vol = 0
    prec_vol = -1
    dirs = mamba.getDirections(grid)[1:]
    while (prec_vol != vol):
        prec_vol = vol
        for d in dirs:
            ed = 1 << d
            mamba.copy(imIn, imWrk1)
            mamba.copy(imIn, imWrk2)
            mamba.supNeighbor(imWrk1, imWrk1, ed, grid=grid)
            mamba.infNeighbor(imWrk2, imWrk2, ed, grid=grid)
            mamba.generateSupMask(imWrk2, imWrk1, imWrk3, False)
            mamba.convertByMask(imWrk3, imWrk1, 0,
                                mamba.computeMaxRange(imIn)[1])
            mamba.linearDilate(imInOut, imWrk2, d, 1, grid=grid)
            mamba.logic(imWrk2, imWrk1, imWrk2, "inf")
            v = mamba.buildNeighbor(imWrk1, imWrk2, d, grid=grid)
            mamba.logic(imWrk2, imInOut, imInOut, "sup")
        vol = mamba.computeVolume(imInOut)
Example #13
0
def lowerGeodesicErode(imIn, imMask, imOut, n=1, se=mamba.DEFAULT_SE):
    """
    Performs a lower geodesic erosion of image 'imIn' under 'imMask'.
    The result is put inside 'imOut', 'n' controls the size of the erosion.
    'se' specifies the type of structuring element used to perform the 
    computation (DEFAULT_SE by default).

    The binary lower geodesic erosion is realised using the fact that the
    dilation is the dual operation of the erosion.
    
    Warning! 'imMask' and 'imOut' must be different.
    """
    
    if imIn.getDepth() == 1:
        mamba.diff(imMask, imIn, imOut)
        lowerGeodesicDilate(imOut, imMask, imOut, n, se=se)
        mamba.diff(imMask, imOut, imOut)
    else:
        imWrk1 = mamba.imageMb(imIn)
        imWrk2 = mamba.imageMb(imIn, 1)
        mamba.logic(imIn, imMask, imOut, "inf")
        for i in range(n):
            mamba.generateSupMask(imOut, imMask, imWrk2, False)
            mamba.convertByMask(imWrk2, imWrk1, 0, mamba.computeMaxRange(imWrk1)[1])
            mamba.logic(imOut, imWrk1, imOut, "sup")
            mamba.erode(imOut, imOut, se=se)
            mamba.logic(imOut, imMask, imOut, "inf")
Example #14
0
def mulRealConst(imIn, v, imOut, nearest=False, precision=2):
    """
    Multiplies image 'imIn' by a real positive constant value 'v' and puts the 
    result in image 'imOut'. 'imIn' and 'imOut' can be 8-bit or 32-bit images.
    If 'imOut' is greyscale (8-bit), the result is saturated (results
    of the multiplication greater than 255 are limited to this value).
    'precision' indicates the number of decimal digits taken into account for
    the constant 'v' (default is 2).
    If 'nearest' is true, the result is rounded to the nearest integer value.
    If not (default), the result is simply truncated.
    """
    
    if imIn.getDepth()==1 or imOut.getDepth()==1:
        mamba.raiseExceptionOnError(core.MB_ERR_BAD_DEPTH)
    imWrk1 = mamba.imageMb(imIn, 32)
    imWrk2 = mamba.imageMb(imIn, 1)
    precVal = (10 ** precision)
    v1 = int(v * precVal)
    if imIn.getDepth()==8:
        imWrk1.reset()
        mamba.copyBytePlane(imIn, 0, imWrk1)
    else:
        mamba.copy(imIn, imWrk1)
    mulConst(imWrk1, v1, imWrk1)
    if nearest:
        adjVal = int(5 * (10 ** (precision - 1)))
        addConst(imWrk1, adjVal , imWrk1)
    divConst(imWrk1, precVal, imWrk1)
    if imOut.getDepth()==8:
        mamba.threshold(imWrk1, imWrk2, 255, mamba.computeMaxRange(imWrk1)[1])
        mamba.copyBytePlane(imWrk1, 0, imOut)
        imWrk2.convert(8)
        mamba.logic(imOut, imWrk2, imOut, "sup")
    else:
        mamba.copy(imWrk1, imOut)
Example #15
0
def conjugateDirectionalDilate(imIn, imOut, d, size, grid=mamba.DEFAULT_GRID, edge=mamba.EMPTY):
    """
    Performs the dilation of image 'imIn' in the conjugate direction 'd' of the
    grid and puts the result in image 'imOut'. The images can be binary, greyscale
    or 32-bit images. 'size' is a multiple of the distance between two adjacent
    points in the conjugate directions. 'edge' is set to EMPTY by default (can
    be changed).
    Note that the linear structuring element is not connected. Points connecting
    adjacent points in the conjugate directions are not present. This is normal
    if we want to insure that the result is identical when we iterate n size 1
    operations to get a size n one (the same remark applies to the erosion).
    """
    
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    mamba.copy(imIn, imOut)
    
    j3 = mamba.transposeDirection(d, grid=grid)
    j2 = mamba.rotateDirection(d, grid=grid)
    j1 = mamba.transposeDirection(j2, grid=grid)
    val = mamba.computeMaxRange(imIn)[1] * int(edge == mamba.FILLED)
    for i in range(size):
        mamba.copy(imOut, imWrk1)
        mamba.copy(imOut, imWrk2)
        mamba.linearDilate(imWrk1, imWrk1, d, 1, grid=grid, edge=edge)
        mamba.shift(imWrk1, imWrk1, j1, 1, val, grid=grid)
        mamba.logic(imWrk1, imOut, imWrk1, "sup")
        mamba.linearDilate(imWrk2, imWrk2, j2, 1, grid=grid, edge=edge)
        mamba.shift(imWrk2, imWrk2, j3, 1, val, grid=grid)
        mamba.logic(imWrk2, imOut, imWrk2, "sup")
        mamba.logic(imWrk1, imWrk2, imOut, "inf")
Example #16
0
def nonEqualNeighbors(imIn,
                      imOut,
                      nb,
                      grid=mamba.DEFAULT_GRID,
                      edge=mamba.FILLED):
    """
    This operator compares the value of each pixel of image 'imIn'
    with the value of its neighbors encoded in 'nb'.
    If all the neighbor values are different, the pixel is unchanged.
    Otherwise, it takes value 0.
    This operator works on hexagonal or square 'grid' and
    'edge' is set to FILLED by default.
    This operator works for 8-bit and 32-bit images.
    """

    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk3 = mamba.imageMb(imIn, 1)
    imWrk4 = mamba.imageMb(imIn, 1)
    for d in mamba.getDirections(grid):
        ed = 1 << d
        if (nb & ed):
            mamba.copy(imIn, imWrk1)
            mamba.copy(imIn, imWrk2)
            mamba.supNeighbor(imWrk1, imWrk1, ed, grid=grid, edge=edge)
            mamba.infNeighbor(imWrk2, imWrk2, ed, grid=grid, edge=edge)
            mamba.generateSupMask(imWrk2, imWrk1, imWrk3, False)
            mamba.logic(imWrk4, imWrk3, imWrk4, "or")
    mamba.convertByMask(imWrk4, imWrk1, mamba.computeMaxRange(imIn)[1], 0)
    mamba.logic(imIn, imWrk1, imOut, "inf")
Example #17
0
def nonEqualNeighbors(imIn, imOut, nb, grid=mamba.DEFAULT_GRID, edge=mamba.FILLED):
    """
    This operator compares the value of each pixel of image 'imIn'
    with the value of its neighbors encoded in 'nb'.
    If all the neighbor values are different, the pixel is unchanged.
    Otherwise, it takes value 0.
    This operator works on hexagonal or square 'grid' and
    'edge' is set to FILLED by default.
    This operator works for 8-bit and 32-bit images.
    """
    
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk3 = mamba.imageMb(imIn, 1)
    imWrk4 = mamba.imageMb(imIn, 1)
    for d in mamba.getDirections(grid):
        ed = 1<<d
        if (nb & ed):
            mamba.copy(imIn, imWrk1)
            mamba.copy(imIn, imWrk2)
            mamba.supNeighbor(imWrk1, imWrk1, ed, grid=grid, edge=edge)
            mamba.infNeighbor(imWrk2, imWrk2, ed, grid=grid, edge=edge)
            mamba.generateSupMask(imWrk2, imWrk1, imWrk3, False)
            mamba.logic(imWrk4, imWrk3, imWrk4, "or")
    mamba.convertByMask(imWrk4, imWrk1, mamba.computeMaxRange(imIn)[1], 0)
    mamba.logic(imIn, imWrk1, imOut, "inf")
Example #18
0
def computeMaxRange3D(imIn):
    """
    Returns a tuple with the minimum and maximum possible pixel values given the
    depth of 3D image 'imIn'. The values are returned in a tuple holding the 
    minimum and the maximum.
    """
    return mamba.computeMaxRange(imIn[0])
Example #19
0
def _sparseConjugateHexagonDilate(imIn, imOut, size, edge=mamba.EMPTY):
    """
    Dilation by a conjugate hexagon. The structuring element used by this operation
    is not complete. Some holes appear inside the structuring element. Therefore, this
    operation should not be used to obtain true conjugate hexagons dilations (for
    internal use only).
    """   

    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    mamba.copy(imIn, imOut)
    val = mamba.computeMaxRange(imIn)[1]*int(edge!=mamba.EMPTY)
    for i in _sizeSplit(size):
        mamba.copy(imOut, imWrk1)
        j = 2*i
        supFarNeighbor(imWrk1, imOut, 1, j, grid=mamba.SQUARE, edge=edge)
        mamba.shift(imWrk1, imWrk2, 2, i, val, grid=mamba.HEXAGONAL)
        supFarNeighbor(imWrk2, imOut, 4, i, grid=mamba.HEXAGONAL, edge=edge)
        supFarNeighbor(imWrk2, imOut, 6, i, grid=mamba.HEXAGONAL, edge=edge)
        supFarNeighbor(imWrk1, imOut, 5, j, grid=mamba.SQUARE, edge=edge)
        mamba.shift(imWrk1, imWrk2, 5, i, val, grid=mamba.HEXAGONAL)
        supFarNeighbor(imWrk2, imOut, 1, i, grid=mamba.HEXAGONAL, edge=edge)
        supFarNeighbor(imWrk2, imOut, 3, i, grid=mamba.HEXAGONAL, edge=edge)
        j = 3*i//2
        supFarNeighbor(imWrk1, imOut, 2, j, grid=mamba.HEXAGONAL, edge=edge)
        supFarNeighbor(imWrk1, imOut, 5, j, grid=mamba.HEXAGONAL, edge=edge)
Example #20
0
def partitionLabel(imIn, imOut):
    """
    This procedure labels each cell of image 'imIn' and puts the result in
    'imOut'. The number of cells is returned. 'imIn' can be a 1-bit, 8-bit or a
    32-bit image. 'imOut' is a 32-bit image. When 'imIn' is a binary image, all the
    connected components of the background are also labelled. When 'imIn' is a grey
    image, the 0-valued cells are also labelled (which is not the case with the label
    operator.
    Warning! The label values of adjacent cells are not necessarily consecutive.
    """

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

    if imIn.getDepth() == 1:
        mamba.negate(imIn, imWrk1)
    else:
        mamba.threshold(imIn, imWrk1, 0, 0)
    nb1 = mamba.label(imWrk1, imWrk2)
    mamba.convertByMask(imWrk1, imOut, mamba.computeMaxRange(imOut)[1], 0)
    mamba.logic(imOut, imWrk2, imOut, "sup")
    nb2 = mamba.label(imIn, imWrk2)
    mamba.addConst(imWrk2, nb1, imWrk2)
    mamba.logic(imOut, imWrk2, imOut, "inf")
    return nb1 + nb2
Example #21
0
def generalSegment(imIn, imOut, gain=2.0, offset=1, grid=mamba.DEFAULT_GRID):
    """
    General segmentation algorithm. This algorithm is controlled by two
    parameters: the 'gain' (identical to the gain used in standard and P
    segmentation) and a new one, the 'offset'. The 'offset' indicates which
    level of hierarchy is compared to the current hierarchical image.
    The 'offset' is relative to the current hierarchical level. If 'offset' is
    equal to 1, this operator corresponds to the standard segmentation, if
    'offset' is equal to 255 (this value stands for the infinity), the operator
    is equivalent to P algorithm.
    Image 'imOut' contains all these hierarchies which are embedded.
    'imIn' and 'imOut' must be greyscale images. 'imIn' and 'imOut' must be
    different.
    This transformation returns the number of hierarchical levels.    
    """

    imWrk0 = mamba.imageMb(imIn)
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk3 = mamba.imageMb(imIn)
    imWrk4 = mamba.imageMb(imIn, 1)
    imWrk5 = mamba.imageMb(imIn, 1)
    imWrk6 = mamba.imageMb(imIn, 32)
    mamba.copy(imIn, imWrk1)
    mamba.mulRealConst(imIn, gain, imWrk6)
    mamba.floorSubConst(imWrk6, 1, imWrk6)
    mamba.threshold(imWrk6, imWrk4, 255, mamba.computeMaxRange(imWrk6)[1])
    mamba.copyBytePlane(imWrk6, 0, imWrk0)
    mamba.convert(imWrk4, imWrk2)
    mamba.logic(imWrk0, imWrk2, imWrk0, "sup")
    mamba.logic(imWrk0, imWrk1, imWrk0, "sup")
    imOut.reset()
    nbLevels = 0
    mamba.threshold(imWrk1, imWrk4, 1, 255)
    flag = not (mamba.checkEmptiness(imWrk4))
    while flag:
        nbLevels += 1
        hierarchy(imWrk1, imWrk4, imWrk2, grid=grid)
        mamba.add(imOut, imWrk4, imOut)
        v = max(nbLevels - offset, 0) + 1
        mamba.threshold(imOut, imWrk4, v, 255)
        mamba.valuedWatershed(imWrk2, imWrk3, grid=grid)
        mamba.threshold(imWrk3, imWrk5, 1, 255)
        flag = not (mamba.checkEmptiness(imWrk5))
        hierarchy(imWrk3, imWrk5, imWrk2, grid=grid)
        mamba.generateSupMask(imWrk0, imWrk2, imWrk5, strict=False)
        mamba.logic(imWrk4, imWrk5, imWrk4, "inf")
        mamba.convertByMask(imWrk4, imWrk3, 0, 255)
        mamba.logic(imWrk1, imWrk3, imWrk3, "inf")
        mamba.negate(imWrk4, imWrk4)
        mamba.label(imWrk4, imWrk6, grid=grid)
        mamba.watershedSegment(imWrk3, imWrk6, grid=grid)
        mamba.copyBytePlane(imWrk6, 3, imWrk3)
        mamba.logic(imWrk1, imWrk2, imWrk1, "sup")
        mamba.logic(imWrk1, imWrk3, imWrk1, "inf")
        mamba.threshold(imWrk1, imWrk4, 1, 255)
    return nbLevels
Example #22
0
def generalSegment(imIn, imOut, gain=2.0, offset=1, grid=mamba.DEFAULT_GRID):
    """
    General segmentation algorithm. This algorithm is controlled by two
    parameters: the 'gain' (identical to the gain used in standard and P
    segmentation) and a new one, the 'offset'. The 'offset' indicates which
    level of hierarchy is compared to the current hierarchical image.
    The 'offset' is relative to the current hierarchical level. If 'offset' is
    equal to 1, this operator corresponds to the standard segmentation, if
    'offset' is equal to 255 (this value stands for the infinity), the operator
    is equivalent to P algorithm.
    Image 'imOut' contains all these hierarchies which are embedded.
    'imIn' and 'imOut' must be greyscale images. 'imIn' and 'imOut' must be
    different.
    This transformation returns the number of hierarchical levels.    
    """
    
    imWrk0 = mamba.imageMb(imIn)
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk3 = mamba.imageMb(imIn)
    imWrk4 = mamba.imageMb(imIn, 1)
    imWrk5 = mamba.imageMb(imIn, 1)
    imWrk6 = mamba.imageMb(imIn, 32)    
    mamba.copy(imIn, imWrk1)
    mamba.mulRealConst(imIn, gain, imWrk6)
    mamba.floorSubConst(imWrk6, 1, imWrk6)
    mamba.threshold(imWrk6, imWrk4, 255, mamba.computeMaxRange(imWrk6)[1])  
    mamba.copyBytePlane(imWrk6, 0, imWrk0)
    mamba.convert(imWrk4, imWrk2)
    mamba.logic(imWrk0, imWrk2, imWrk0, "sup")
    mamba.logic(imWrk0, imWrk1, imWrk0, "sup")
    imOut.reset()
    nbLevels = 0
    mamba.threshold(imWrk1, imWrk4, 1, 255)
    flag = not(mamba.checkEmptiness(imWrk4))
    while flag:
        nbLevels += 1
        hierarchy(imWrk1, imWrk4, imWrk2, grid=grid)
        mamba.add(imOut, imWrk4, imOut)
        v = max(nbLevels - offset, 0) + 1
        mamba.threshold(imOut, imWrk4, v, 255)
        mamba.valuedWatershed(imWrk2, imWrk3, grid=grid)
        mamba.threshold(imWrk3, imWrk5, 1, 255)
        flag = not(mamba.checkEmptiness(imWrk5))
        hierarchy(imWrk3, imWrk5, imWrk2, grid=grid)
        mamba.generateSupMask(imWrk0, imWrk2, imWrk5, strict=False)
        mamba.logic(imWrk4, imWrk5, imWrk4, "inf")
        mamba.convertByMask(imWrk4, imWrk3, 0, 255)
        mamba.logic(imWrk1, imWrk3, imWrk3, "inf")
        mamba.negate(imWrk4, imWrk4)
        mamba.label(imWrk4, imWrk6, grid=grid)
        mamba.watershedSegment(imWrk3, imWrk6, grid=grid)
        mamba.copyBytePlane(imWrk6, 3, imWrk3)
        mamba.logic(imWrk1, imWrk2, imWrk1, "sup")
        mamba.logic(imWrk1, imWrk3, imWrk1, "inf")
        mamba.threshold(imWrk1, imWrk4, 1, 255)
    return nbLevels
Example #23
0
def standardSegment(imIn, imOut, gain=2.0, grid=mamba.DEFAULT_GRID):
    """
    General standard segmentation. This algorithm keeps the contours of the 
    watershed transform which are above or equal to the hierarchical image 
    associated to the next level of hierarchy when the altitude of the contour
    is multiplied by a 'gain' factor (default is 2.0). This transform also ends 
    by idempotence. All the hierarchical levels of image 'imIn'(which is a 
    valued watershed) are computed. 'imOut' contains all these hierarchies which
    are embedded, so that hierarchy i is simply obtained by a threshold
    [i+1, 255] of image 'imOut'.
    'imIn' and 'imOut' must be greyscale images. 'imIn' and 'imOut' must be
    different.
    This transformation returns the number of hierarchical levels.    
    """

    imWrk0 = mamba.imageMb(imIn)
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk3 = mamba.imageMb(imIn)
    imWrk4 = mamba.imageMb(imIn, 1)
    imWrk5 = mamba.imageMb(imIn, 1)
    imWrk6 = mamba.imageMb(imIn, 32)
    mamba.copy(imIn, imWrk1)
    mamba.mulRealConst(imIn, gain, imWrk6)
    mamba.floorSubConst(imWrk6, 1, imWrk6)
    mamba.threshold(imWrk6, imWrk4, 255, mamba.computeMaxRange(imWrk6)[1])
    mamba.copyBytePlane(imWrk6, 0, imWrk0)
    mamba.convert(imWrk4, imWrk2)
    mamba.logic(imWrk0, imWrk2, imWrk0, "sup")
    mamba.logic(imWrk0, imWrk1, imWrk0, "sup")
    imOut.reset()
    nbLevels = 0
    mamba.threshold(imWrk1, imWrk4, 1, 255)
    flag = not (mamba.checkEmptiness(imWrk4))
    while flag:
        hierarchy(imWrk1, imWrk4, imWrk2, grid=grid)
        mamba.add(imOut, imWrk4, imOut)
        mamba.valuedWatershed(imWrk2, imWrk3, grid=grid)
        mamba.threshold(imWrk3, imWrk5, 1, 255)
        flag = not (mamba.checkEmptiness(imWrk5))
        hierarchy(imWrk3, imWrk5, imWrk2, grid=grid)
        mamba.generateSupMask(imWrk0, imWrk2, imWrk5, strict=False)
        mamba.logic(imWrk4, imWrk5, imWrk4, "inf")
        mamba.convertByMask(imWrk4, imWrk3, 0, 255)
        mamba.logic(imWrk1, imWrk3, imWrk3, "inf")
        mamba.negate(imWrk4, imWrk4)
        mamba.label(imWrk4, imWrk6, grid=grid)
        mamba.watershedSegment(imWrk3, imWrk6, grid=grid)
        mamba.copyBytePlane(imWrk6, 3, imWrk3)
        mamba.logic(imWrk1, imWrk2, imWrk1, "sup")
        mamba.logic(imWrk1, imWrk3, imWrk1, "inf")
        mamba.threshold(imWrk1, imWrk4, 1, 255)
        nbLevels += 1
    return nbLevels
Example #24
0
def standardSegment(imIn, imOut, gain=2.0, grid=mamba.DEFAULT_GRID):
    """
    General standard segmentation. This algorithm keeps the contours of the 
    watershed transform which are above or equal to the hierarchical image 
    associated to the next level of hierarchy when the altitude of the contour
    is multiplied by a 'gain' factor (default is 2.0). This transform also ends 
    by idempotence. All the hierarchical levels of image 'imIn'(which is a 
    valued watershed) are computed. 'imOut' contains all these hierarchies which
    are embedded, so that hierarchy i is simply obtained by a threshold
    [i+1, 255] of image 'imOut'.
    'imIn' and 'imOut' must be greyscale images. 'imIn' and 'imOut' must be
    different.
    This transformation returns the number of hierarchical levels.    
    """
    
    imWrk0 = mamba.imageMb(imIn)
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk3 = mamba.imageMb(imIn)
    imWrk4 = mamba.imageMb(imIn, 1)
    imWrk5 = mamba.imageMb(imIn, 1)
    imWrk6 = mamba.imageMb(imIn, 32)    
    mamba.copy(imIn, imWrk1)
    mamba.mulRealConst(imIn, gain, imWrk6)
    mamba.floorSubConst(imWrk6, 1, imWrk6)
    mamba.threshold(imWrk6, imWrk4, 255, mamba.computeMaxRange(imWrk6)[1])  
    mamba.copyBytePlane(imWrk6, 0, imWrk0)
    mamba.convert(imWrk4, imWrk2)
    mamba.logic(imWrk0, imWrk2, imWrk0, "sup")
    mamba.logic(imWrk0, imWrk1, imWrk0, "sup")
    imOut.reset()
    nbLevels = 0
    mamba.threshold(imWrk1, imWrk4, 1, 255)
    flag = not(mamba.checkEmptiness(imWrk4))
    while flag:
        hierarchy(imWrk1, imWrk4, imWrk2, grid=grid)
        mamba.add(imOut, imWrk4, imOut)
        mamba.valuedWatershed(imWrk2, imWrk3, grid=grid)
        mamba.threshold(imWrk3, imWrk5, 1, 255)
        flag = not(mamba.checkEmptiness(imWrk5))
        hierarchy(imWrk3, imWrk5, imWrk2, grid=grid)
        mamba.generateSupMask(imWrk0, imWrk2, imWrk5, strict=False)
        mamba.logic(imWrk4, imWrk5, imWrk4, "inf")
        mamba.convertByMask(imWrk4, imWrk3, 0, 255)
        mamba.logic(imWrk1, imWrk3, imWrk3, "inf")
        mamba.negate(imWrk4, imWrk4)
        mamba.label(imWrk4, imWrk6, grid=grid)
        mamba.watershedSegment(imWrk3, imWrk6, grid=grid)
        mamba.copyBytePlane(imWrk6, 3, imWrk3)
        mamba.logic(imWrk1, imWrk2, imWrk1, "sup")
        mamba.logic(imWrk1, imWrk3, imWrk1, "inf")
        mamba.threshold(imWrk1, imWrk4, 1, 255)
        nbLevels += 1
    return nbLevels
Example #25
0
def computeRange3D(imIn):
    """
    Computes the range, i.e. the minimum and maximum values, of 3D image 'imIn'.
    The values are returned in a tuple holding the minimum and the maximum.
    """
    mav,miv = mamba.computeMaxRange(imIn[0])
    
    for im2D in imIn:
        mi,ma = mamba.computeRange(im2D)
        miv = min(mi,miv)
        mav = max(ma,mav)
    return (miv,mav)
Example #26
0
def cellsExtract(imIn, imMarkers, imOut, grid=mamba.DEFAULT_GRID):
    """
    Geodesic reconstruction and extraction of the cells of the partition image
    'imIn' which are marked by the binary marker image 'imMarkers'. The marked
    cells keep their initial value. The result is stored in 'imOut'.
    The images can be 8-bit or 32-bit images.
    'grid' can be set to HEXAGONAL or SQUARE.
    """

    imWrk1 = mamba.imageMb(imIn)
    mamba.convertByMask(imMarkers, imWrk1, 0, mamba.computeMaxRange(imIn)[1])
    mamba.logic(imIn, imWrk1, imOut, "inf")
    cellsBuild(imIn, imOut, grid=grid)
Example #27
0
def cellsExtract(imIn, imMarkers, imOut, grid=mamba.DEFAULT_GRID):
    """
    Geodesic reconstruction and extraction of the cells of the partition image
    'imIn' which are marked by the binary marker image 'imMarkers'. The marked
    cells keep their initial value. The result is stored in 'imOut'.
    The images can be 8-bit or 32-bit images.
    'grid' can be set to HEXAGONAL or SQUARE.
    """
    
    imWrk1 = mamba.imageMb(imIn)
    mamba.convertByMask(imMarkers, imWrk1, 0, mamba.computeMaxRange(imIn)[1])
    mamba.logic(imIn, imWrk1, imOut, "inf")
    cellsBuild(imIn, imOut, grid=grid)
Example #28
0
def binarySkeletonByOpening(imIn, imOut1, imOut2, grid=mamba.DEFAULT_GRID, edge=mamba.FILLED):
    """
    Skeleton by openings (maximal balls skeleton) of binary image 'imIn'.
    'imOut1' contains the skeleton points (centers of maximal balls) and
    'imOut2' contains the associated function (that is the radius of each
    maximal ball included in the initial set.

    The operation is fast because it is computed through the use of the
    distance function of 'imIn' (skeleton points can be obtained by a
    Top Hat transform on the distance function).

    The edge is set to 'FILLED' by default.
    """

    imWrk1 = mamba.imageMb(imIn, 32)
    imWrk2 = mamba.imageMb(imIn, 32)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    mamba.computeDistance(imIn, imWrk1, grid=grid, edge=edge)
    mamba.whiteTopHat(imWrk1, imWrk2, 1, se=se)
    mamba.threshold(imWrk2, imOut1, 1, mamba.computeMaxRange(imWrk2)[1])
    mamba.convertByMask(imOut1, imWrk2, 0, mamba.computeMaxRange(imWrk2)[1])
    mamba.logic(imWrk1, imWrk2, imOut2, "inf")
Example #29
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)
Example #30
0
def minPartialBuild(imIn, imMask, imOut, grid=mamba.DEFAULT_GRID):
    """
    Performs the partial reconstruction of 'imIn' with its minima 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)
    minima(imIn, imWrk, 1, grid=grid)
    mamba.logic(imMask, imWrk, imWrk, "inf")
    mamba.convertByMask(imWrk, imOut, mamba.computeMaxRange(imIn)[1], 0)
    mamba.logic(imIn, imOut, imOut, "sup")
    mamba.dualBuild(imIn, imOut)
Example #31
0
def maxPartialBuild3D(imIn, imMask, imOut, grid=m3D.DEFAULT_GRID3D):
    """
    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 = m3D.image3DMb(imIn, 1)
    maxima3D(imIn, imWrk, 1, grid=grid)
    m3D.logic3D(imMask, imWrk, imWrk, "inf")
    m3D.convertByMask3D(imWrk, imOut, 0, mamba.computeMaxRange(imIn[0])[1])
    m3D.logic3D(imIn, imOut, imOut, "inf")
    m3D.build3D(imIn, imOut)
Example #32
0
def minPartialBuild3D(imIn, imMask, imOut, grid=m3D.DEFAULT_GRID3D):
    """
    Performs the partial reconstruction of 'imIn' with its minima which are
    contained in the binary mask 'imMask'. The result is put in 'imOut'.
    
    'imIn' and 'imOut' must be different and greyscale images.
    """
    
    imWrk = m3D.image3DMb(imIn, 1)
    minima3D(imIn, imWrk, 1, grid=grid)
    m3D.logic3D(imMask, imWrk, imWrk, "inf")
    m3D.convertByMask3D(imWrk, imOut, mamba.computeMaxRange(imIn[0])[1], 0)
    m3D.logic3D(imIn, imOut, imOut, "sup")
    m3D.dualBuild3D(imIn, imOut)
Example #33
0
def floorSubConst(imIn, v, imOut):
    """
    Subtracts a constant value 'v' to image 'imIn' and puts the result in 'imOut'.
    If imIn - v is negative, the result is truncated and limited to 0.
    
    Note that this operator is mainly useful for 32-bit images, as the result
    of the subtraction is always truncated for 8-bit images.
    """
    
    imMask = mamba.imageMb(imIn, 1)
    imWrk = mamba.imageMb(imIn)
    mamba.subConst(imIn, v, imWrk)
    mamba.generateSupMask(imIn, imWrk, imMask, False)
    mamba.convertByMask(imMask, imOut, 0, mamba.computeMaxRange(imOut)[1])
    mamba.logic(imOut, imWrk, imOut, "inf")
Example #34
0
def ceilingAddConst(imIn, v, imOut):
    """
    Adds a constant value 'v' to image 'imIn' and puts the result in 'imOut'. If
    imIn + v is larger than the maximal possible value in imOut, the result is
    truncated and limited to this maximal value.
    
    Note that this operator is mainly useful for 32-bit images, as the result
    of the addition is always truncated for 8-bit images.
    """
    
    imMask = mamba.imageMb(imIn, 1)
    imWrk = mamba.imageMb(imIn)
    mamba.addConst(imIn, v, imWrk)
    mamba.generateSupMask(imIn, imWrk, imMask, True)
    mamba.convertByMask(imMask, imOut, 0, mamba.computeMaxRange(imOut)[1])
    mamba.logic(imOut, imWrk, imOut, "sup")
Example #35
0
def maxima3D(imIn, imOut, h=1, grid=m3D.DEFAULT_GRID3D):
    """
    Computes the maxima of 'imIn' using a build operation and puts the
    result in 'imOut'.
    
    'h' can be used to define the maxima height. Grid used by the build
    operation can be specified by 'grid'.
    
    Only works with 8-bit or 32-bit as input. 'imOut' must be binary.
    """
    
    imWrk = m3D.image3DMb(imIn)
    m3D.subConst3D(imIn, h, imWrk)
    m3D.build3D(imIn, imWrk, grid=grid)
    m3D.sub3D(imIn, imWrk, imWrk)
    m3D.threshold3D(imWrk, imOut, 1, mamba.computeMaxRange(imIn[0])[1])
Example #36
0
def cellsErode(imIn, imOut, n=1, se=mamba.DEFAULT_SE, edge=mamba.FILLED):
    """
    Simultaneous erosion of size 'n' (default 1) of all the cells of the
    partition image 'imIn' with 'se' structuring element.
    The resulting partition is put in 'imOut'.
    'edge' is set to FILLED by default.
    This operation works on 8-bit and 32-bit partitions.
    """
    
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn, 1)
    mamba.dilate(imIn, imWrk1, n=n, se=se)
    mamba.erode(imIn, imOut, n=n, se=se, edge=edge)
    mamba.generateSupMask(imOut, imWrk1, imWrk2, False)
    mamba.convertByMask(imWrk2, imWrk1, 0, mamba.computeMaxRange(imIn)[1])
    mamba.logic(imOut, imWrk1, imOut, "inf")
Example #37
0
def cellsErode(imIn, imOut, n=1, se=mamba.DEFAULT_SE, edge=mamba.FILLED):
    """
    Simultaneous erosion of size 'n' (default 1) of all the cells of the
    partition image 'imIn' with 'se' structuring element.
    The resulting partition is put in 'imOut'.
    'edge' is set to FILLED by default.
    This operation works on 8-bit and 32-bit partitions.
    """

    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn, 1)
    mamba.dilate(imIn, imWrk1, n=n, se=se)
    mamba.erode(imIn, imOut, n=n, se=se, edge=edge)
    mamba.generateSupMask(imOut, imWrk1, imWrk2, False)
    mamba.convertByMask(imWrk2, imWrk1, 0, mamba.computeMaxRange(imIn)[1])
    mamba.logic(imOut, imWrk1, imOut, "inf")
Example #38
0
def maxima3D(imIn, imOut, h=1, grid=m3D.DEFAULT_GRID3D):
    """
    Computes the maxima of 'imIn' using a build operation and puts the
    result in 'imOut'.
    
    'h' can be used to define the maxima height. Grid used by the build
    operation can be specified by 'grid'.
    
    Only works with 8-bit or 32-bit as input. 'imOut' must be binary.
    """

    imWrk = m3D.image3DMb(imIn)
    m3D.subConst3D(imIn, h, imWrk)
    m3D.build3D(imIn, imWrk, grid=grid)
    m3D.sub3D(imIn, imWrk, imWrk)
    m3D.threshold3D(imWrk, imOut, 1, mamba.computeMaxRange(imIn[0])[1])
Example #39
0
def floorSub(imIn1, imIn2, imOut):
    """
    Subtracts image 'imIn2' from image 'imIn1' and puts the result in 'imOut'.
    If imIn1 - imIn2 is negative, the result is truncated and limited to 0.
    
    Although it is possible to use a 8-bit image for imIn2, it is recommended to
    use the same depth for all the images.
    
    Note that this operator is mainly useful for 32-bit images, as the result
    of the subtraction is always truncated for 8-bit images.
    """
    
    imMask = mamba.imageMb(imIn1, 1)
    imWrk = mamba.imageMb(imIn1)
    mamba.sub(imIn1, imIn2, imWrk)
    mamba.generateSupMask(imIn1, imWrk, imMask, False)
    mamba.convertByMask(imMask, imOut, 0, mamba.computeMaxRange(imOut)[1])
    mamba.logic(imOut, imWrk, imOut, "inf")
Example #40
0
def ceilingAdd(imIn1, imIn2, imOut):
    """
    Adds image 'imIn2' to image 'imIn1' and puts the result in 'imOut'. If
    imIn1 + imIn2 is larger than the maximal possible value in imOut, the result
    is truncated and limited to this maximal value.
    
    Although it is possible to use a 8-bit image for imIn2, it is recommended to
    use the same depth for all the images.
    
    Note that this operator is mainly useful for 32-bit images, as the result
    of the addition is always truncated for 8-bit images.
    """
    
    imMask = mamba.imageMb(imIn1, 1)
    imWrk = mamba.imageMb(imIn1)
    mamba.add(imIn1, imIn2, imWrk)
    mamba.generateSupMask(imIn1, imWrk, imMask, True)
    mamba.convertByMask(imMask, imOut, 0, mamba.computeMaxRange(imOut)[1])
    mamba.logic(imOut, imWrk, imOut, "sup")
Example #41
0
def erode(imIn, imOut, n=1, se=DEFAULT_SE, edge=mamba.FILLED):
    """
    This operator corresponds, for erosion, to the dilation operator. It performs
    an erosion using the default structuring element of image 'imIn' and puts the
    result in 'imOut'. The operation is repeated 'n' times (default is 1). This
    function will assume a FILLED edge unless specified otherwise using 'edge'.
    
    This operator always considers that the origin of the structuring element in
    use is at position 0 even if this point does not belong to it.
    """

    imWrk = mamba.imageMb(imIn)
    mamba.copy(imIn, imOut)
    dirs = se.getEncodedDirections(withoutZero=True)
    for i in range(n):
        mamba.copy(imOut, imWrk)
        if not se.hasZero():
            imOut.fill(mamba.computeMaxRange(imIn)[1])
        infNeighbor(imWrk, imOut, dirs, grid=se.getGrid(), edge=edge)
Example #42
0
def minDynamics(imIn, imOut, h, grid=mamba.DEFAULT_GRID):
    """
    Extracts the minima 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.addConst(imIn, h, imWrk)
        mamba.hierarDualBuild(imIn, imWrk, grid=grid)
        mamba.sub(imWrk, imIn, imWrk)
    else:
        mamba.ceilingAddConst(imIn, h, imWrk)
        mamba.dualBuild(imIn, imWrk, grid=grid)
        mamba.floorSub(imWrk, imIn, imWrk)
    mamba.threshold(imWrk, imOut, h, mamba.computeMaxRange(imIn)[1])
Example #43
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])
Example #44
0
def maxDynamics3D(imIn, imOut, h, grid=m3D.DEFAULT_GRID3D):
    """
    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 = m3D.image3DMb(imIn)
    if imIn.getDepth() == 8:
        m3D.subConst3D(imIn, h, imWrk)
        m3D.build3D(imIn, imWrk, grid=grid)
        m3D.sub3D(imIn, imWrk, imWrk)
    else:
        m3D.floorSubConst3D(imIn, h, imWrk)
        m3D.build3D(imIn, imWrk, grid=grid)
        m3D.floorSub3D(imIn, imWrk, imWrk)
    m3D.threshold3D(imWrk, imOut, h, mamba.computeMaxRange(imIn[0])[1])
Example #45
0
def minDynamics3D(imIn, imOut, h, grid=m3D.DEFAULT_GRID3D):
    """
    Extracts the minima 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 = m3D.image3DMb(imIn)
    if imIn.getDepth() == 8:
        m3D.addConst3D(imIn, h, imWrk)
        m3D.dualBuild3D(imIn, imWrk, grid=grid)
        m3D.sub3D(imWrk, imIn, imWrk)
    else:
        m3D.ceilingAddConst3D(imIn, h, imWrk)
        m3D.dualBuild3D(imIn, imWrk, grid=grid)
        m3D.floorSub3D(imWrk, imIn, imWrk)
    m3D.threshold3D(imWrk, imOut, h, mamba.computeMaxRange(imIn[0])[1])
Example #46
0
def equalNeighbors(imIn, imOut, nb, grid=mamba.DEFAULT_GRID, edge=mamba.FILLED):
    """
    This operator compares the value of each pixel of image 'imIn'
    with the value of its neighbors encoded in 'nb'.
    If all the neighbor values are equal, the pixel is unchanged.
    Otherwise, it takes value 0.
    This operator works on hexagonal or square 'grid' and 
    'edge' is set to FILLED by default.
    This operator works for 8-bit and 32-bit images.
    """
    
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn, 1)
    mamba.copy(imIn, imWrk1)
    mamba.copy(imIn, imOut)
    mamba.supNeighbor(imIn, imWrk1, nb, grid=grid, edge=edge)
    mamba.infNeighbor(imOut, imOut, nb, grid=grid, edge=edge)
    mamba.generateSupMask(imOut, imWrk1, imWrk2, False)
    mamba.convertByMask(imWrk2, imWrk1, 0, mamba.computeMaxRange(imIn)[1])
    mamba.logic(imOut, imWrk1, imOut, "inf")
Example #47
0
def infFarNeighbor3D(imIn, imInOut, nb, amp, grid=m3D.DEFAULT_GRID3D, edge=mamba.FILLED):
    """
    Performs an infimum operation between the 'imInOut' 3D image pixels and their neighbor 'nb'
    at distance 'amp' according to 'grid' in 3D image 'imIn'. The result is put in 'imInOut'.
    "grid' value can be CUBIC, CENTER_CUBIC or FACE_CENTER_CUBIC. 'edge' value can be EMPTY
    or FILLED.
    """
    
    (width,height,length) = imIn.getSize()
    if length!=len(imInOut):
        mamba.raiseExceptionOnError(core.MB_ERR_BAD_SIZE)
    imWrk = mamba.imageMb(imIn[0])
    # Computing limits according to the scanning direction.
    scan = grid.convertFromDir(nb,0)[0]
    if scan == 0:
        startPlane, endPlane, scanDir = 0, length, 1
        startFill, endFill = 0, 0
    elif scan == 1:
        startPlane, endPlane, scanDir = 0, length - amp, 1
        startFill, endFill = max(length - amp, 0), length
    else:
        startPlane, endPlane, scanDir = length - 1, amp - 1, -1
        startFill, endFill = 0, min(amp, length)    
    # Performing the shift operations given by the getShiftDirList method.
    if edge == mamba.EMPTY:
        fillValue = 0
    else:
        fillValue = mamba.computeMaxRange(imIn[0])[1]
    for i in range(startPlane, endPlane, scanDir):
        j = i + amp * scan
        dirList = grid.getShiftDirsList(nb, amp, i)
        if len(dirList) == 1:
            mamba.infFarNeighbor(imIn[j], imInOut[i], dirList[0][0] , dirList[0][1], grid=dirList[0][2], edge=edge)
        else:
            d = mamba.transposeDirection(dirList[1][0], dirList[1][2])
            mamba.shift(imIn[j], imWrk, d, dirList[1][1], fillValue, grid=dirList[1][2])
            mamba.infFarNeighbor(imWrk, imInOut[i], dirList[0][0] , dirList[0][1], grid=dirList[0][2], edge=edge)            
    # Filling the necessary planes.
    if edge == mamba.EMPTY:
        for i in range(startFill, endFill):
            imInOut[i].fill(fillValue)