def mosaicGradient3D(imIn, imOut, grid=m3D.DEFAULT_GRID3D): """ Builds the mosaic-gradient 3D 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 = m3D.image3DMb(imIn) imWrk2 = m3D.image3DMb(imIn) imWrk3 = m3D.image3DMb(imIn) imWrk4 = m3D.image3DMb(imIn) imWrk5 = m3D.image3DMb(imIn) mosaic3D(imIn, imWrk2, imWrk3, grid=grid) m3D.sub3D(imWrk2, imWrk3, imWrk1) m3D.logic3D(imWrk2, imWrk3, imWrk2, "sup") m3D.negate3D(imWrk2, imWrk2) se = m3D.structuringElement3D(m3D.getDirections3D(grid), grid) while m3D.computeVolume3D(imWrk3) != 0: m3D.dilate3D(imWrk1, imWrk4, 2, se=se) m3D.dilate3D(imWrk2, imWrk5, 2, se=se) m3D.logic3D(imWrk4, imWrk3, imWrk4, "inf") m3D.logic3D(imWrk5, imWrk3, imWrk5, "inf") m3D.logic3D(imWrk1, imWrk4, imWrk1, "sup") m3D.logic3D(imWrk2, imWrk5, imWrk2, "sup") m3D.erode3D(imWrk3, imWrk3, 2, se=se) m3D.negate3D(imWrk2, imWrk2) m3D.sub3D(imWrk1, imWrk2, imOut)
def hitOrMiss3D(imIn, imOut, dse, edge=mamba.EMPTY): """ Performs a binary Hit-or-miss operation on 3D image 'imIn' using the doubleStructuringElement3D 'dse'. Result is put in 'imOut'. WARNING! 'imIn' and 'imOut' must be different images. """ (width, height, length) = imIn.getSize() depth = imIn.getDepth() if depth != 1: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DEPTH) if length != len(imOut): mamba.raiseExceptionOnError(core.MB_ERR_BAD_SIZE) zext = dse.grid.getZExtension() imWrk = m3D.image3DMb(width, height, length + zext * 2, depth) # Border handling imWrk.reset() m3D.copy3D(imIn, imWrk, firstPlaneOut=1) if edge == mamba.FILLED: m3D.negate3D(imWrk, imWrk) for i in range(zext): imWrk[i].reset() imWrk[length + zext * 2 - 1 - i].reset() dse = dse.flip() # Central point if dse.se1.hasZero(): m3D.copy3D(imWrk, imOut, firstPlaneIn=1) else: if dse.se0.hasZero(): for i in range(length): mamba.negate(imWrk[i + 1], imOut[i]) else: imOut.fill(1) # Other directions dirs = m3D.getDirections3D(dse.getGrid(), True) dirs0 = dse.se0.getDirections() dirs1 = dse.se1.getDirections() grid2D = dse.getGrid().get2DGrid() for d in dirs: if d in dirs1: for i in range(length): (planeOffset, dc) = dse.getGrid().convertFromDir(d, i) mamba.infNeighbor(imWrk[i + 1 + planeOffset], imOut[i], 1 << dc, grid=grid2D, edge=edge) elif d in dirs0: for i in range(length): (planeOffset, dc) = dse.getGrid().convertFromDir(d, i) mamba.diffNeighbor(imWrk[i + 1 + planeOffset], imOut[i], 1 << dc, grid=grid2D, edge=edge)
def hitOrMiss3D(imIn, imOut, dse, edge=mamba.EMPTY): """ Performs a binary Hit-or-miss operation on 3D image 'imIn' using the doubleStructuringElement3D 'dse'. Result is put in 'imOut'. WARNING! 'imIn' and 'imOut' must be different images. """ (width,height,length) = imIn.getSize() depth = imIn.getDepth() if depth!=1: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DEPTH) if length!=len(imOut): mamba.raiseExceptionOnError(core.MB_ERR_BAD_SIZE) zext = dse.grid.getZExtension() imWrk = m3D.image3DMb(width, height, length+zext*2, depth) # Border handling imWrk.reset() m3D.copy3D(imIn, imWrk, firstPlaneOut=1) if edge==mamba.FILLED: m3D.negate3D(imWrk, imWrk) for i in range(zext): imWrk[i].reset() imWrk[length+zext*2-1-i].reset() dse = dse.flip() # Central point if dse.se1.hasZero(): m3D.copy3D(imWrk, imOut, firstPlaneIn=1) else: if dse.se0.hasZero(): for i in range(length): mamba.negate(imWrk[i+1], imOut[i]) else: imOut.fill(1) # Other directions dirs = m3D.getDirections3D(dse.getGrid(), True) dirs0 = dse.se0.getDirections() dirs1 = dse.se1.getDirections() grid2D = dse.getGrid().get2DGrid() for d in dirs: if d in dirs1: for i in range(length): (planeOffset, dc) = dse.getGrid().convertFromDir(d,i) mamba.infNeighbor(imWrk[i+1+planeOffset], imOut[i], 1<<dc, grid=grid2D, edge=edge) elif d in dirs0: for i in range(length): (planeOffset, dc) = dse.getGrid().convertFromDir(d,i) mamba.diffNeighbor(imWrk[i+1+planeOffset], imOut[i], 1<<dc, grid=grid2D, edge=edge)
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 closeHoles3D(imIn, imOut, grid=m3D.DEFAULT_GRID3D): """ Close holes in 3D image 'imIn' and puts the result in 'imOut'. This operator works on binary and greytone images. In this case, however, it should be used cautiously. """ imWrk = m3D.image3DMb(imIn) m3D.negate3D(imIn, imIn) m3D.drawEdge3D(imWrk) m3D.logic3D(imIn, imWrk, imWrk, "inf") build3D(imIn, imWrk, grid=grid) m3D.negate3D(imIn, imIn) m3D.negate3D(imWrk, imOut)