Last active
March 25, 2019 21:21
-
-
Save ctrueden/ae89963150448ced6ef44f16be33c48a to your computer and use it in GitHub Desktop.
Seeded watershed in ImageJ using BoofCV
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#@dependency(group="org.boofcv", module="boofcv-core", version="0.33") | |
#@dependency(group="org.boofcv", module="boofcv-swing", version="0.32") | |
#@both ImagePlus imp | |
#@output ImagePlus (label="Watersheds") watersheds | |
#@output ImagePlus (label="Regions") regions | |
#@output ImagePlus (label="Seeds") seeds | |
import boofcv.alg.filter.binary.BinaryImageOps | |
import boofcv.alg.filter.binary.ThresholdImageOps | |
import boofcv.alg.misc.ImageStatistics | |
import boofcv.alg.segmentation.watershed.WatershedVincentSoille1991 | |
import boofcv.factory.segmentation.FactorySegmentationAlg | |
import boofcv.gui.binary.VisualizeBinaryData | |
import boofcv.gui.feature.VisualizeRegions | |
import boofcv.io.image.ConvertBufferedImage | |
import boofcv.struct.ConnectRule | |
import boofcv.struct.image.GrayS32 | |
import boofcv.struct.image.GrayU8 | |
// Call BoofCV to perform an in-place seeded watershed segmentation. | |
// Adapted from: | |
// https://github.com/lessthanoptimal/BoofCV/blob/v0.33.1/examples/src/main/java/boofcv/examples/segmentation/ExampleWatershedWithSeeds.java | |
// - Accepts a BufferedImage as input and mutates it. | |
// - Returns [regions, seeds] as a two-element list. | |
def seededWatershed = { image -> | |
input = ConvertBufferedImage.convertFromSingle(image, null, GrayU8.class) | |
// declare working data | |
binary = new GrayU8(input.width,input.height) | |
label = new GrayS32(input.width,input.height) | |
// Try using the mean pixel value to create a binary image then erode it to separate the particles from | |
// each other | |
mean = ImageStatistics.mean(input) | |
ThresholdImageOps.threshold(input, binary, (int) mean, true) | |
filtered = BinaryImageOps.erode8(binary, 2, null) | |
numRegions = BinaryImageOps.contour(filtered, ConnectRule.EIGHT, label).size() + 1 | |
// +1 to regions because contour only counts blobs and not the background | |
// The labeled image can be used as is. A precondition for seeded watershed is that all seeds have an | |
// ID > 0. Luckily, a value of 0 was used for background pixels in the contour algorithm. | |
watershed = FactorySegmentationAlg.watershed(ConnectRule.FOUR) | |
watershed.process(input,label) | |
output = watershed.getOutput() | |
outLabeled = VisualizeBinaryData.renderLabeledBG(label, numRegions, null) | |
VisualizeRegions.watersheds(output,image,1) | |
// Removing the watersheds and update the region count | |
// NOTE: watershed.getTotalRegions() does not return correct results if seeds are used! | |
watershed.removeWatersheds() | |
numRegions-- | |
outRegions = VisualizeRegions.regions(output,numRegions,null) | |
return [outRegions, outLabeled] | |
} | |
result = seededWatershed(imp.getImage()) | |
regions = new ij.ImagePlus("Regions", result[0]) | |
seeds = new ij.ImagePlus("Seeds", result[1]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Requires
scijava-grab
, not currently included with Fiji. Download it here and drop it intoFiji.app/jars
.