Example #1
0
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")))
Example #2
0
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
Example #3
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]
# 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
Example #6
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]
Example #7
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]
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