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 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 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])
# Create the integral image of an 8-bit input, stored as 64-bit target = ArrayImgs.unsignedLongs(Intervals.dimensionsAsLongArray(img)) # Copy input onto the target image compute(img).into(target) # Extend target with zeros, so that we can read at coordinate -1 imgE = Views.extendZero(target) # Integrate every dimension, cummulatively by writing into # a target image that is also the input for d in xrange(img.numDimensions()): coord = [0] * img.numDimensions() # array of zeros coord[d] = -1 # Cummulative sum along the current dimension # Note that instead of the ImgMath offset op, # we could have used Views.translate(Views.extendZero(target), [1, 0])) # (Notice though the sign change in the translation) integral = add(target, offset(imgE, coord)) compute(integral).into(target) # The target is the integral image integralImg = target # 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)) # divide by total number of pixels in the block blurred = ArrayImgs.floats(Intervals.dimensionsAsLongArray(img)) compute(op).into(blurred, FloatType())
# 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]))) for name, op in ((name, eval(name)) for name in vars() if re.match(r"^op\d+$", name)): # For development: if WindowManager.getImage(name): continue # don't open # opimp = IL.wrap(op.view(FloatType()), name) opimp.getProcessor().resetMinAndMax() opimp.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 ]