Ejemplo n.º 1
0
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]
Ejemplo n.º 2
0
# 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
    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)
"""
for i, level in enumerate(pyramid):
  imp_level = IL.wrap(level, str(i+1))
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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]
Ejemplo n.º 5
0
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]
Ejemplo n.º 6
0
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())

# 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()
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()
Ejemplo n.º 8
0
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