Skip to content

Commit

Permalink
Added exception for converter from grayscale image
Browse files Browse the repository at this point in the history
  • Loading branch information
CellDynamics committed Jan 9, 2018
1 parent eae303a commit 83e2f67
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 35 deletions.
Expand Up @@ -539,7 +539,7 @@ public Contour(boolean storeSeeds, AutoThresholder.Method trueBackground, double
public Seeds propagateSeed(ImageProcessor previous, ImageProcessor org, double shrinkPower,
double expandPower) {
// FIXME if there are two separate objects in the same color they will be treated as
// separately
// separate objects
double stepsshrink = shrinkPower / stepSize; // total shrink/step size
double stepsexp = (expandPower) / stepSize; // total shrink/step size
Seeds ret = new Seeds(2);
Expand Down Expand Up @@ -676,37 +676,42 @@ public Seeds propagateSeed(ImageProcessor previous, ImageProcessor org, double s
// store seeds if option ticked
Seeds ret = new Seeds(2);
// need to process each object separately to preserve multi fg seeds.
Seeds decodedSeeds = SeedProcessor.getGrayscaleAsSeeds(cp);
for (ImageProcessor ip : decodedSeeds.get(SeedTypes.FOREGROUNDS)) {
// make objects smaller
small = BinaryFilters.iterateMorphological(ip, MorphoOperations.ERODE, shrinkPower);
ret.put(SeedTypes.FOREGROUNDS, small);
}
Seeds decodedSeeds;
try {
decodedSeeds = SeedProcessor.getGrayscaleAsSeeds(cp);
for (ImageProcessor ip : decodedSeeds.get(SeedTypes.FOREGROUNDS)) {
// make objects smaller
small = BinaryFilters.iterateMorphological(ip, MorphoOperations.ERODE, shrinkPower);
ret.put(SeedTypes.FOREGROUNDS, small);
}

// make background bigger but for all, convert to binary first
big.threshold(0);
big = BinaryFilters.iterateMorphological(big, MorphoOperations.DILATE, expandPower);
cp.threshold(0); // input also must be binary (after computing FG)

// apply big to old background making object bigger and prevent covering objects on
// frame
// n+1
// by previous background (make "empty" not seeded space around objects)
// IJ.saveAsTiff(new ImagePlus("", big), "/tmp/testIterateMorphological_bigbef.tif");
// IJ.saveAsTiff(new ImagePlus("", cp), "/tmp/testIterateMorphological_cp.tif");
for (int x = 0; x < cp.getWidth(); x++) {
for (int y = 0; y < cp.getHeight(); y++) {
big.putPixel(x, y, big.getPixel(x, y) | cp.getPixel(x, y));
// make background bigger but for all, convert to binary first
big.threshold(0);
big = BinaryFilters.iterateMorphological(big, MorphoOperations.DILATE, expandPower);
cp.threshold(0); // input also must be binary (after computing FG)

// apply big to old background making object bigger and prevent covering objects on
// frame
// n+1
// by previous background (make "empty" not seeded space around objects)
// IJ.saveAsTiff(new ImagePlus("", big), "/tmp/testIterateMorphological_bigbef.tif");
// IJ.saveAsTiff(new ImagePlus("", cp), "/tmp/testIterateMorphological_cp.tif");
for (int x = 0; x < cp.getWidth(); x++) {
for (int y = 0; y < cp.getHeight(); y++) {
big.putPixel(x, y, big.getPixel(x, y) | cp.getPixel(x, y));
}
}
}

big.invert(); // invert to have BG pixels white in seed. (required by convertToList)
big.invert(); // invert to have BG pixels white in seed. (required by convertToList)

ret.put(SeedTypes.BACKGROUND, getTrueBackground(big, org));
if (storeSeeds) {
seeds.add(ret);
ret.put(SeedTypes.BACKGROUND, getTrueBackground(big, org));
if (storeSeeds) {
seeds.add(ret);
}
} catch (RandomWalkException e) { // from decodeseeds - no FG seeds
// this is handled to console only as return is still valid (no FG seeds in output)
LOGGER.debug("Empty seeds.");
}

return ret;
}

Expand Down
Expand Up @@ -305,15 +305,19 @@ private enum StoppedBy {
public enum SeedTypes {
/**
* Denote foreground related data. Usually on index 0.
*
* <p>FG data can be grayscale images up to 8-bits.
*/
FOREGROUNDS(0),
/**
* Denote background related data. Usually on index 1.
*
* <p>BG data can be grayscale image up to 8-bits.
*/
BACKGROUND(1),
/**
* Rough mask used for computing local mean. Used only if {@link RandomWalkOptions#useLocalMean}
* is true.
* is true. This mask should be always binary.
*
* @see RandomWalkSegmentation#solver(Seeds, RealMatrix[])
* @see RandomWalkSegmentation#getMeanSeedLocal(ImageProcessor, int)
Expand Down Expand Up @@ -443,7 +447,7 @@ public ImageProcessor run(Seeds seeds) throws RandomWalkException {
}
solved = solver(seedsNext, precomputed);
}
RealMatrix result = compare(solved); // result as matrix // FIXME can be null
RealMatrix result = compare(solved); // result as matrix
ImageProcessor resultim = realMatrix2ImageProcessor(result).convertToByteProcessor(true);
// cut mask - cut segmentation result by initial ROUGHMASK if present
if (params.maskLimit == true && seeds.get(SeedTypes.ROUGHMASK) != null) {
Expand Down Expand Up @@ -1042,7 +1046,7 @@ protected ProbabilityMaps solver(Seeds seeds, RealMatrix[] gradients) {

// get average "distance" between weights multiplying w = w.*avgw, this is only for
// optimisation purposes.
// does not apply for FG if we use local mean, applied for BG always FIXME why?
// does not apply for FG if we use local mean, applied for BG always (better results)
if (params.useLocalMean == false || userBckPoints.contains(seedsPointsFg.get(cell))) {
wrfg.walkInOptimizedOrder(new MatrixDotProduct(avgwxfg));
wlfg.walkInOptimizedOrder(new MatrixDotProduct(avgwxfg));
Expand Down
Expand Up @@ -797,7 +797,6 @@ public ImagePlus runPlugin() {
foreColor = Color.RED;
backColor = Color.GREEN;
if (seedImage.getNSlices() >= startSlice) {
// FIXME seeds can be empty (but at least one map will exist always)
seeds = SeedProcessor.decodeSeedsfromRgb(seedImage.getStack().getProcessor(startSlice),
Arrays.asList(foreColor), backColor);
} else {
Expand Down Expand Up @@ -825,6 +824,10 @@ public ImagePlus runPlugin() {
if (seedImage == null) {
throw new RandomWalkException("Mask image could not be loaded");
}
// TODO add checkbox in UI to show (in QCONFfile dynamic region)
ImagePlus maskToDisplay = seedImage.duplicate();
maskToDisplay.setTitle("Mask-" + Paths.get(model.qconfFile).getFileName().toString());
maskToDisplay.show();
// TODO check if each slice max value is less than 255
// and continue to the next case
case MaskImage:
Expand All @@ -835,7 +838,7 @@ public ImagePlus runPlugin() {
is.getProcessor(startSlice), model.shrinkPower, model.expandPower);
// mask to local mean
seeds.put(SeedTypes.ROUGHMASK,
seedImage.getStack().getProcessor(startSlice).convertToByte(true).duplicate());
seedImage.getStack().getProcessor(startSlice).convertToByte(true));
seeds.get(SeedTypes.ROUGHMASK, 1).threshold(0); // to have BW map in case
break;
default:
Expand Down Expand Up @@ -878,7 +881,8 @@ public ImagePlus runPlugin() {
seedImage.getStack().getProcessor(s).convertToByte(true), is.getProcessor(s),
model.shrinkPower, model.expandPower);
nextseed.put(SeedTypes.ROUGHMASK,
seedImage.getStack().getProcessor(s).convertToByte(false));
seedImage.getStack().getProcessor(s).convertToByte(false)); // this makes copy
nextseed.get(SeedTypes.ROUGHMASK, 1).threshold(0); // to have BW map in case
break;
default:
}
Expand Down
Expand Up @@ -283,8 +283,9 @@ public static ImageProcessor flatten(Seeds seeds, SeedTypes type, int initialVal
*
* @param im 8-bit grayscale image, 0 is background
* @return Seeds with {@link SeedTypes#FOREGROUNDS} filled. No {@link SeedTypes#BACKGROUND}
* @throws RandomWalkException when all output FG seed maps are empty
*/
public static Seeds getGrayscaleAsSeeds(ImageProcessor im) {
public static Seeds getGrayscaleAsSeeds(ImageProcessor im) throws RandomWalkException {
Seeds ret = new Seeds(2);
ImageStatistics stats = im.getStats();
int max = (int) stats.max; // max value
Expand Down Expand Up @@ -316,6 +317,7 @@ public static Seeds getGrayscaleAsSeeds(ImageProcessor im) {
ret.get(SeedTypes.FOREGROUNDS).remove(i.intValue() - 1);
}
}
validateSeeds(ret, SeedTypes.FOREGROUNDS);
return ret;
}

Expand Down
Expand Up @@ -28,9 +28,11 @@
* in {@link ImageStack}. One needs to take care about proper unwrapping data if standard
* {@link #get(Object)} is used.
*
* <p>Seed maps can be converted from various sources like RGB images or grayscale images but maps
* are always binary.
*
* @author p.baniukiewicz
*
* @see SeedProcessor
*/
@SuppressWarnings("serial")
public class Seeds extends ListMap<ImageProcessor> {
Expand Down

0 comments on commit 83e2f67

Please sign in to comment.