def filterBankPatch(img, width=5): """ Returns the raw pixel value of a square block of pixels (a patch) centered each pixel. """ half = width / 2 # e.g. for 5, it's 2 imgE = Views.extendBorder(img) ops = [offset(imgE, [x, y]) for x in xrange(-half, half + 1) for y in xrange(-half, half + 1)] return ops
def translate_single_stack_using_imglib2(imp, dx, dy, dz): # wrap into a float imglib2 and translate # conversion into float is necessary due to "overflow of n-linear interpolation due to accuracy limits of unsigned bytes" # see: https://github.com/fiji/fiji/issues/136#issuecomment-173831951 img = ImagePlusImgs.from(imp.duplicate()) extended = Views.extendBorder(img) converted = Converters.convert(extended, RealFloatSamplerConverter()) interpolant = Views.interpolate(converted, NLinearInterpolatorFactory()) # translate if imp.getNDimensions()==3: transformed = RealViews.affine(interpolant, Translation3D(dx, dy, dz)) elif imp.getNDimensions()==2: transformed = RealViews.affine(interpolant, Translation2D(dx, dy)) else: IJ.log("Can only work on 2D or 3D stacks") return None cropped = Views.interval(transformed, img) # wrap back into bit depth of input image and return bd = imp.getBitDepth() if bd==8: return(ImageJFunctions.wrapUnsignedByte(cropped,"imglib2")) elif bd == 16: return(ImageJFunctions.wrapUnsignedShort(cropped,"imglib2")) elif bd == 32: return(ImageJFunctions.wrapFloat(cropped,"imglib2")) else: return None
def readPatch(img, width=5): half = width / 2 # e.g. for 5, it's 2 imgE = Views.extendBorder(img) ops = [ offset(imgE, [x, y]) for x in xrange(-half, half + 1) for y in xrange(-half, half + 1) ] return ops
def filterBankEdges(img): """ Return all 4 edge detectors (left, right, top, bottom) as 3x3 convolution kernels. """ imgE = Views.extendBorder(img) opTop = as2DKernel(imgE, [-1]*3 + [0]*3 + [1]*3) opBottom = as2DKernel(imgE, [1]*3 + [0]*3 + [-1]*3) opLeft = as2DKernel(imgE, [-1, 0, 1] * 3) opRight = as2DKernel(imgE, [1, 0, -1] * 3) return [opTop, opBottom, opLeft, opRight]
def filterBankBlockStatistics(img, block_width=5, block_height=5, integralImgE=None, sumType=UnsignedLongType(), converter=Util.genericRealTypeConverter()): # corners of a block centered at the pixel block_width = int(block_width) block_height = int(block_height) w0 = -block_width/2 # e.g. -2 when block_width == 4 and also when block_width == 5 h0 = -block_height/2 decX = 1 if 0 == block_width % 2 else 0 decY = 1 if 0 == block_height % 2 else 0 w1 = block_width/2 - decX # e.g. 2 when block_width == 5 but 1 when block_width == 4 h1 = block_height/2 - decY corners = [[w0, h0], [w1, h0], [w0, h1], [w1, h1]] # Create the integral image, stored as 64-bit if not integralImgE: alg = IntegralImg(img, sumType, converter) alg.process() integralImgE = Views.extendBorder(alg.getResult()) # Create the integral image of squares, stored as 64-bit sqimg = compute(power(img, 2)).view(sumType) algSq = IntegralImg(sqimg, sumType, converter) algSq.process() integralImgSqE = Views.extendBorder(algSq.getResult()) # block mean: creates holes in blurred membranes opMean = div(block(integralImgSqE, corners), block_width * block_height) # block variance: sum of squares minus square of sum opVariance = sub(block(integralImgSqE, corners), power(block(integralImgE, corners), 2)) opVarianceNonZero = let("var", opVariance, IF(LT("var", 0), THEN(0), ELSE("var"))) return [opMean, opVarianceNonZero]
def pyramidAreaAveraging(img, top_level, min_width=32, sumType=UnsignedLongType, mathType=UnsignedLongType, converter=Util.genericIntegerTypeConverter()): """ Return a list of image views, one per scale level of the image pyramid, except for level zero (the first image) which is the provided img. All images are of the same type as the source img. Based on an integral image for fast computation. """ img_type = img.randomAccess().get().createVariable() # Create an integral image in longs alg = IntegralImg(img, sumType(), converter) alg.process() integralImg = alg.getResult() # Create an image pyramid as views, with ImgMath and imglib2, # which amounts to scale area averaging sped up by the integral image # and generated on demand whenever each pyramid level is read. width = img.dimension(0) imgE = Views.extendBorder(integralImg) blockSide = 1 level_index = 1 # Corners for level 1: a box of 2x2 corners = [[0, 0], [1, 0], [0, 1], [1, 1]] pyramid = [img] while width > min_width and level_index <= top_level: blockSide *= 2 width /= 2 # Scale the corner coordinates to make the block larger cs = [[c * blockSide for c in corner] for corner in corners] blockRead = div(block(imgE, cs), pow(blockSide, 2)) # the op # a RandomAccessibleInterval view of the op, computed with shorts but seen as bytes view = blockRead.view(mathType(), img_type.createVariable()) # Views.subsample by 2 will turn a 512-pixel width to a 257 width, # so crop to proper interval 256 level = Views.interval(Views.subsample(view, blockSide), [0] * img.numDimensions(), # min [img.dimension(d) / blockSide -1 for d in xrange(img.numDimensions())]) # max pyramid.append(level) level_index += 1 # for next iteration return pyramid
def translate_using_imglib2(imp, dx, dy, dz): print "imp channels",imp.getNChannels() # todo: # if multiple channels use Duplicator to translate each channel individually ## wrap # http://javadoc.imagej.net/ImgLib2/net/imglib2/img/imageplus/ImagePlusImg.html img = ImagePlusImgs.from(imp.duplicate()) print "dimensions:",img.numDimensions() print img.getChannels() ## prepare image print "img",img ddd extended = Views.extendBorder(img) #print "extended",extended #print "extended",extended.dimension(1) dims = zeros(4, 'l') img.dimensions(dims) print "dims",dims converted = Converters.convert(extended, RealFloatSamplerConverter()) composite = Views.collapseReal(converted, imp.getNChannels()) print "composite",composite interpolant = Views.interpolate(composite, NLinearInterpolatorFactory()) #print "interpolant",interpolant transformed = RealViews.affine(interpolant, Translation3D(dx, dy, dz)) print "transformed", transformed cropped = Views.interval(transformed, img) print "cropped.numDimensions()", cropped.numDimensions() print "cropped",cropped ## wrap back and return bd = imp.getBitDepth() # maybe simply wrap works? if bd==8: return(ImageJFunctions.wrapUnsignedByte(cropped,"imglib2")) elif bd == 16: return(ImageJFunctions.wrapUnsignedShort(cropped,"imglib2")) elif bd == 32: return(ImageJFunctions.wrapFloat(cropped,"imglib2")) else: return None
imp = IJ.getImage() # e.g. EM of Drosophila neurons 180-220-sub512x512-30.tif #imp = IJ.openImage("/home/albert/lab/TEM/abd/microvolumes/Seg/180-220-sub/180-220-sub512x512-30.tif") img = compute(IL.wrap(imp)).intoImg(UnsignedShortType()) # in 16-bit # Create an integral image in longs alg = IntegralImg(img, UnsignedLongType(), Util.genericIntegerTypeConverter()) alg.process() integralImg = alg.getResult() # Create an image pyramid as views, with ImgMath and imglib2, # which amounts to scale area averaging sped up by the integral image # and generated on demand whenever each pyramid level is read. width = img.dimension(0) min_width = 32 imgE = Views.extendBorder(integralImg) blockSide = 1 # Corners for level 1: a box of 2x2 corners = [[0, 0], [1, 0], [0, 1], [1, 1]] pyramid = [] # level 0 is the image itself, not added while width > min_width: blockSide *= 2 width /= 2 # Scale the corner coordinates to make the block larger cs = [[c * blockSide for c in corner] for corner in corners] blockRead = div(block(imgE, cs), pow(blockSide, 2)) # the op # a RandomAccessibleInterval view of the op, computed with shorts but seen as bytes view = blockRead.view(UnsignedShortType(), UnsignedByteType()) # Views.subsample by 2 will turn a 512-pixel width to a 257 width, # so crop to proper interval 256
imp = IJ.getImage() # an 8-bit image, e.g. blobs sample image img = IL.wrap(imp) # A converter from 8-bit (unsigned byte) to 64-bit (unsigned long) int_converter = Util.genericIntegerTypeConverter() # Create the integral image of an 8-bit input, stored as 64-bit alg = IntegralImg(img, UnsignedLongType(), int_converter) alg.process() integralImg = alg.getResult() # Read out blocks of radius 5 (i.e. 10x10 for a 2d image) # in a way that is entirely n-dimensional (applies to 1d, 2d, 3d, 4d ...) radius = 5 nd = img.numDimensions() op = div(block(Views.extendBorder(integralImg), [radius] * nd), pow(radius * 2, nd)) blurred = img.factory().create(img) # an 8-bit image # Compute in floats, store result into longs # using a default generic RealType converter via t.setReal(t.getRealDouble()) compute(op).into(blurred, None, FloatType(), None) # Show the blurred image with the same LUT as the original imp2 = IL.wrap(blurred, "integral image radius 5 blur") imp2.getProcessor().setLut(imp.getProcessor().getLut()) imp2.show() # Compare with Gaussian blur from ij import ImagePlus from ij.plugin.filter import GaussianBlur from ij.gui import Line, ProfilePlot
def filterBank(img, bs=4, bl=8, sumType=UnsignedLongType(), converter=Util.genericRealTypeConverter()): """ Haar-like features from Viola and Jones using integral images tuned to identify neuron membranes in electron microscopy. bs: length of the short side of a block bl: length of the long side of a block sumType: the type with which to add up pixel values in the integral image converter: for the IntegralImg, to convert from input to sumType """ # Create the integral image, stored as 64-bit alg = IntegralImg(img, sumType, converter) alg.process() integralImg = alg.getResult() imgE = Views.extendBorder(integralImg) # corners of a 4x8 or 8x4 rectangular block where 0,0 is the top left cornersV = [[0, 0], [bs -1, 0], # Vertical [0, bl -1], [bs -1, bl - 1]] cornersH = [[0, 0], [bl -1, 0], # Horizontal [0, bs -1], [bl -1, bs - 1]] # Two adjacent vertical rectangles 4x8 - 4x8 centered on the pixel blockVL = block(imgE, shift(cornersV, -bs, -bl/2)) blockVR = block(imgE, shift(cornersV, 0, -bl/2)) op1 = let("VL", blockVL, "VR", blockVR, IF(GT("VL", "VR"), THEN(div("VR", "VL")), ELSE(div("VL", "VR")))) #op1 = sub(blockVL, blockVR) #op2 = sub(blockVR, blockVL) # Two adjacent horizontal rectangles 8x4 - 8x4 centered on the pixel blockHT = block(imgE, shift(cornersH, -bs, -bl/2)) blockHB = block(imgE, shift(cornersH, -bs, 0)) op3 = let("HT", blockHT, "HB", blockHB, IF(GT("HT", "HB"), THEN(div("HB", "HT")), # div works better than sub ELSE(div("HT", "HB")))) #op3 = sub(blockHT, blockHB) #op4 = sub(blockHB, blockHT) # Two bright-black-bright vertical features 4x8 - 4x8 - 4x8 block3VL = block(imgE, shift(cornersV, -bs -bs/2, -bl/2)) block3VC = block(imgE, shift(cornersV, -bs/2, -bl/2)) block3VR = block(imgE, shift(cornersV, bs/2, -bl/2)) op5 = let("3VL", block3VL, "3VC", block3VC, "3VR", block3VR, IF(AND(GT("3VL", "3VC"), GT("3VR", "3VC")), THEN(sub(add("3VL", "3VR"), "3VC")), # like Viola and Jones 2001 ELSE(div(add("3VL", "3VC", "3VR"), 3)))) # average block value # Purely like Viola and Jones 2001: work poorly for EM membranes #op5 = sub(block3VC, block3VL, block3VR) # center minus sides #op6 = sub(add(block3VL, block3VR), block3VC) # sides minus center # Two bright-black-bright horizontal features 8x4 / 8x4 / 8x4 block3HT = block(imgE, shift(cornersH, -bl/2, -bs -bs/2)) block3HC = block(imgE, shift(cornersH, -bl/2, -bs/2)) block3HB = block(imgE, shift(cornersH, -bl/2, bs/2)) op7 = let("3HT", block3HT, "3HC", block3HC, "3HB", block3HB, IF(AND(GT("3HT", "3HC"), GT("3HB", "3HC")), THEN(sub(add("3HT", "3HB"), "3HC")), # like Viola and Jones 2001 ELSE(div(add("3HT", "3HC", "3HB"), 3)))) # average block value # Purely like Viola and Jones 2001: work poorly for EM membranes #op7 = sub(block3HC, block3HT, block3HB) # center minus top and bottom #op8 = sub(add(block3HT, block3HB), block3HC) # top and bottom minus center # Combination of vertical and horizontal edge detection #op9 = maximum(op1, op3) #op10 = maximum(op6, op8) #op10 = maximum(op5, op7) """ # corners of a square block where 0,0 is at the top left cornersS = [[0, 0], [bs, 0], [0, bs], [bs, bs]] # 2x2 squares for oblique edge detection blockSTL = block(imgE, shift(cornersS, -bs, -bs)) # top left blockSTR = block(imgE, shift(cornersS, 0, -bs)) # top right blockSBL = block(imgE, shift(cornersS, -bs, 0)) # bottom left blockSBR = block(imgE, cornersS) # bottom right op11 = sub(add(blockSTL, blockSBR), blockSTR, blockSBL) op12 = sub(add(blockSTR, blockSBL), blockSTL, blockSBR) """ # Combination of vertical, horizontal and oblique edge detection #op13 = maximum(op1, op3, op6, op8, op11, op12) #op13 = maximum(op1, op3, op5, op7, op11, op12) # combinations are terrible for RandomForest # Edge detectors: sum of 3 adjacent pixels (not dividing by the other 6 # to avoid penalizing Y membrane configurations) """ op14 = maximum(add(offset(op13, [-1, -1]), op13, offset(op13, [ 1, 1])), add(offset(op13, [ 0, -1]), op13, offset(op13, [ 0, 1])), add(offset(op13, [ 1, -1]), op13, offset(op13, [-1, 1])), add(offset(op13, [-1, 0]), op13, offset(op13, [ 1, 0]))) """ #opMean, opVariance = filterBankBlockStatistics(img, integralImgE=imgE, sumType=sumType, converter=converter) # Return an ordered list of all ops #return [op1, op2, op3, op4, op5, op6, op7, op8, op9, op10, op11, op12, op13, op14] #return [op1, op3, op5, op7, opMean, opVariance] return [op1, op3, op5, op7]
def filterBankOrthogonalEdges(img, bs=4, bl=8, sumType=UnsignedLongType(), converter=Util.genericRealTypeConverter()): """ Haar-like features from Viola and Jones using integral images of a set of rotated images tuned to identify neuron membranes in electron microscopy. bs: length of the short side of a block bl: length of the long side of a block sumType: the type with which to add up pixel values in the integral image converter: for the IntegralImg, to convert from input to sumType """ # Create the integral image, stored as 64-bit alg = IntegralImg(img, sumType, converter) alg.process() integralImg = alg.getResult() imgE = Views.extendBorder(integralImg) # corners of a 4x8 or 8x4 rectangular block where 0,0 is the top left cornersV = [[0, 0], [bs -1, 0], # Vertical [0, bl -1], [bs -1, bl - 1]] cornersH = [[0, 0], [bl -1, 0], # Horizontal [0, bs -1], [bl -1, bs - 1]] # Two adjacent vertical rectangles 4x8 - 4x8 centered on the pixel blockVL = block(imgE, shift(cornersV, -bs, -bl/2)) blockVR = block(imgE, shift(cornersV, 0, -bl/2)) op1 = sub(blockVL, blockVR) op2 = sub(blockVR, blockVL) # Two adjacent horizontal rectangles 8x4 - 8x4 centered on the pixel blockHT = block(imgE, shift(cornersH, -bs, -bl/2)) blockHB = block(imgE, shift(cornersH, -bs, 0)) op3 = sub(blockHT, blockHB) op4 = sub(blockHB, blockHT) # Two bright-black-bright vertical features 4x8 - 4x8 - 4x8 block3VL = block(imgE, shift(cornersV, -bs -bs/2, -bl/2)) block3VC = block(imgE, shift(cornersV, -bs/2, -bl/2)) block3VR = block(imgE, shift(cornersV, bs/2, -bl/2)) op5 = let("3VL", block3VL, "3VC", block3VC, "3VR", block3VR, IF(AND(GT("3VL", "3VC"), GT("3VR", "3VC")), THEN(sub(add("3VL", "3VR"), "3VC")), # like Viola and Jones 2001 ELSE(div(add("3VL", "3VC", "3VR"), 3)))) # average block value # Purely like Viola and Jones 2001: work poorly for EM membranes #op5 = sub(block3VC, block3VL, block3VR) # center minus sides #op6 = sub(add(block3VL, block3VR), block3VC) # sides minus center # Two bright-black-bright horizontal features 8x4 / 8x4 / 8x4 block3HT = block(imgE, shift(cornersH, -bl/2, -bs -bs/2)) block3HC = block(imgE, shift(cornersH, -bl/2, -bs/2)) block3HB = block(imgE, shift(cornersH, -bl/2, bs/2)) op7 = let("3HT", block3HT, "3HC", block3HC, "3HB", block3HB, IF(AND(GT("3HT", "3HC"), GT("3HB", "3HC")), THEN(sub(add("3HT", "3HB"), "3HC")), ELSE(div(add("3HT", "3HC", "3HB"), 3)))) # average block value TODO make a single block #op7 = sub(block3HC, block3HT, block3HB) # center minus top and bottom #op8 = sub(add(block3HT, block3HB), block3HC) # top and bottom minus center # Two adjacent horizontal rectanges, 12x12 - 4x4 bll = bl + bl/2 cornersLarge = [[0, 0], [bll -1, 0], [0, bll -1], [bll -1, bll -1]] cornersSmall = [[0, 0], [bs -1, 0], [0, bs -1], [bs -1, bs -1]] # Subtract a large black rectangle from a small bright one - aiming at capturing synapses # Bright on the right blockLargeL = block(imgE, shift(cornersLarge, -bll, -bll/2)) blockSmallR = block(imgE, shift(cornersSmall, 0, -bs/2)) op9 = sub(blockSmallR, blockLargeL) # Bright on the left blockLargeR = block(imgE, shift(cornersLarge, 0, -bll/2)) blockSmallL = block(imgE, shift(cornersSmall, -bs, -bs/2)) op10 = sub(blockSmallL, blockLargeR) # Bright at the bottom blockLargeT = block(imgE, shift(cornersLarge, -bll/2, -bll)) blockSmallB = block(imgE, shift(cornersSmall, -bs/2, 0)) op11 = sub(blockSmallB, blockLargeT) # Bright at the top blockLargeB = block(imgE, shift(cornersLarge, -bll/2, 0)) blockSmallT = block(imgE, shift(cornersSmall, -bs/2, -bs)) op12 = sub(blockSmallT, blockLargeB) return [op1, op2, op3, op4, op5, op7, op9, op10, op11, op12]
def smooth_temporal_gradient(ops, img, sigma_xy, sigma_t, frame_start, frame_end, normalize_output): """ Smooth input image (imglib2 array) xyt with Gaussian and build temporal gradient from frame_start to frame_end """ n = img.numDimensions() assert n == 3, "Input data needs to be 3-dimensional, 2D + time" dims = [img.dimension(d) for d in range(n)] dim_x, dim_y, dim_t = dims if frame_end == -1: frame_end = dim_t if frame_end > dim_t: frame_end = dim_t assert frame_start < frame_end, "'Frame start' must be smaller than 'Frame end'" ## crop image temporally by using a View # img_crop = Views.interval(img, [0, 0, frame_start], [dim_x-1, dim_y-1, frame_end-1]) # or by cropping without view img_crop = ops.transform().crop( img, Intervals.createMinMax(0, 0, frame_start, dim_x - 1, dim_y - 1, frame_end - 1)) # create output for smoothing img_smooth = ArrayImgFactory(FloatType()).create(img_crop) # update dimensions (after cropping) dims = [img_crop.dimension(d) for d in range(n)] # smooth with Gaussian (use mirror as border treatment) Gauss3.gauss([sigma_xy, sigma_xy, sigma_t], Views.extendBorder(img_crop), img_smooth) # compute gradient along (time) axis 2 gradient = ArrayImgFactory(FloatType()).create(dims) PartialDerivative.gradientBackwardDifference( Views.extendBorder(img_smooth), gradient, 2) # separate response into growing and shrinking part by thresholding and multiplying that mask thresholded = ops.run("threshold.apply", gradient, FloatType(0.)) mask = ops.convert().float32(thresholded) grow = ops.run("math.multiply", gradient, mask) # same for shrinking, but negate befor to obtain negative part gradient_neg = ops.run("math.multiply", gradient, -1) thresholded = ops.run("threshold.apply", gradient_neg, FloatType(0.)) mask = ops.convert().float32(thresholded) shrink = ops.run("math.multiply", gradient, mask) # allign growth and shrink by offset of 1 in t dimesnion shrink = Views.interval(shrink, [0, 0, 0], [dims[0] - 1, dims[1] - 1, dims[2] - 2]) grow = Views.interval(grow, [0, 0, 1], [dims[0] - 1, dims[1] - 1, dims[2] - 1]) img_smooth = Views.interval(img_smooth, [0, 0, 0], [dims[0] - 1, dims[1] - 1, dims[2] - 2]) # concatenate output if normalize_output: shrink = rescale_uint8(ops, shrink) grow = rescale_uint8(ops, grow) img_smooth = rescale_uint8(ops, img_smooth) out = Views.stack([shrink, grow, img_smooth]) # permute channel with time to make time last dim (for back-conversion) out = Views.permute(out, 2, 3) # crop view 1st time point result (empty since using backwardDifferences) out = Views.interval(out, [0, 0, 0, 1], [out.dimension(d) - 1 for d in range(4)]) # get ImagePlus back and set correct dimensions out_imp = IJF.wrap(out, "Grow and shrink") # resize IMP now one frame less (see crop view) out_imp.setDimensions(3, 1, frame_end - frame_start - 2) out_imp.setDisplayMode(IJ.COMPOSITE) # IJ.save(out_imp, "H:/projects/032_loose_speckle/grow_and_shrink_ij.tif") return out_imp
from net.imglib2.algorithm.math.ImgMath import compute, add, offset, mul, minimum, maximum from net.imglib2.img.display.imagej import ImageJFunctions as IL from net.imglib2.type.numeric.real import FloatType from net.imglib2.view import Views from ij import IJ, ImagePlus img = IL.wrap(IJ.getImage()) # E.g. blobs sample image imgE = Views.extendBorder(img) def as2DKernel(imgE, weights): """ imgE: a RandomAccessible, such as an extended view of a RandomAccessibleInterval. weights: an odd-length list defining a square convolution kernel centered on the pixel, with columns moving slower than rows. Returns an ImgMath op. """ # Check preconditions: validate kernel if 1 != len(weights) % 2: raise Error("list of kernel weights must have an odd length.") side = int(pow(len(weights), 0.5)) # sqrt if pow(side, 2) != len(weights): raise Error("kernel must be a square.") half = side / 2 # Generate ImgMath ops # Note that multiplications by weights of value 1 or 0 will be erased automatically # so that the hierarchy of operations will be the same as in the manual approach above. return add([mul(weight, offset(imgE, [index % side - half, index / side - half])) for index, weight in enumerate(weights) if 0 != weight]) # All 4 edge detectors (left, right, top, bottom) opTop = as2DKernel(imgE, [-1]*3 + [0]*3 + [1]*3)
def filterBank(img, sumType=UnsignedLongType(), converter=Util.genericRealTypeConverter()): """ Haar-like features from Viola and Jones tuned to identify neuron membranes in electron microscopy. """ # Create the integral image, stored as 64-bit alg = IntegralImg(img, sumType, converter) alg.process() integralImg = alg.getResult() imgE = Views.extendBorder(integralImg) # corners of a 4x8 or 8x4 rectangular block where 0,0 is the top left bs = 4 # short side bl = 8 # long side cornersV = [ [0, 0], [bs - 1, 0], # Vertical [0, bl - 1], [bs - 1, bl - 1] ] cornersH = [ [0, 0], [bl - 1, 0], # Horizontal [0, bs - 1], [bl - 1, bs - 1] ] # Two adjacent vertical rectangles 4x8 - 4x8 centered on the pixel blockVL = block(imgE, shift(cornersV, -bs, -bl / 2)) blockVR = block(imgE, shift(cornersV, 0, -bl / 2)) op1 = sub(blockVL, blockVR) op2 = sub(blockVR, blockVL) # Two adjacent horizontal rectangles 8x4 - 8x4 centered on the pixel blockHT = block(imgE, shift(cornersH, -bs, -bl / 2)) blockHB = block(imgE, shift(cornersH, -bs, 0)) op3 = sub(blockHT, blockHB) op4 = sub(blockHB, blockHT) # Two bright-black-bright vertical features 4x8 - 4x8 - 4x8 block3VL = block(imgE, shift(cornersV, -bs - bs / 2, -bl / 2)) block3VC = block(imgE, shift(cornersV, -bs / 2, -bl / 2)) block3VR = block(imgE, shift(cornersV, bs / 2, -bl / 2)) op5 = sub(block3VC, block3VL, block3VR) # center minus sides op6 = sub(add(block3VL, block3VR), block3VC) # sides minus center # Two bright-black-bright horizontal features 8x4 / 8x4 / 8x4 block3HT = block(imgE, shift(cornersH, -bl / 2, -bs - bs / 2)) block3HC = block(imgE, shift(cornersH, -bl / 2, -bs / 2)) block3HB = block(imgE, shift(cornersH, -bl / 2, bs / 2)) op7 = sub(block3HC, block3HT, block3HB) # center minus top and bottom op8 = sub(add(block3HT, block3HB), block3HC) # top and bottom minus center # Combination of vertical and horizontal edge detection op9 = maximum(op1, op3) op10 = maximum(op6, op8) # corners of a square block where 0,0 is at the top left cornersS = [[0, 0], [bs, 0], [0, bs], [bs, bs]] # 2x2 squares for oblique edge detection blockSTL = block(imgE, shift(cornersS, -bs, -bs)) # top left blockSTR = block(imgE, shift(cornersS, 0, -bs)) # top right blockSBL = block(imgE, shift(cornersS, -bs, 0)) # bottom left blockSBR = block(imgE, cornersS) # bottom right op11 = sub(add(blockSTL, blockSBR), blockSTR, blockSBL) op12 = sub(add(blockSTR, blockSBL), blockSTL, blockSBR) # Combination of vertical, horizontal and oblique edge detection op13 = maximum(op1, op3, op6, op8, op11, op12) # Edge detectors: sum of 3 adjacent pixels (not dividing by the other 6 # to avoid penalizing Y membrane configurations) op14 = maximum(add(offset(op13, [-1, -1]), op13, offset(op13, [1, 1])), add(offset(op13, [0, -1]), op13, offset(op13, [0, 1])), add(offset(op13, [1, -1]), op13, offset(op13, [-1, 1])), add(offset(op13, [-1, 0]), op13, offset(op13, [1, 0]))) # Return a list of all ops #return [ob for name, ob in vars().iteritems() if re.match(r"^op\d+$", name)] # Ordered return [ op1, op2, op3, op4, op5, op6, op7, op8, op9, op10, op11, op12, op13, op14 ]
from net.imglib2 import FinalInterval from ij import IJ img = IL.wrap(IJ.getImage()) pyramid = [img] # level 0 is the image itself # Create levels of a pyramid with interpolation width = img.dimension(0) min_width = 32 s = [0.5 for d in xrange(img.numDimensions())] t = [-0.25 for d in xrange(img.numDimensions())] while width > min_width: width /= 2 imgE = Views.interpolate(Views.extendBorder(img), NLinearInterpolatorFactory()) # A scaled-down view of the imgR level = Views.interval( RealViews.transform(imgE, ScaleAndTranslation(s, t)), FinalInterval([ int(img.dimension(d) * 0.5) for d in xrange(img.numDimensions()) ])) # Create a new image for this level scaledImg = img.factory().create(level) # of dimensions as of level ImgUtil.copy(level, scaledImg) # copy the scaled down view into scaledImg pyramid.append(scaledImg) # Prepare for next iteration img = scaledImg # for the dimensions of the level in the next iteration for i, imgScaled in enumerate(pyramid):
resultFileName = '%s/result.tif' % home.rstrip('/') imp = ImageJFunctions.wrap( result, 'result' ) IJ.saveAsTiff(imp.duplicate(), resultFileName) relativeResult = result.copy() c = relativeResult.cursor() while c.hasNext(): c.fwd() cur = c.get() val = cur.get() cur.set( val - c.getDoublePosition( 2 ) ) relativeResultFileName = '%s/relativeResult.tif' % home.rstrip('/') imp = ImageJFunctions.wrap( relativeResult, 'relative result' ) IJ.saveAsTiff(imp.duplicate(), relativeResultFileName) ratio = [ wrappedImage.dimension( 0 )*1.0/result.dimension( 0 ), wrappedImage.dimension( 1 )*1.0/result.dimension( 1 ) ] shift = [ 0.0, 0.0 ] lutField = SingleDimensionLUTGrid(3, 3, result, 2, ratio, shift ) transformed = Views.interval( Views.raster( RealViews.transformReal( Views.interpolate( Views.extendBorder( wrappedImage ), NLinearInterpolatorFactory() ), lutField ) ), wrappedImage ) imp = ImageJFunctions.wrap( transformed, 'transformed' ) transformedFileName = '%s/transformed.tif' % home.rstrip('/') IJ.saveAsTiff( imp.duplicate(), transformedFileName ) # result = inference.estimateZCoordinates( 0, 0, startingCoordinates, matrixTracker, options )