Esempio n. 1
0
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    
Esempio n. 3
0
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
Esempio n. 4
0
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]
Esempio n. 5
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]
Esempio n. 6
0
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    
Esempio n. 8
0
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
Esempio n. 9
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
Esempio n. 10
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]
Esempio n. 11
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]
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
    ]
Esempio n. 15
0
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 )