Ejemplo n.º 1
0
def rotatingThin(imIn, imOut, dse, edge=mamba.FILLED):
    """
    Performs a complete rotation of thinnings , the initial 'dse' double
    structuring element being turned one step clockwise after each thinning.
    At each rotation step, the previous result is used as input for the next
    thinning (chained thinnings). Depending on the grid where 'dse' is defined,
    6 or 8 rotations are performed.
    
    'imIn' and 'imOut' are binary images.
    
    'edge' is set to FILLED by default (default value is EMPTY in simple thin).
    """
    
    imWrk = mamba.imageMb(imIn)
    if edge == mamba.FILLED:
        mamba.negate(imIn, imOut)
        for d in mamba.getDirections(dse.getGrid(), True):
            hitOrMiss(imOut, imWrk, dse.flip(), edge=mamba.EMPTY)
            mamba.logic(imWrk, imOut, imOut, "sup")
            dse = dse.rotate()
        mamba.negate(imOut, imOut)
    else:
        mamba.copy(imIn, imOut)
        for d in mamba.getDirections(dse.getGrid(), True):
            hitOrMiss(imOut, imWrk, dse, edge=mamba.EMPTY)
            mamba.diff(imOut, imWrk, imOut)
            dse = dse.rotate()
Ejemplo n.º 2
0
def rotatingThin(imIn, imOut, dse, edge=mamba.FILLED):
    """
    Performs a complete rotation of thinnings , the initial 'dse' double
    structuring element being turned one step clockwise after each thinning.
    At each rotation step, the previous result is used as input for the next
    thinning (chained thinnings). Depending on the grid where 'dse' is defined,
    6 or 8 rotations are performed.
    
    'imIn' and 'imOut' are binary images.
    
    'edge' is set to FILLED by default (default value is EMPTY in simple thin).
    """

    imWrk = mamba.imageMb(imIn)
    if edge == mamba.FILLED:
        mamba.negate(imIn, imOut)
        for d in mamba.getDirections(dse.getGrid(), True):
            hitOrMiss(imOut, imWrk, dse.flip(), edge=mamba.EMPTY)
            mamba.logic(imWrk, imOut, imOut, "sup")
            dse = dse.rotate()
        mamba.negate(imOut, imOut)
    else:
        mamba.copy(imIn, imOut)
        for d in mamba.getDirections(dse.getGrid(), True):
            hitOrMiss(imOut, imWrk, dse, edge=mamba.EMPTY)
            mamba.diff(imOut, imWrk, imOut)
            dse = dse.rotate()
Ejemplo 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")
Ejemplo n.º 4
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")
Ejemplo n.º 5
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)
Ejemplo n.º 6
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)
Ejemplo n.º 7
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)
Ejemplo n.º 8
0
def _initialQuasiDist_(imIn, imOut1, imOut2, grid=mamba.DEFAULT_GRID):
    """
    Computes the initial quasi-distance. For internal use only. The resulting
    quasi-distance is not lipchitzian (see MM documentation for details).
    """
    
    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.sub(imWrk1, imWrk2, imWrk1)
        _generateMask_(imWrk1, imOut1, maskIm)
        mamba.convertByMask(maskIm, imWrk3, 0, i)
        mamba.logic(imOut1, imWrk1, imOut1, "sup")
        mamba.logic(imOut2, imWrk3, imOut2, "sup")
        mamba.copy(imWrk2, imWrk1)
        v2 = mamba.computeVolume(imWrk1)
Ejemplo n.º 9
0
def mosaicGradient(imIn, imOut, grid=mamba.DEFAULT_GRID):
    """
    Builds the mosaic-gradient image of 'imIn' and puts the result in 'imOut'.
    The mosaic-gradient image is built by computing the differences of two
    mosaic images generated from 'imIn', the first one having its watershed
    lines valued by the suprema of the adjacent catchment basins values, the
    second one been valued by the infima.
    """

    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk3 = mamba.imageMb(imIn)
    imWrk4 = mamba.imageMb(imIn)
    imWrk5 = mamba.imageMb(imIn)
    imWrk6 = mamba.imageMb(imIn, 1)
    mosaic(imIn, imWrk2, imWrk3, grid=grid)
    mamba.sub(imWrk2, imWrk3, imWrk1)
    mamba.logic(imWrk2, imWrk3, imWrk2, "sup")
    mamba.negate(imWrk2, imWrk2)
    mamba.threshold(imWrk3, imWrk6, 1, 255)
    mamba.multiplePoints(imWrk6, imWrk6, grid=grid)
    mamba.convertByMask(imWrk6, imWrk3, 0, 255)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    mamba.dilate(imWrk1, imWrk4, se=se)
    mamba.dilate(imWrk2, imWrk5, se=se)
    while mamba.computeVolume(imWrk3) != 0:
        mamba.dilate(imWrk1, imWrk1, 2, se=se)
        mamba.dilate(imWrk2, imWrk2, 2, se=se)
        mamba.logic(imWrk1, imWrk3, imWrk1, "inf")
        mamba.logic(imWrk2, imWrk3, imWrk2, "inf")
        mamba.logic(imWrk1, imWrk4, imWrk4, "sup")
        mamba.logic(imWrk2, imWrk5, imWrk5, "sup")
        mamba.erode(imWrk3, imWrk3, 2, se=se)
    mamba.negate(imWrk5, imWrk5)
    mamba.sub(imWrk4, imWrk5, imOut)
Ejemplo n.º 10
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")
Ejemplo n.º 11
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)
Ejemplo n.º 12
0
def mosaicGradient(imIn, imOut, grid=mamba.DEFAULT_GRID):
    """
    Builds the mosaic-gradient image of 'imIn' and puts the result in 'imOut'.
    The mosaic-gradient image is built by computing the differences of two
    mosaic images generated from 'imIn', the first one having its watershed
    lines valued by the suprema of the adjacent catchment basins values, the
    second one been valued by the infima.
    """

    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk3 = mamba.imageMb(imIn)
    imWrk4 = mamba.imageMb(imIn)
    imWrk5 = mamba.imageMb(imIn)
    imWrk6 = mamba.imageMb(imIn, 1)
    mosaic(imIn, imWrk2, imWrk3, grid=grid)
    mamba.sub(imWrk2, imWrk3, imWrk1)
    mamba.logic(imWrk2, imWrk3, imWrk2, "sup")
    mamba.negate(imWrk2, imWrk2)
    mamba.threshold(imWrk3, imWrk6, 1, 255)
    mamba.multiplePoints(imWrk6, imWrk6, grid=grid)
    mamba.convertByMask(imWrk6, imWrk3, 0, 255)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    mamba.dilate(imWrk1, imWrk4, se=se)
    mamba.dilate(imWrk2, imWrk5, se=se)
    while mamba.computeVolume(imWrk3) != 0:
        mamba.dilate(imWrk1, imWrk1, 2, se=se)
        mamba.dilate(imWrk2, imWrk2, 2, se=se)
        mamba.logic(imWrk1, imWrk3, imWrk1, "inf")
        mamba.logic(imWrk2, imWrk3, imWrk2, "inf")
        mamba.logic(imWrk1, imWrk4, imWrk4, "sup")
        mamba.logic(imWrk2, imWrk5, imWrk5, "sup")
        mamba.erode(imWrk3, imWrk3, 2, se=se)
    mamba.negate(imWrk5, imWrk5)
    mamba.sub(imWrk4, imWrk5, imOut)
Ejemplo n.º 13
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")
Ejemplo n.º 14
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)
Ejemplo n.º 15
0
def removeEdgeParticles(imIn, imOut, grid=mamba.DEFAULT_GRID):
    """
    Removes particles (connected components) touching the edge in image 'imIn'.
    The resulting image is put in image 'imOut'.
    Although this operator may be used with greytone images, it should be
    considered with caution.
    """
    
    imWrk = mamba.imageMb(imIn)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    mamba.dilate(imWrk, imWrk, se=se, edge=mamba.FILLED)
    mamba.logic(imIn, imWrk, imWrk, "inf")
    build(imIn, imWrk, grid=grid)
    mamba.diff(imIn, imWrk, imOut)
Ejemplo n.º 16
0
def neighborCounter(imIn, imOut, grid=mamba.DEFAULT_GRID):
    """
    For each pixel set to true in the binary image 'imIn', this function
    counts its neighbor set to true and puts the result in 'imOut'. The
    neighbors are selected according to 'grid'.
    """

    imWrk = mamba.imageMb(imIn)
    imOut.reset()
    
    for d in mamba.getDirections(grid)[1:]:
        dse = mamba.doubleStructuringElement([],[0,d],grid)
        mamba.hitOrMiss(imIn, imWrk, dse)
        mamba.add(imOut, imWrk, imOut)
Ejemplo n.º 17
0
def neighborCounter(imIn, imOut, grid=mamba.DEFAULT_GRID):
    """
    For each pixel set to true in the binary image 'imIn', this function
    counts its neighbor set to true and puts the result in 'imOut'. The
    neighbors are selected according to 'grid'.
    """

    imWrk = mamba.imageMb(imIn)
    imOut.reset()

    for d in mamba.getDirections(grid)[1:]:
        dse = mamba.doubleStructuringElement([], [0, d], grid)
        mamba.hitOrMiss(imIn, imWrk, dse)
        mamba.add(imOut, imWrk, imOut)
Ejemplo n.º 18
0
def regularisedGradient(imIn, imOut, n, grid=mamba.DEFAULT_GRID):
    """
    Computes the regularized gradient of image 'imIn' of size 'n'.
    The result is put in 'imOut'. A regularized gradient of size 'n' extracts
    in the image contours thinner than 'n' while avoiding false detections.
    
    This operation is only valid for omnidirectional structuring elements.
    """
    
    imWrk = mamba.imageMb(imIn)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    gradient(imIn, imWrk, n, se=se)
    whiteTopHat(imWrk, imWrk, n, se=se)
    mamba.erode(imWrk, imOut, n-1, se=se)
Ejemplo n.º 19
0
def partitionDilate(imIn, imOut, n=1, grid=mamba.DEFAULT_GRID):
    """
    Graph dilation of the corresponding partition image 'imIn'. The size is given
    by 'n'. The corresponding partition image of the resulting dilated graph is
    put in 'imOut'.
    'grid' can be set to HEXAGONAL or SQUARE.
    """

    imWrk = mamba.imageMb(imIn)
    mamba.copy(imIn, imOut)
    mamba.copy(imIn, imWrk)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    for i in range(n):
        mamba.dilate(imOut, imOut, se=se)
        cellsBuild(imWrk, imOut, grid=grid)
Ejemplo n.º 20
0
def partitionDilate(imIn, imOut, n=1, grid=mamba.DEFAULT_GRID):
    """
    Graph dilation of the corresponding partition image 'imIn'. The size is given
    by 'n'. The corresponding partition image of the resulting dilated graph is
    put in 'imOut'.
    'grid' can be set to HEXAGONAL or SQUARE.
    """
    
    imWrk = mamba.imageMb(imIn)
    mamba.copy(imIn, imOut)
    mamba.copy(imIn, imWrk)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    for i in range(n):
        mamba.dilate(imOut, imOut, se=se)
        cellsBuild(imWrk, imOut, grid=grid)
Ejemplo n.º 21
0
def cellsComputeDistance(imIn, imOut, grid=mamba.DEFAULT_GRID, edge=mamba.EMPTY):
    """
    Computation of the distance function for each cell of the partition
    image 'imIn'.
    The result is put in the 32-bit image 'imOut'.
    This operator works on hexagonal or square 'grid' and
    'edge' is set to EMPTY by default.
    """
    
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn, 1)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    cellsErode(imIn, imWrk1, 1, se=se, edge=edge)
    mamba.threshold(imWrk1, imWrk2, 1, 255)
    mamba.computeDistance(imWrk2, imOut, grid=grid, edge=edge)
    mamba.addConst(imOut, 1, imOut)
Ejemplo n.º 22
0
def cellsComputeDistance(imIn,
                         imOut,
                         grid=mamba.DEFAULT_GRID,
                         edge=mamba.EMPTY):
    """
    Computation of the distance function for each cell of the partition
    image 'imIn'.
    The result is put in the 32-bit image 'imOut'.
    This operator works on hexagonal or square 'grid' and
    'edge' is set to EMPTY by default.
    """

    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn, 1)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    cellsErode(imIn, imWrk1, 1, se=se, edge=edge)
    mamba.threshold(imWrk1, imWrk2, 1, 255)
    mamba.computeDistance(imWrk2, imOut, grid=grid, edge=edge)
    mamba.addConst(imOut, 1, imOut)
Ejemplo n.º 23
0
def rotatingThick(imIn, imOut, dse):
    """
    Performs a complete rotation of thickenings, the initial 'dse' double
    structuring element being turned one step clockwise after each thickening.
    At each rotation step, the previous result is used as input for the next
    thickening (chained thickenings). Depending on the grid where 'dse' is defined,
    6 or 8 rotations are performed.
    
    'imIn' and 'imOut' are binary images.
    
    The edge is always set to EMPTY.
    """
    
    imWrk = mamba.imageMb(imIn)
    mamba.copy(imIn, imOut)
    for d in mamba.getDirections(dse.getGrid(), True):
        hitOrMiss(imOut, imWrk, dse, edge=mamba.EMPTY)
        mamba.logic(imWrk, imOut, imOut, "sup")
        dse = dse.rotate()
Ejemplo n.º 24
0
def dualBuild(imMask, imInout, grid=mamba.DEFAULT_GRID):
    """
    Builds (dual build) image 'imInout' using 'imMask' as a mask. This operator
    performs the geodesic dual reconstruction (by erosions) of 'imInout' inside
    the mask image and puts the result in the same image.
    
    This operator uses a recursive implementation of the reconstruction.
    
    This function will use the mamba default grid unless specified otherwise in
    'grid'.
    """
    
    vol = 0
    prec_vol = -1
    dirs = mamba.getDirections(grid, True)
    while(prec_vol!=vol):
        prec_vol = vol
        for d in dirs:
            vol = dualbuildNeighbor(imMask, imInout, d, grid)
Ejemplo n.º 25
0
def rotatingThick(imIn, imOut, dse):
    """
    Performs a complete rotation of thickenings, the initial 'dse' double
    structuring element being turned one step clockwise after each thickening.
    At each rotation step, the previous result is used as input for the next
    thickening (chained thickenings). Depending on the grid where 'dse' is defined,
    6 or 8 rotations are performed.
    
    'imIn' and 'imOut' are binary images.
    
    The edge is always set to EMPTY.
    """

    imWrk = mamba.imageMb(imIn)
    mamba.copy(imIn, imOut)
    for d in mamba.getDirections(dse.getGrid(), True):
        hitOrMiss(imOut, imWrk, dse, edge=mamba.EMPTY)
        mamba.logic(imWrk, imOut, imOut, "sup")
        dse = dse.rotate()
Ejemplo n.º 26
0
def ultimateOpening(imIn, imOut1, imOut2, grid=mamba.DEFAULT_GRID):
    """
    Ultimate opening of image 'imIn'. 'imOut1' contains the ultimate 
    opening whereas 'imOut2' contains the granulometric function.
    
    Ultimate opening is obtained by using successive openings by hexagons or
    squares as primitive functions depending of the grid in use.
    
    Depth of 'imOut1' is the same as 'imIn', depth of 'imOut2' is 32. 
    """

    maskIm = mamba.imageMb(imIn, 1)
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk3 = mamba.imageMb(imIn, 32)
    imWrk4 = mamba.imageMb(imIn)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    i = 0
    mamba.copy(imIn, imWrk1)
    v2 = mamba.computeVolume(imWrk1)
    mamba.copy(imWrk1, imWrk4)
    v1 = v2 + 1
    imOut1.reset()
    imOut2.reset()
    if grid == mamba.HEXAGONAL:
        dilation = mamba.largeHexagonalDilate
    else:
        dilation = mamba.largeSquareDilate
    while v1 > v2:
        i += 1
        v1 = v2
        mamba.erode(imWrk4, imWrk4, se=se)
        dilation(imWrk4, imWrk2, i)
        mamba.sub(imWrk1, imWrk2, imWrk1)
        _generateMask_(imWrk1, imOut1, maskIm)
        mamba.convertByMask(maskIm, imWrk3, 0, i)
        mamba.logic(imOut1, imWrk1, imOut1, "sup")
        mamba.logic(imOut2, imWrk3, imOut2, "sup")
        v2 = mamba.computeVolume(imWrk4)
        mamba.copy(imWrk2, imWrk1)
Ejemplo n.º 27
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")
Ejemplo n.º 28
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)
Ejemplo n.º 29
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)
Ejemplo n.º 30
0
def ultimateBuildOpening(imIn, imOut1, imOut2, grid=mamba.DEFAULT_GRID):
    """
    Ultimate opening  by build of image 'imIn'. 'imOut1' contains the ultimate
    opening whereas 'imOut2' contains the granulometric function.
    
    This ultimate opening is obtained by using successive openings by build.
    
    Depth of 'imOut1' is the same as 'imIn', depth of 'imOut2' is 32. 
    """

    maskIm = mamba.imageMb(imIn, 1)
    imWrk1 = mamba.imageMb(imIn)
    imWrk2 = mamba.imageMb(imIn)
    imWrk3 = mamba.imageMb(imIn, 32)
    imWrk4 = mamba.imageMb(imIn)
    se = mamba.structuringElement(mamba.getDirections(grid), grid)
    i = 0
    mamba.copy(imIn, imWrk1)
    v2 = mamba.computeVolume(imWrk1)
    mamba.copy(imWrk1, imWrk4)
    v1 = v2 + 1
    imOut1.reset()
    imOut2.reset()
    while v1 > v2:
        i += 1
        v1 = v2
        mamba.erode(imWrk4, imWrk4, se=se)
        mamba.copy(imWrk4, imWrk2)
        mamba.hierarBuild(imWrk1, imWrk2, grid=mamba.DEFAULT_GRID)
        mamba.sub(imWrk1, imWrk2, imWrk1)
        _generateMask_(imWrk1, imOut1, maskIm)
        mamba.convertByMask(maskIm, imWrk3, 0, i)
        mamba.logic(imOut1, imWrk1, imOut1, "sup")
        mamba.logic(imOut2, imWrk3, imOut2, "sup")
        v2 = mamba.computeVolume(imWrk4)
        mamba.copy(imWrk2, imWrk1)
Ejemplo n.º 31
0
def skeletonByOpening(imIn, imOut1, imOut2, grid=mamba.DEFAULT_GRID):
    """
    General skeleton by openings working on greytone image 'imIn'.
    'imOut1' contains the skeleton function and 'imOut2' contains the 
    associated function.
    
    This skeleton corresponds to the centers of maximal cylinders included
    in the set under the graph of the image 'imIn'.
    
    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.opening(imWrk1, imWrk2, se=se)
        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)