def absdiff(imgA, imgB): return let( "diff", sub(imgA, imgB), IF( LT("diff", 0), THEN(sub(0, "diff")), # invert the sign to make it positive ELSE("diff")))
def findPeaks(img4D, params): """ img4D: a 4D RandomAccessibleInterval params["frames"]: the number of consecutive time points to average towards detecting peaks with difference of Gaussian. Returns a list of lists of peaks found, one list per time point. """ frames = params["frames"] # Work image: the current sum sum3D = ArrayImgs.unsignedLongs([img4D.dimension(d) for d in [0, 1, 2]]) peaks = [] # Sum of the first set of frames compute(add([Views.hyperSlice(img4D, 3, i) for i in xrange(frames)])).into(sum3D) # Extract nuclei from first sum3D peaks.append(doGPeaks(sum3D, params)) # Running sums: subtract the first and add the last for i in xrange(frames, img4D.dimension(3), 1): compute(add(sub(sum3D, Views.hyperSlice(img4D, 3, i - frames)), Views.hyperSlice(img4D, 3, i))) \ .into(sum3D) # Extract nuclei from sum4D peaks.append(doGPeaks(sum3D, params)) return peaks
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]
# Compute the brightness: pick the maximum intensity pixel of every channel # and then normalize it by dividing by the number of channels compute(div(maximum([red, green, blue]), 255.0)).into(brightness) # Show the brightness image impB = IL.wrap(brightness, imp.getTitle() + " brightness") impB.show() # Compute now the image color saturation saturation = ArrayImgFactory(FloatType()).create(img) compute( let( "red", red, # store as directly readable variables (no dictionary lookups) "green", green, # so that only 3 cursors are needed instead of 6 "blue", blue, "max", maximum([var("red"), var("green"), var("blue")]), "min", minimum([var("red"), var("green"), var("blue")]), IF(EQ(0, var("max")), THEN(0), ELSE(div(sub(var("max"), var("min")), var("max")))))).into(saturation) impC = IL.wrap(saturation, imp.getTitle() + " saturation") impC.show()
# Create the integral image, stored as 64-bit alg = IntegralImg(img, UnsignedLongType(), Util.genericIntegerTypeConverter()) alg.process() integralImg = alg.getResult() imgE = Views.extendBorder(integralImg) # Haar-like features from Viola and Jones # tuned to identify neuron membranes # Two adjacent vertical rectangles 4x8 - 4x8 cornersVL = [[-3, -4], [0, -4], [-3, 3], [0, 3]] cornersVR = [[1, -4], [4, -4], [1, 3], [4, 3]] blockVL = block(imgE, cornersVL) blockVR = block(imgE, cornersVR) op1 = sub(blockVL, blockVR) op2 = sub(blockVR, blockVL) # Two adjacent horizontal rectangles 4x8 - 4x8 cornersHT = [[-4, -3], [3, -3], [-4, 0], [3, 0]] cornersHB = [[-4, 1], [3, 1], [-4, 4], [3, 4]] blockHT = block(imgE, cornersHT) blockHB = block(imgE, cornersHB) op3 = sub(blockHT, blockHB) op4 = sub(blockHB, blockHT) # Two bright-black-bright vertical features 4x8 - 4x8 - 4x8 corners3VL = [[x - 2, y] for x, y in cornersVL] corners3VC = [[x + 2, y] for x, y in cornersVL] corners3VR = [[x + 2, y] for x, y in cornersVR] print corners3VL
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]
from net.imglib2.algorithm.math.ImgMath import computeIntoFloat, sub, div from net.imglib2.img.display.imagej import ImageJFunctions as IL from net.imglib2.type.numeric.real import FloatType from ij import IJ # Simple example: normalize an image imp = IJ.getImage() ip = imp.getProcessor() minV, maxV = ip.getMin(), ip.getMax() img = IL.wrap(imp) op = div(sub(img, minV), maxV - minV + 1) result = computeIntoFloat(op) IL.wrap(result, "normalized").show() # As a view IL.wrap(op.view(FloatType()), "normalized").show()
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 ]
def test(red, green, blue, easy=True): saturation = let( "red", red, "green", green, "blue", blue, "max", maximum("red", "green", "blue"), "min", minimum("red", "green", "blue"), IF(EQ(0, "max"), THEN(0), ELSE(div(sub("max", "min"), "max")))) brightness = div(maximum(red, green, blue), 255.0) hue = IF( EQ(0, saturation), THEN(0), ELSE( let( "red", red, "green", green, "blue", blue, "max", maximum("red", "green", "blue"), "min", minimum("red", "green", "blue"), "range", sub("max", "min"), "redc", div(sub("max", "red"), "range"), "greenc", div(sub("max", "green"), "range"), "bluec", div(sub("max", "blue"), "range"), "hue", div( IF( EQ("red", "max"), THEN(sub("bluec", "greenc")), ELSE( IF(EQ("green", "max"), THEN(sub(add(2, "redc"), "bluec")), ELSE(sub(add(4, "greenc"), "redc"))))), 6), IF(LT("hue", 0), THEN(add("hue", 1)), ELSE("hue"))))) #print hierarchy(hue) #print "hue view:", hue.view( FloatType() ).iterationOrder() if easy: # About 26 ms """ hsb = Views.stack( hue.view( FloatType() ), saturation.view( FloatType() ), brightness.view( FloatType() ) ) """ # About 13 ms: half! Still much worse than plain ImageJ, # but the source images are iterated 4 times, rather than just once, # and the saturation is computed twice, # and the min, max is computed 3 and 4 times, respectively. hsb = Views.stack(hue.viewDouble(FloatType()), saturation.viewDouble(FloatType()), brightness.viewDouble(FloatType())) """ # Even worse: ~37 ms width, height = rgb.dimension(0), rgb.dimension(1) h = compute(hue).into(ArrayImgs.floats([width, height])) s = compute(saturation).into(ArrayImgs.floats([width, height])) b = compute(brightness).into(ArrayImgs.floats([width, height])) hsb = Views.stack( h, s, b ) """ imp = IL.wrap(hsb, "HSB view") else: # Tested it: takes more time (~40 ms vs 26 ms above) width, height = rgb.dimension(0), rgb.dimension(1) hb = zeros(width * height, 'f') sb = zeros(width * height, 'f') bb = zeros(width * height, 'f') h = ArrayImgs.floats(hb, [width, height]) s = ArrayImgs.floats(sb, [width, height]) b = ArrayImgs.floats(bb, [width, height]) #print "ArrayImg:", b.iterationOrder() ImgUtil.copy(ImgView.wrap(hue.view(FloatType()), None), h) ImgUtil.copy(ImgView.wrap(saturation.view(FloatType()), None), s) ImgUtil.copy(ImgView.wrap(brightness.view(FloatType()), None), b) stack = ImageStack(width, height) stack.addSlice(FloatProcessor(width, height, hb, None)) stack.addSlice(FloatProcessor(width, height, sb, None)) stack.addSlice(FloatProcessor(width, height, bb, None)) imp = ImagePlus("hsb", stack) return imp