Example #1
0
def lowerGeodesicErode3D(imIn, imMask, imOut, n=1, se=m3D.CUBOCTAHEDRON1):
    """
    Performs a lower geodesic erosion of 3D 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 (CUBOCTAHEDRON 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:
        m3D.diff3D(imMask, imIn, imOut)
        lowerGeodesicDilate3D(imOut, imMask, imOut, n, se=se)
        m3D.diff3D(imMask, imOut, imOut)
    else:
        imWrk1 = m3D.image3DMb(imIn)
        imWrk2 = m3D.image3DMb(imIn, 1)
        m3D.logic3D(imIn, imMask, imOut, "inf")
        for i in range(n):
            m3D.generateSupMask3D(imOut, imMask, imWrk2, False)
            m3D.convertByMask3D(imWrk2, imWrk1, 0, m3D.computeMaxRange3D(imWrk1)[1])
            m3D.logic3D(imOut, imWrk1, imOut, "sup")
            m3D.erode3D(imOut, imOut, se=se)
            m3D.logic3D(imOut, imMask, imOut, "inf")
Example #2
0
def upperGeodesicDilate3D(imIn, imMask, imOut, n=1, se=m3D.CUBOCTAHEDRON1):
    """
    Performs a upper geodesic dilation of 3D 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 (CUBOCTAHEDRON by default). 
    
    Warning! 'imMask' and 'imOut' must be different.
    """
    
    m3D.logic3D(imIn, imMask, imOut, "sup")
    if imIn.getDepth() == 1:
        for i in range(n):
            m3D.diff3D(imOut, imMask, imOut)
            m3D.dilate3D(imOut, imOut, se=se)
            m3D.logic3D(imMask, imOut, imOut, "sup")
    else:
        imWrk1 = m3D.image3DMb(imIn)
        imWrk2 = m3D.image3DMb(imIn, 1)
        for i in range(n):
            m3D.generateSupMask3D(imOut, imMask, imWrk2, True)
            m3D.convertByMask3D(imWrk2, imWrk1, 0, m3D.computeMaxRange3D(imWrk1)[1])
            m3D.logic3D(imOut, imWrk1, imOut, "inf")
            m3D.dilate3D(imOut, imOut, se=se)
            m3D.logic3D(imOut, imMask, imOut, "sup")
Example #3
0
def upperGeodesicDilate3D(imIn, imMask, imOut, n=1, se=m3D.CUBOCTAHEDRON1):
    """
    Performs a upper geodesic dilation of 3D 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 (CUBOCTAHEDRON by default). 
    
    Warning! 'imMask' and 'imOut' must be different.
    """

    m3D.logic3D(imIn, imMask, imOut, "sup")
    if imIn.getDepth() == 1:
        for i in range(n):
            m3D.diff3D(imOut, imMask, imOut)
            m3D.dilate3D(imOut, imOut, se=se)
            m3D.logic3D(imMask, imOut, imOut, "sup")
    else:
        imWrk1 = m3D.image3DMb(imIn)
        imWrk2 = m3D.image3DMb(imIn, 1)
        for i in range(n):
            m3D.generateSupMask3D(imOut, imMask, imWrk2, True)
            m3D.convertByMask3D(imWrk2, imWrk1, 0,
                                m3D.computeMaxRange3D(imWrk1)[1])
            m3D.logic3D(imOut, imWrk1, imOut, "inf")
            m3D.dilate3D(imOut, imOut, se=se)
            m3D.logic3D(imOut, imMask, imOut, "sup")
Example #4
0
def lowerGeodesicErode3D(imIn, imMask, imOut, n=1, se=m3D.CUBOCTAHEDRON1):
    """
    Performs a lower geodesic erosion of 3D 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 (CUBOCTAHEDRON 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:
        m3D.diff3D(imMask, imIn, imOut)
        lowerGeodesicDilate3D(imOut, imMask, imOut, n, se=se)
        m3D.diff3D(imMask, imOut, imOut)
    else:
        imWrk1 = m3D.image3DMb(imIn)
        imWrk2 = m3D.image3DMb(imIn, 1)
        m3D.logic3D(imIn, imMask, imOut, "inf")
        for i in range(n):
            m3D.generateSupMask3D(imOut, imMask, imWrk2, False)
            m3D.convertByMask3D(imWrk2, imWrk1, 0,
                                m3D.computeMaxRange3D(imWrk1)[1])
            m3D.logic3D(imOut, imWrk1, imOut, "sup")
            m3D.erode3D(imOut, imOut, se=se)
            m3D.logic3D(imOut, imMask, imOut, "inf")
Example #5
0
def simpleLevelling3D(imIn, imMask, imOut, grid=m3D.DEFAULT_GRID3D):
    """
    Performs a simple levelling of 3D 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 = m3D.image3DMb(imIn)
    imWrk2 = m3D.image3DMb(imIn)
    mask_im = m3D.image3DMb(imIn, 1)
    m3D.logic3D(imIn, imMask, imWrk1, "inf")
    m3D.build3D(imIn, imWrk1, grid=grid)
    m3D.logic3D(imIn, imMask, imWrk2, "sup")
    m3D.dualBuild3D(imIn, imWrk2, grid=grid)
    m3D.generateSupMask3D(imIn, imMask, mask_im, False)
    m3D.convertByMask3D(mask_im, imOut, 0, m3D.computeMaxRange3D(imIn)[1])
    m3D.logic3D(imOut, imWrk1, imWrk1, "inf")
    m3D.negate3D(imOut, imOut)
    m3D.logic3D(imOut, imWrk2, imOut, "inf")
    m3D.logic3D(imWrk1, imOut, imOut, "sup")
Example #6
0
def simpleLevelling3D(imIn, imMask, imOut, grid=m3D.DEFAULT_GRID3D):
    """
    Performs a simple levelling of 3D 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 = m3D.image3DMb(imIn)
    imWrk2 = m3D.image3DMb(imIn)
    mask_im = m3D.image3DMb(imIn, 1)
    m3D.logic3D(imIn, imMask, imWrk1, "inf")
    m3D.build3D(imIn, imWrk1, grid=grid)
    m3D.logic3D(imIn, imMask, imWrk2, "sup")
    m3D.dualBuild3D(imIn, imWrk2, grid=grid)
    m3D.generateSupMask3D(imIn, imMask, mask_im, False)
    m3D.convertByMask3D(mask_im, imOut, 0, m3D.computeMaxRange3D(imIn)[1])
    m3D.logic3D(imOut, imWrk1, imWrk1, "inf")
    m3D.negate3D(imOut, imOut)
    m3D.logic3D(imOut, imWrk2, imOut, "inf")
    m3D.logic3D(imWrk1, imOut, imOut, "sup")
def infClose3D(imIn, imOut, n, grid=m3D.DEFAULT_GRID3D):
    """
    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 = m3D.image3DMb(imIn)
    imWrk2 = m3D.image3DMb(imIn)
    imWrk1.fill(m3D.computeMaxRange3D(imIn)[1])
    # Default grid is a proxy for an actual grid
    if grid == m3D.CUBIC:
        # First neighbors located at a sqrt(2) distance from the center
        size = int((1.4142 * n + 1) / 2)
        for d in [2, 4, 10, 12, 14, 16]:
            linearClose3D(imIn, imWrk2, d, size, grid)
            m3D.logic3D(imWrk1, imWrk2, imWrk1, "inf")
        # First neighbors located at a sqrt(3) distance from the center
        size = int((1.7320 * n + 1) / 2)
        for d in [11, 13, 15, 17]:
            linearClose3D(imIn, imWrk2, d, size, grid)
            m3D.logic3D(imWrk1, imWrk2, imWrk1, "inf")
        # Finally neighbors located at a 1 distance from the center
        size = n
        for d in [1, 3, 9]:
            linearClose3D(imIn, imWrk2, d, size, grid)
            m3D.logic3D(imWrk1, imWrk2, imWrk1, "inf")
    elif grid == m3D.FACE_CENTER_CUBIC:
        for d in [1, 3, 5, 7, 8, 9]:
            linearClose3D(imIn, imWrk2, d, n, grid)
            m3D.logic3D(imWrk1, imWrk2, imWrk1, "inf")
    else:
        mamba.raiseExceptionOnError(core.MB_ERR_BAD_PARAMETER)
    m3D.copy3D(imWrk1, imOut)
Example #8
0
def infClose3D(imIn, imOut, n, grid=m3D.DEFAULT_GRID3D):
    """
    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 = m3D.image3DMb(imIn)
    imWrk2 = m3D.image3DMb(imIn)
    imWrk1.fill(m3D.computeMaxRange3D(imIn)[1])
    # Default grid is a proxy for an actual grid
    if grid == m3D.CUBIC:
        # First neighbors located at a sqrt(2) distance from the center
        size = int((1.4142 * n + 1) / 2)
        for d in [2, 4, 10, 12, 14, 16]:
            linearClose3D(imIn, imWrk2, d, size, grid)
            m3D.logic3D(imWrk1, imWrk2, imWrk1, "inf")
        # First neighbors located at a sqrt(3) distance from the center
        size = int((1.7320 * n + 1) / 2)
        for d in [11, 13, 15, 17]:
            linearClose3D(imIn, imWrk2, d, size, grid)
            m3D.logic3D(imWrk1, imWrk2, imWrk1, "inf")
        # Finally neighbors located at a 1 distance from the center
        size = n
        for d in [1, 3, 9]:
            linearClose3D(imIn, imWrk2, d, size, grid)
            m3D.logic3D(imWrk1, imWrk2, imWrk1, "inf")
    elif grid == m3D.FACE_CENTER_CUBIC:
        for d in [1, 3, 5, 7, 8, 9]:
            linearClose3D(imIn, imWrk2, d, n, grid)
            m3D.logic3D(imWrk1, imWrk2, imWrk1, "inf")
    else:
        mamba.raiseExceptionOnError(core.MB_ERR_BAD_PARAMETER)
    m3D.copy3D(imWrk1, imOut)
Example #9
0
def erode3D(imIn, imOut, n=1, se=CUBOCTAHEDRON1, edge=mamba.FILLED):
    """
    This operator performs an erosion, using the structuring element 'se' (set
    by default as CUBOCTAHEDRON1), of 3D image 'imIn' and puts the result in 
    'imOut'. The operation is repeated 'n' times (default is 1). This operator
    assumes a 'FILLED' edge by default.
    
    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.
    """
    
    (width,height,length) = imIn.getSize()
    depth = imIn.getDepth()
    if length!=len(imOut):
        mamba.raiseExceptionOnError(core.MB_ERR_BAD_SIZE)
    zext = se.grid.getZExtension()
    imWrk = m3D.image3DMb(width, height, length+zext*2, depth)
    if edge==mamba.EMPTY:
        for i in range(zext):
            imWrk[i].reset()
            imWrk[length+zext*2-1-i].reset()
    else:
        value = mamba.computeMaxRange(imIn[0])[1]
        for i in range(zext):
            imWrk[i].fill(value)
            imWrk[length+zext*2-1-i].fill(value)
    
    m3D.copy3D(imIn, imOut)
    
    dirs = se.getDirections(withoutZero=True)
    for size in range(n):
        m3D.copy3D(imOut, imWrk, 0, 1)
        if not se.hasZero():
            imOut.fill(m3D.computeMaxRange3D(imIn)[1])
        for i in range(length):
            dirs_enc = se.grid.getEncodedDirs(dirs,i)
            mamba.infNeighbor(imWrk[i], imOut[i], dirs_enc[-1], grid=se.grid.get2DGrid(), edge=edge)
            mamba.infNeighbor(imWrk[i+1], imOut[i], dirs_enc[0], grid=se.grid.get2DGrid(), edge=edge)
            mamba.infNeighbor(imWrk[i+2], imOut[i], dirs_enc[1], grid=se.grid.get2DGrid(), edge=edge)