def logic(imIn1, imIn2 , imOut, log): """ Performs a logic operation between the pixels of images 'imIn1' and 'imIn2' and put the result in 'imOut'. The logic operation to be performed is indicated through argument 'log'. The allowed logical operations in 'log' are: "and", "or", "xor", ""inf" or "sup". "and" performs a bitwise AND operation, "or" a bitwise OR and "xor" a bitwise XOR. "inf" calculates the minimum and "sup" the maximum between corresponding pixel values. 'imIn1', imIn2' and 'imOut' can be 1-bit, 8-bit or 32-bit images of same size and depth. """ if log=="and": err = core.MB_And(imIn1.mbIm, imIn2.mbIm,imOut.mbIm) elif log=="or": err = core.MB_Or(imIn1.mbIm, imIn2.mbIm,imOut.mbIm) elif log=="xor": err = core.MB_Xor(imIn1.mbIm, imIn2.mbIm,imOut.mbIm) elif log=="inf": err = core.MB_Inf(imIn1.mbIm, imIn2.mbIm,imOut.mbIm) elif log=="sup": err = core.MB_Sup(imIn1.mbIm, imIn2.mbIm,imOut.mbIm) mamba.raiseExceptionOnError(err) imOut.update()
def computeConnectivityNumber(imIn, grid=mamba.DEFAULT_GRID): """ Computes the connectivity number (Euler_Poincare constant) of image 'ImIn'. The result is an integer number. Beware, if the input image 'imIn' is not a binary image, the function raises an error. """ if imIn.getDepth() != 1: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DEPTH) imWrk = mamba.imageMb(imIn) if grid == mamba.HEXAGONAL: dse = mamba.doubleStructuringElement([1, 6], [0], mamba.HEXAGONAL) mamba.hitOrMiss(imIn, imWrk, dse) n = mamba.computeVolume(imWrk) dse = mamba.doubleStructuringElement([1], [0, 2], mamba.HEXAGONAL) mamba.hitOrMiss(imIn, imWrk, dse) n = n - mamba.computeVolume(imWrk) else: dse = mamba.doubleStructuringElement([3, 4, 5], [0], mamba.SQUARE) mamba.hitOrMiss(imIn, imWrk, dse) n = mamba.computeVolume(imWrk) dse = mamba.doubleStructuringElement([4], [0, 3, 5], mamba.SQUARE) mamba.hitOrMiss(imIn, imWrk, dse) n = n - mamba.computeVolume(imWrk) dse = mamba.doubleStructuringElement([3, 5], [0, 4], mamba.SQUARE) mamba.hitOrMiss(imIn, imWrk, dse) n = n + mamba.computeVolume(imWrk) return n
def compare3D(imIn1, imIn2, imOut): """ Compares the two 3D images 'imIn1' and 'imIn2'. The comparison is performed pixelwise by scanning the two images from top left to bottom right starting with plane 0 and it stops as soon as a pixel is different in the two images. The corresponding pixel in 'imOut' is set to the value of the pixel of 'imIn1'. The function returns a tuple holding the position of the first mismatching pixel. The tuple value is (-1,-1,-1) if the two images are identical. 'imOut' is not reset at the beginning of the comparison. 'imIn1', imIn2' and 'imOut' can be 1-bit, 8-bit or 32-bit images of same size and depth. """ outl = len(imOut) in1l = len(imIn1) in2l = len(imIn2) if in1l!=outl or in2l!=outl: mamba.raiseExceptionOnError(core.MB_ERR_BAD_SIZE) z = 0 x = -1 y = -1 while x<0 and z<outl: x,y = mamba.compare(imIn1[z], imIn2[z], imOut[z]) z += 1 if x<0: z = -1 else: z -= 1 return (x,y,z)
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)
def shift3D(imIn, imOut, d, amp, fill, grid=m3D.DEFAULT_GRID3D): """ Shifts 3D image 'imIn' in direction 'd' of the 'grid' over an amplitude of 'amp'. The emptied space is filled with 'fill' value. This implementation is fast as a minimal number of shifts is used. The result is put in 'imOut'. """ (width,height,length) = imIn.getSize() if length!=len(imOut): mamba.raiseExceptionOnError(core.MB_ERR_BAD_SIZE) # Computing limits according to the scanning direction. scan = grid.convertFromDir(d,0)[0] if scan == 0: startPlane, endPlane, scanDir = 0, length, 1 startFill, endFill = 0, 0 elif scan == -1: startPlane, endPlane, scanDir = amp, length, 1 startFill, endFill = max(length - amp, 0), length else: startPlane, endPlane, scanDir = length - amp - 1, -1, -1 startFill, endFill = 0, min(amp, length) # Performing the shift operations given by the getShiftDirList method. for i in range(startPlane, endPlane, scanDir): j = i + amp * scan dirList = grid.getShiftDirsList(d, amp, i) mamba.shift(imIn[i], imOut[j], dirList[0][0] , dirList[0][1], fill, grid=dirList[0][2]) if len(dirList) > 1: mamba.shift(imOut[j], imOut[j], dirList[1][0] , dirList[1][1], fill, grid=dirList[1][2]) # Filling the necessary planes. for i in range(startFill, endFill): imOut[i].fill(fill)
def computeDiameter(imIn, dir, scale=(1.0, 1.0), grid=mamba.DEFAULT_GRID): """ Computes the diameter (diametral variation) of binary image 'imIn' in direction 'dir'. 'scale' is a tuple defining the horizontal and vertical scale factors (default is 1.0). Beware, if the input image 'imIn' is not a binary image, the function raises an error. """ if imIn.getDepth() != 1: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DEPTH) if dir == 0: return 0.0 dir = ((dir - 1)%(mamba.gridNeighbors(grid)//2)) +1 imWrk = mamba.imageMb(imIn) mamba.copy(imIn, imWrk) mamba.diffNeighbor(imIn, imWrk, 1<<dir, grid=grid) if grid == mamba.HEXAGONAL: l = scale[1] if dir != 2: l = 2*l*scale[0]/math.sqrt(scale[0]*scale[0] + 4*scale[1]*scale[1]) else: if dir == 1: l = scale[0] elif dir == 3: l = scale[1] else: l = scale[0]*scale[1]/math.sqrt(scale[0]*scale[0] + scale[1]*scale[1]) l = l*mamba.computeVolume(imWrk) return l
def compare3D(imIn1, imIn2, imOut): """ Compares the two 3D images 'imIn1' and 'imIn2'. The comparison is performed pixelwise by scanning the two images from top left to bottom right starting with plane 0 and it stops as soon as a pixel is different in the two images. The corresponding pixel in 'imOut' is set to the value of the pixel of 'imIn1'. The function returns a tuple holding the position of the first mismatching pixel. The tuple value is (-1,-1,-1) if the two images are identical. 'imOut' is not reset at the beginning of the comparison. 'imIn1', imIn2' and 'imOut' can be 1-bit, 8-bit or 32-bit images of same size and depth. """ outl = len(imOut) in1l = len(imIn1) in2l = len(imIn2) if in1l != outl or in2l != outl: mamba.raiseExceptionOnError(core.MB_ERR_BAD_SIZE) z = 0 x = -1 y = -1 while x < 0 and z < outl: x, y = mamba.compare(imIn1[z], imIn2[z], imOut[z]) z += 1 if x < 0: z = -1 else: z -= 1 return (x, y, z)
def isotropicDistance(imIn, imOut, edge=mamba.FILLED): """ Computes the distance function of a set in 'imIn'. This distance function uses dodecagonal erosions and the grid is assumed to be hexagonal. The procedure is quite slow but the result is more aesthetic. This operator also illustrates how to perform successive dodecagonal operations of increasing sizes. """ if imIn.getDepth() != 1: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DEPTH) imOut.reset() oldn = 0 size = 0 imWrk1 = mamba.imageMb(imIn) imWrk2 = mamba.imageMb(imIn) mamba.copy(imIn, imWrk1) while mamba.computeVolume(imWrk1) != 0: mamba.add(imOut, imWrk1, imOut) size += 1 n = int(0.4641 * size) n += abs(n % 2 - size % 2) if (n - oldn) == 1: mamba.copy(imWrk1, imWrk2) mamba.erode(imWrk1, imWrk1, 1, se=mamba.HEXAGON, edge=edge) else: mamba.conjugateHexagonalErode(imWrk2, imWrk1, 1, edge=edge) oldn = n
def computeDiameter(imIn, dir, scale=(1.0, 1.0), grid=mamba.DEFAULT_GRID): """ Computes the diameter (diametral variation) of binary image 'imIn' in direction 'dir'. 'scale' is a tuple defining the horizontal and vertical scale factors (default is 1.0). Beware, if the input image 'imIn' is not a binary image, the function raises an error. """ if imIn.getDepth() != 1: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DEPTH) if dir == 0: return 0.0 dir = ((dir - 1) % (mamba.gridNeighbors(grid) // 2)) + 1 imWrk = mamba.imageMb(imIn) mamba.copy(imIn, imWrk) mamba.diffNeighbor(imIn, imWrk, 1 << dir, grid=grid) if grid == mamba.HEXAGONAL: l = scale[1] if dir != 2: l = 2 * l * scale[0] / math.sqrt(scale[0] * scale[0] + 4 * scale[1] * scale[1]) else: if dir == 1: l = scale[0] elif dir == 3: l = scale[1] else: l = scale[0] * scale[1] / math.sqrt(scale[0] * scale[0] + scale[1] * scale[1]) l = l * mamba.computeVolume(imWrk) return l
def computeConnectivityNumber(imIn, grid=mamba.DEFAULT_GRID): """ Computes the connectivity number (Euler_Poincare constant) of image 'ImIn'. The result is an integer number. Beware, if the input image 'imIn' is not a binary image, the function raises an error. """ if imIn.getDepth() != 1: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DEPTH) imWrk = mamba.imageMb(imIn) if grid == mamba.HEXAGONAL: dse = mamba.doubleStructuringElement([1,6],[0],mamba.HEXAGONAL) mamba.hitOrMiss(imIn, imWrk, dse) n = mamba.computeVolume(imWrk) dse = mamba.doubleStructuringElement([1],[0,2],mamba.HEXAGONAL) mamba.hitOrMiss(imIn, imWrk, dse) n = n - mamba.computeVolume(imWrk) else: dse = mamba.doubleStructuringElement([3,4,5],[0],mamba.SQUARE) mamba.hitOrMiss(imIn, imWrk, dse) n = mamba.computeVolume(imWrk) dse = mamba.doubleStructuringElement([4],[0,3,5],mamba.SQUARE) mamba.hitOrMiss(imIn, imWrk, dse) n = n - mamba.computeVolume(imWrk) dse = mamba.doubleStructuringElement([3,5],[0,4],mamba.SQUARE) mamba.hitOrMiss(imIn, imWrk, dse) n = n + mamba.computeVolume(imWrk) return n
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 computeRange(imIn): """ Computes the range, i.e. the minimum and maximum values, of image 'imIn'. The values are returned in a tuple holding the minimum and the maximum. """ err, min, max = core.MB_Range(imIn.mbIm) mamba.raiseExceptionOnError(err) return (min, max)
def getHistogram(imIn): """ Returns a list holding the histogram of the greyscale image 'imIn' (0 to 255). """ histo = 256*[0] err, histo = core.MB_Histo(imIn.mbIm,histo) mamba.raiseExceptionOnError(err) return histo
def getHistogram(imIn): """ Returns a list holding the histogram of the greyscale image 'imIn' (0 to 255). """ histo = 256 * [0] err, histo = core.MB_Histo(imIn.mbIm, histo) mamba.raiseExceptionOnError(err) return histo
def convertFromDir(self, direction, zindex): if direction > 26 or direction < 0: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DIRECTION) if direction < 9: return (0, direction) elif direction < 18: return (-1, direction - 9) else: return (1, direction - 18)
def getEncodedDirs(self, directions, zindex): dirs = {-1: 0, 0: 0, 1: 0} try: for d in directions: conv = self.listConvs[zindex % 2][d] dirs[conv[0]] |= (1 << (conv[1])) except IndexError: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DIRECTION) return dirs
def getEncodedDirs(self, directions, zindex): dirs = {-1:0,0:0,1:0} try: for d in directions: conv = self.listConvs[zindex%2][d] dirs[conv[0]] |= (1<<(conv[1])) except IndexError: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DIRECTION) return dirs
def convertFromDir(self, direction, zindex): if direction>26 or direction<0: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DIRECTION) if direction<9: return (0,direction) elif direction<18: return (-1,direction-9) else: return (1,direction-18)
def computeMaxRange(imIn): """ Returns a tuple with the minimum and maximum possible pixel values given the depth of image 'imIn'. The values are returned in a tuple holding the minimum and the maximum. """ err, min, max = core.MB_depthRange(imIn.mbIm) mamba.raiseExceptionOnError(err) return (min, max)
def copy(imIn, imOut): """ Copies 'imIn' image into 'imOut' image. 'imIn' and 'imOut' can be 1-bit, 8-bit or 32-bit images. The images must have the same depth and size. """ err = core.MB_Copy(imIn.mbIm, imOut.mbIm) mamba.raiseExceptionOnError(err) imOut.update()
def computeVolume(imIn): """ Computes the volume of the image 'imIn', i.e. the sum of its pixel values. The computed integer value is returned by the function. 'imIn' can be a 1-bit, 8-bit or 32-bit image. """ err, volume = core.MB_Volume(imIn.mbIm) mamba.raiseExceptionOnError(err) return volume
def negate(imIn, imOut): """ Negates the image 'imIn' and puts the result in 'imOut'. The operation is a binary complement for binary images and a negation for greyscale and 32-bit images. """ err = core.MB_Inv(imIn.mbIm, imOut.mbIm) mamba.raiseExceptionOnError(err) imOut.update()
def PIL2Mamba(pilim, imOut): """ The PIL/PILLOW image 'pilim' is used to load the Mamba image 'imOut'. """ depth = imOut.getDepth() (width, height) = imOut.getSize() next_mbIm = utils.loadFromPILFormat(pilim, size=(width,height)) err = core.MB_Convert(next_mbIm, imOut.mbIm) mamba.raiseExceptionOnError(err) imOut.update()
def checkEmptiness(imIn): """ Checks if image 'imIn' is empty (i.e. completely black). Returns True if so, False otherwise. 'imIn' can be a 1-bit, 8-bit or 32-bit image. """ err, isEmpty = core.MB_Check(imIn.mbIm) mamba.raiseExceptionOnError(err) return bool(isEmpty)
def setPixel(self, value, position): """ Sets the pixel at 'position' with 'value'. 'position' is a tuple holding (x,y,z). """ (x,y,z) = position if z<0 or z>=self.length: mamba.raiseExceptionOnError(core.MB_ERR_BAD_SIZE) err = core.MB_PutPixel(self.seq[z].mbIm, value, position[0], position[1]) mamba.raiseExceptionOnError(err)
def copyLine(imIn, nIn, imOut, nOut): """ Copies the line numbered 'nIn' of image 'imIn' into 'imOut' at line index 'nOut'. 'imIn' and 'imOut' can be 1-bit, 8-bit or 32-bit images. The images must have the same depth and size. """ err = core.MB_CopyLine(imIn.mbIm, imOut.mbIm, nIn, nOut) mamba.raiseExceptionOnError(err) imOut.update()
def extractRaw(self): """ Extracts and returns the image raw string data. This method only works on 8 and 32-bit images. """ data = b"" for im in self.seq: err,s = core.MB_Extract(im.mbIm) mamba.raiseExceptionOnError(err) data += s return data
def convertByMask(imIn, imOut, mFalse, mTrue): """ Converts a binary image 'imIn' into a greyscale image (8-bit) or a 32-bit image and puts the result in 'imOut'. white pixels of 'imIn' are set to value 'mTrue' in the output image and the black pixels set to value 'mFalse'. """ err = core.MB_Mask(imIn.mbIm, imOut.mbIm, mFalse, mTrue) mamba.raiseExceptionOnError(err) imOut.update()
def lookup(imIn, imOut, lutable): """ Converts the greyscale image 'imIn' using the look-up table 'lutable' and puts the result in greyscale image 'imOut'. 'lutable' is a list containing 256 values with the first one corresponding to 0 and the last one to 255. """ err = core.MB_Lookup(imIn.mbIm,imOut.mbIm,lutable) mamba.raiseExceptionOnError(err) imOut.update()
def extractFrame(imIn, threshold): """ Extracts the smallest frame (tuple containing the coordinates of the upper left point and the lower right point) inside the image 'imIn' that includes all the pixels whose value is greater or equal to 'threshold'. 'imIn' can be a 8-bit or 32-bit image. """ err, x1, y1, x2, y2 = core.MB_Frame(imIn.mbIm, threshold) mamba.raiseExceptionOnError(err) return (x1, y1, x2, y2)
def getEncodedDirs(self, directions, zindex): dirs = {-1: 0, 0: 0, 1: 0} for d in directions: if d > 26 or d < 0: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DIRECTION) if d < 9: dirs[0] |= (1 << d) elif d < 18: dirs[-1] |= (1 << (d - 9)) else: dirs[1] |= (1 << (d - 18)) return dirs
def getPixel(self, position): """ Gets the pixel value at 'position'. 'position' is a tuple holding (x,y,z). Returns the value of the pixel. """ (x,y,z) = position if z<0 or z>=self.length: mamba.raiseExceptionOnError(core.MB_ERR_BAD_SIZE) err, value = core.MB_GetPixel(self.seq[z].mbIm, x, y) mamba.raiseExceptionOnError(err) return value
def generateSupMask(imIn1, imIn2, imOut, strict): """ Generates a binary mask image in 'imOut' where pixels are set to 1 when they are greater (strictly if 'strict' is set to True, greater or equal otherwise) in image 'imIn1' than in image 'imIn2'. 'imIn1' and imIn2' can be 1-bit, 8-bit or 32-bit images of same size and depth. """ err = core.MB_SupMask(imIn1.mbIm, imIn2.mbIm,imOut.mbIm, int(strict)) mamba.raiseExceptionOnError(err) imOut.update()
def getEncodedDirs(self, directions, zindex): dirs = {-1:0,0:0,1:0} for d in directions: if d>26 or d<0: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DIRECTION) if d<9: dirs[0] |= (1<<d) elif d<18: dirs[-1] |= (1<<(d-9)) else: dirs[1] |= (1<<(d-18)) return dirs
def computeDistance3D(imIn, imOut, grid=m3D.DEFAULT_GRID3D, edge=mamba.EMPTY): """ Computes for each white pixel of binary 3D 'imIn' the minimum distance to reach a connected component boundary while constantly staying in the set. The result is put in 32-bit 'imOut'. The distance computation will be performed according to the 'grid' (CUBIC is 26-Neighbors and FACE_CENTER_CUBIC is 12-Neighbors, CENTER_CUBIC is unsupported by this operator). 'edge' can be FILLED or EMPTY. """ err = core.MB3D_Distanceb(imIn.mb3DIm, imOut.mb3DIm, grid.getCValue(), edge.id) mamba.raiseExceptionOnError(err)
def _dualBuild3D_1(imMask, imInout, grid): # Build function for binary 3D images if imMask.getDepth()!=1: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DEPTH) imMask_8 = m3D.image3DMb(imMask, 8) imInout_8= m3D.image3DMb(imInout, 8) m3D.convert3D(imMask, imMask_8) m3D.convert3D(imInout, imInout_8) err = core.MB3D_HierarDualBld(imMask_8.mb3DIm, imInout_8.mb3DIm, grid.getCValue()) mamba.raiseExceptionOnError(err) m3D.convert3D(imMask_8, imMask) m3D.convert3D(imInout_8, imInout)
def shiftVector(imIn, imOut, vector, fill): """ Shifts image 'imIn' by 'vector' (tuple with dx,dy). The emptied space is filled with 'fill' value. The result is put in 'imOut'. 'imIn' and 'imOut' can be 1-bit, 8-bit or 32-bit images of same size and depth. """ err = core.MB_ShiftVector(imIn.mbIm, imOut.mbIm, vector[0], vector[1], fill) mamba.raiseExceptionOnError(err) imOut.update()
def getShiftDirsList(self, d, amp, zindex): if d < 0 or d > 12: mamba.raiseExceptionOnError(core.MB_ERR_BAD_DIRECTION) elif d < 7: dirList = [(d, amp, mamba.HEXAGONAL)] elif d < 9: extraS = (((0, 0, 0), (1, 0, 0), (1, 0, 1)), ((0, 0, 0), (0, 1, 0), (1, 1, 0)), ((0, 0, 0), (0, 0, 1), (0, 1, 1))) hdList = [self.convertFromDir(d, i)[1] for i in range(3)] usedDir = [0, 1, 2] del usedDir[hdList.index(0)] amph = amp // 3 + extraS[zindex % 3][amp % 3][usedDir[0]] dirList = [(hdList[usedDir[0]], amph, mamba.HEXAGONAL)] amph = amp // 3 + extraS[zindex % 3][amp % 3][usedDir[1]] dirList.append((hdList[usedDir[1]], amph, mamba.HEXAGONAL)) elif d == 9: extraS = (((0, 0), (0, 1), (1, 0)), ((0, 0), (0, 0), (0, 1)), ((0, 0), (0, 1), (0, 1))) (sc, sh) = extraS[zindex % 3][amp % 3] nc = (amp // 3 + sc) * 2 dirList = [(1, nc, mamba.SQUARE)] if sh != 0: if (zindex % 3) == 2: hd = 1 else: hd = 6 dirList.append((hd, 1, mamba.HEXAGONAL)) elif d < 12: extraS = (((0, 0, 0), (1, 0, 0), (1, 1, 0)), ((0, 0, 0), (0, 1, 0), (0, 1, 1)), ((0, 0, 0), (0, 0, 1), (1, 0, 1))) hdList = [self.convertFromDir(d, i)[1] for i in range(3)] usedDir = [0, 1, 2] del usedDir[hdList.index(0)] amph = amp // 3 + extraS[zindex % 3][amp % 3][usedDir[0]] dirList = [(hdList[usedDir[0]], amph, mamba.HEXAGONAL)] amph = amp // 3 + extraS[zindex % 3][amp % 3][usedDir[1]] dirList.append((hdList[usedDir[1]], amph, mamba.HEXAGONAL)) elif d == 12: extraS = (((0, 0), (0, 0), (0, 1)), ((0, 0), (0, 1), (1, 0)), ((0, 0), (0, 1), (0, 1))) (sc, sh) = extraS[zindex % 3][amp % 3] nc = (amp // 3 + sc) * 2 dirList = [(5, nc, mamba.SQUARE)] if sh != 0: if (zindex % 3) == 2: hd = 3 else: hd = 4 dirList.append((hd, 1, mamba.HEXAGONAL)) return dirList
def copyBytePlane(imIn, plane, imOut): """ Inserts or extracts a byte plane. If 'imIn' is a greyscale image, it is inserted at 'plane' position in 32-bit 'imOut'. If 'imIn' is a 32-bit image, its byte plane at 'plane' position is extracted and put into 'imOut'. Plane values are from 0 (LSByte) to 3 (MSByte). """ err = core.MB_CopyBytePlane(imIn.mbIm,imOut.mbIm, plane) mamba.raiseExceptionOnError(err) imOut.update()
def shift(imIn, imOut, d, amp, fill, grid=mamba.DEFAULT_GRID): """ Shifts image 'imIn' in direction 'd' of the 'grid' over an amplitude of 'amp'. The emptied space is filled with 'fill' value. The result is put in 'imOut'. 'grid' value can be HEXAGONAL or SQUARE and is set to DEFAULT_GRID by default. 'imIn' and 'imOut' can be 1-bit, 8-bit or 32-bit images of same size and depth. """ err = core.MB_Shift(imIn.mbIm, imOut.mbIm, d, amp, fill, grid.id) mamba.raiseExceptionOnError(err) imOut.update()
def copyBytePlane(imIn, plane, imOut): """ Inserts or extracts a byte plane. If 'imIn' is a greyscale image, it is inserted at 'plane' position in 32-bit 'imOut'. If 'imIn' is a 32-bit image, its byte plane at 'plane' position is extracted and put into 'imOut'. Plane values are from 0 (LSByte) to 3 (MSByte). """ err = core.MB_CopyBytePlane(imIn.mbIm, imOut.mbIm, plane) mamba.raiseExceptionOnError(err) imOut.update()
def mulConst(imIn, v, imOut): """ Multiplies 'imIn' pixel values with value 'v' and puts the result in 'imOut'. The operation can be sum up in the following formula: imOut = imIn * v The operation is saturated for greyscale images. You cannot use it with binary images. """ err = core.MB_ConMul(imIn.mbIm,v,imOut.mbIm) mamba.raiseExceptionOnError(err) imOut.update()
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 dualbuildNeighbor(imMask, imInout, d, grid=mamba.DEFAULT_GRID): """ Dual builds image 'imInout' in direction 'd' according to 'grid' using 'imMask' as a mask (the propagation is performed only in 'd' direction). The function also returns the volume of the image 'imInout' after the build operation. 'grid' value can be HEXAGONAL or SQUARE. """ err,volume = core.MB_DualBldNb(imMask.mbIm,imInout.mbIm,d, grid.id) mamba.raiseExceptionOnError(err) imInout.update() return volume