def __init__(self, *args): """ Double structuring element constructor. A double structuring element is defined by the first (background points) and second (foreground points) structuring elements. You can define it in two ways: * doubleStructuringElement(se0, se1): where 'se0' and 'se1' are instances of the class structuring element found in erodil module. These structuring elements must be defined on the same grid. * doubleStructuringElement(dse0, dse1, grid): where 'dse0' and 'dse1' are direction lists and 'grid' defines the grid on which the two structuring elements are defined. If the constructor is called with inapropriate arguments, it raises a ValueError exception. """ if len(args)==2: if args[0].getGrid()!=args[1].getGrid(): raise ValueError("Grid value mismatch") self.se0 = args[0] self.se1 = args[1] self.grid = self.se0.getGrid() elif len(args)==3: self.se0 = mamba.structuringElement(args[0], args[2]) self.se1 = mamba.structuringElement(args[1], args[2]) self.grid = args[2] else: raise ValueError("Incorrect constructor call")
def __init__(self, *args): """ Double structuring element constructor. A double structuring element is defined by the first (background points) and second (foreground points) structuring elements. You can define it in two ways: * doubleStructuringElement(se0, se1): where 'se0' and 'se1' are instances of the class structuring element found in erodil module. These structuring elements must be defined on the same grid. * doubleStructuringElement(dse0, dse1, grid): where 'dse0' and 'dse1' are direction lists and 'grid' defines the grid on which the two structuring elements are defined. If the constructor is called with inapropriate arguments, it raises a ValueError exception. """ if len(args) == 2: if args[0].getGrid() != args[1].getGrid(): raise ValueError("Grid value mismatch") self.se0 = args[0] self.se1 = args[1] self.grid = self.se0.getGrid() elif len(args) == 3: self.se0 = mamba.structuringElement(args[0], args[2]) self.se1 = mamba.structuringElement(args[1], args[2]) self.grid = args[2] else: raise ValueError("Incorrect constructor call")
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)
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)
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")
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")
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)
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)
def drawEdge(imOut, thick=1): """ Draws a frame around the edge of 'imOut' whose value equals the maximum range value and whose thickness is given by 'thick' (default 1). """ imOut.reset() se=mamba.structuringElement([0,1,2,3,4,5,6,7,8], mamba.SQUARE) mamba.dilate(imOut, imOut, thick, se=se, edge=mamba.FILLED)
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)
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)
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)
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)
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)
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)
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")
def tlaferm((name, thresh, outpath)): # =============== Load numpy file and create contours then save png ========= # threshold=25 # print 'name= ',name zr = np.load(name) im = Image.fromarray(zr.T) # xpixels, ypixels = im.size[1], im.size[0] dpi, scalefactor = 72, 1 xinch = xpixels * scalefactor / dpi yinch = ypixels * scalefactor / dpi # fig = plt.figure(figsize=(xinch, yinch)) ax = plt.axes([0, 0, 1, 1], frame_on=False, xticks=[], yticks=[]) imc = plt.contourf(zr, [0, thresh], colors='black', origin='image') ## imfile = 'image_' + os.path.basename(name) + '.png' impath = os.path.dirname(name) plt.savefig(os.path.join(outpath, imfile), dpi=dpi) plt.close('all') # # =================== load png and use mamba then save ====================================== im = mamba.imageMb(os.path.join(outpath, imfile)) im1, im2, im3, im4 = mamba.imageMb(im), mamba.imageMb(im), mamba.imageMb( im), mamba.imageMb(im) se = mamba.structuringElement([0, 1, 2, 3, 4, 5, 6], grid=mamba.HEXAGONAL) mamba.closeHoles(im, im) mamba.negate(im, im) mamba.closeHoles(im, im) mamba.negate(im, im) # #mamba.opening(im, im1, n=2, se=se) ma_file = 'mamba_' + imfile + '.png' im.save(os.path.join(outpath, ma_file))
def tlaferm((name,thresh,outpath)): # =============== Load numpy file and create contours then save png ========= # threshold=25 # print 'name= ',name zr=np.load(name) im=Image.fromarray(zr.T) # xpixels,ypixels = im.size[1],im.size[0] dpi,scalefactor = 72,1 xinch = xpixels * scalefactor / dpi yinch = ypixels * scalefactor / dpi # fig = plt.figure(figsize=(xinch,yinch)) ax = plt.axes([0, 0, 1, 1], frame_on=False, xticks=[], yticks=[]) imc=plt.contourf(zr, [0,thresh], colors='black', origin='image') ## imfile='image_'+os.path.basename(name)+'.png' impath=os.path.dirname(name) plt.savefig(os.path.join(outpath,imfile), dpi=dpi) plt.close('all') # # =================== load png and use mamba then save ====================================== im = mamba.imageMb(os.path.join(outpath,imfile)) im1,im2,im3,im4=mamba.imageMb(im),mamba.imageMb(im),mamba.imageMb(im),mamba.imageMb(im) se = mamba.structuringElement([0,1,2,3,4,5,6],grid=mamba.HEXAGONAL) mamba.closeHoles(im, im) mamba.negate(im, im) mamba.closeHoles(im, im) mamba.negate(im, im) # #mamba.opening(im, im1, n=2, se=se) ma_file='mamba_'+imfile+'.png' im.save(os.path.join(outpath,ma_file))
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)
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)
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)