Skip to content

Commit

Permalink
add label/filter/ChamferLabelErosion2DShort.java
Browse files Browse the repository at this point in the history
  • Loading branch information
dlegland committed Sep 29, 2022
1 parent 5f6de9a commit 274a8d3
Show file tree
Hide file tree
Showing 5 changed files with 500 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ private void backwardIteration(ImageStack res, ImageStack distMap, double distMa
Collection<ShortOffset> offsets = mask.getBackwardOffsets();

// Iterate over voxels
for (int z = 0; z < sizeZ; z++)
for (int z = sizeZ-1; z >= 0; z--)
{
this.fireProgressChanged(this, z, sizeZ);
for (int y = sizeY-1; y >= 0; y--)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/**
*
*/
package inra.ijpb.label.filter;

import ij.process.ImageProcessor;
import inra.ijpb.algo.AlgoStub;
import inra.ijpb.binary.distmap.ChamferMask2D;
import inra.ijpb.morphology.Strel;
import inra.ijpb.morphology.strel.ChamferStrel;

/**
* Implementation of morphological erosion for 2D label images / label maps.
*
* Can be applied to label maps encoded with 8 or 16 bits integers, or 32 bit
* floats.
*
*
* @author dlegland
*
*/
public class ChamferLabelErosion2DShort extends AlgoStub
{
/**
* The chamfer mask used to propagate distances.
*/
ChamferMask2D mask;

/**
* The radius of dilation of labels. In practice, the distance is propagated
* up to radius + 0.5.
*/
double radius;

/**
* For erosion, we can work only with the structuring element.
*/
Strel strel;

public ChamferLabelErosion2DShort(ChamferMask2D mask, double radius)
{
this.mask = mask;
this.radius = radius;

this.strel = new ChamferStrel(mask, radius);
}

public ImageProcessor process(ImageProcessor image)
{
// retrieve image size
int sizeX = image.getWidth();
int sizeY = image.getHeight();

// allocate memory for output
ImageProcessor res = image.createProcessor(sizeX, sizeY);

// pre-compute strel shifts
int[][] shifts = strel.getShifts();

// iterate over pixels within output image
for (int y = 0; y < sizeY; y++)
{
for (int x = 0; x < sizeX; x++)
{
int label = (int) image.getf(x, y);

// no need to process background pixels
if (label == 0)
{
continue;
}

// iterate over neighbors defined by strel
for (int[] shift : shifts)
{
// position of neighbor
int x2 = x + shift[0];
int y2 = y + shift[1];

// do not process pixels outside of image bounds
if (x2 < 0 || x2 >= sizeX) continue;
if (y2 < 0 || y2 >= sizeY) continue;

// check if neighbor is background
int label2 = (int) image.getf(x2, y2);
if (label2 == 0)
{
label = 0;
break;
}
}

res.setf(x, y, label);
}
}

return res;
}
}
104 changes: 104 additions & 0 deletions src/main/java/inra/ijpb/label/filter/ChamferLabelErosion3DShort.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
*
*/
package inra.ijpb.label.filter;

import ij.ImageStack;
import inra.ijpb.algo.AlgoStub;
import inra.ijpb.binary.distmap.ChamferMask3D;
import inra.ijpb.morphology.Strel3D;
import inra.ijpb.morphology.strel.ChamferStrel3D;

/**
* Implementation of morphological erosion for 3D label images / label maps.
*
* Can be applied to label maps encoded with 8 or 16 bits integers, or 32 bit
* floats.
*
*
* @author dlegland
*
*/
public class ChamferLabelErosion3DShort extends AlgoStub
{
/**
* The chamfer mask used to propagate distances.
*/
ChamferMask3D mask;

/**
* The radius of dilation of labels. In practice, the distance is propagated
* up to radius + 0.5.
*/
double radius;

/**
* For erosion, we can work only with the structuring element.
*/
Strel3D strel;

public ChamferLabelErosion3DShort(ChamferMask3D mask, double radius)
{
this.mask = mask;
this.radius = radius;

this.strel = new ChamferStrel3D(mask, radius);
}

public ImageStack process(ImageStack image)
{
// retrieve image size
int sizeX = image.getWidth();
int sizeY = image.getHeight();
int sizeZ = image.getSize();

// allocate memory for output
ImageStack res = ImageStack.create(sizeX, sizeY, sizeZ, image.getBitDepth());

// pre-compute strel shifts
int[][] shifts = strel.getShifts3D();

// iterate over pixels within output image
for (int z = 0; z < sizeZ; z++)
{
for (int y = 0; y < sizeY; y++)
{
for (int x = 0; x < sizeX; x++)
{
int label = (int) image.getVoxel(x, y, z);

// no need to process background pixels
if (label == 0)
{
continue;
}

// iterate over neighbors defined by strel
for (int[] shift : shifts)
{
// position of neighbor
int x2 = x + shift[0];
int y2 = y + shift[1];
int z2 = z + shift[2];

// do not process pixels outside of image bounds
if (x2 < 0 || x2 >= sizeX) continue;
if (y2 < 0 || y2 >= sizeY) continue;
if (z2 < 0 || z2 >= sizeZ) continue;

// check if neighbor is background
int label2 = (int) image.getVoxel(x2, y2, z2);
if (label2 == 0)
{
label = 0;
break;
}
}

res.setVoxel(x, y, z, label);
}
}
}
return res;
}
}
4 changes: 2 additions & 2 deletions src/main/java/inra/ijpb/morphology/strel/AbstractStrel3D.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public ImageStack dilation(ImageStack image)
int sizeZ = image.getSize();

// allocate result
ImageStack res = ImageStack.create(sizeX, sizeX, sizeZ, image.getBitDepth());
ImageStack res = ImageStack.create(sizeX, sizeY, sizeZ, image.getBitDepth());

// iterate over pixels
int[][] shifts = getShifts3D();
Expand Down Expand Up @@ -201,7 +201,7 @@ public ImageStack erosion(ImageStack image)
int sizeZ = image.getSize();

// allocate result
ImageStack res = ImageStack.create(sizeX, sizeX, sizeZ, image.getBitDepth());
ImageStack res = ImageStack.create(sizeX, sizeY, sizeZ, image.getBitDepth());

// iterate over pixels
int[][] shifts = getShifts3D();
Expand Down
Loading

0 comments on commit 274a8d3

Please sign in to comment.