[ImageJ-devel] Qeustion regarding labeling and regions of interest in imglib2
Robert Haase
rhaase at mpi-cbg.de
Thu Sep 10 03:11:38 CDT 2015
Hi Tobias,
thanks a lot for the help. Actually, the presented for-loop only worked
for byte images, but the needed change is not too complicated.
Just in case, somebody out there has a similar issue, the final solution is:
//Transform an ImagePlus to an ImpLabeling. The original pixel value
should be the label afterwards.
public static ImgLabeling<Integer, IntType>
getIntIntImgLabellingFromLabelMapImagePlus(ImagePlus labelMap)
{
final Img< FloatType > img2 = ImageJFunctions.wrapFloat(
labelMap );
final Dimensions dims = img2;
final IntType t = new IntType();
final RandomAccessibleInterval< IntType > img =
Util.getArrayOrCellImgFactory( dims, t ).create( dims, t );
final ImgLabeling< Integer, IntType > labeling = new
ImgLabeling< Integer, IntType >( img );
final Cursor< LabelingType< Integer > > labelCursor =
Views.flatIterable( labeling ).cursor();
for ( final FloatType input : Views.flatIterable( img2 ) )
{
final LabelingType< Integer > element = labelCursor.next();
if ( input.get() != 0 )
element.add( (int)input.get() );
}
return labeling;
}
So, thanks again!
Best,
Robert
Am 9/9/15 um 9:21 PM schrieb Tobias Pietzsch:
> Hi Robert,
>
> the problem is the following:
> In the ImgLabeling constructor
> public ImgLabeling( final RandomAccessibleInterval< I > img )
> the img you pass is used to store the labels at each pixel.
> (The way that works is that integers are mapped to sets of labels that
> occur. If you have labels of type String, i.e., a
> ImgLabeling<String,IntType>,
> then depending on which labels and combinations of labels actually
> occur in your labeling, the mapping might be something like
> 0 -> {}
> 1 -> {"A"}
> 2 -> {"B"}
> 3 -> {"B","C"}
> etc...
> The mapping is build, as you add labels to pixels.)
>
> The assumption is that initially the labeling is empty, that is all
> zeros in the backing image, and the mapping just comprising 0 -> {}.
> In your example, you passed the labelMap as the backing image. This is
> not zeroed.
>
> One way to make your example work is to simply use a new, empty
> backing image, and then set the labels from the labelMap like you did.
> Replace this:
> final RandomAccessibleInterval< IntType > img =
> ImageJFunctions.wrapNumeric( labelMap );
> Img< FloatType > img2 = ImageJFunctions.convertFloat( labelMap );
> final long[] dims = new long[ img.numDimensions() ];
> ImgLabeling< Integer, IntType > labeling = new ImgLabeling< Integer,
> IntType >( img );
> by this:
> final Img< FloatType > img2 = ImageJFunctions.convertFloat( labelMap );
> final Dimensions dims = img2;
> final IntType t = new IntType();
> final RandomAccessibleInterval< IntType > img =
> Util.getArrayOrCellImgFactory( dims, t ).create( dims, t );
> final ImgLabeling< Integer, IntType > labeling = new ImgLabeling<
> Integer, IntType >( img );
> Then it works.
>
>
> For transfering the labeling you do not have to loop over all the
> labels. you could just do this:
> final Cursor< LabelingType< Integer > > labelCursor =
> Views.flatIterable( labeling ).cursor();
> for ( final UnsignedByteType input : Views.flatIterable(
> ImageJFunctions.wrapByte( labelMap ) ) )
> {
> final LabelingType< Integer > element = labelCursor.next();
> if ( input.get() != 0 )
> element.add( input.get() );
> }
> (This assumes that in labelMap the value 0 means “no label”).
>
>
> In principle, if your labelMap has values 0, 1, 2, ... without big
> gaps, and 0 means “no label” you could just use it directly as backing
> image and produce a fitting LabelingMapping, like
> 0 -> {}
> 1 -> {1}
> 2 -> {2}
> 3 -> {3}
> etc yourself. But that involves diving much deeper into the details,
> basically reading through the code of ImgLabeling and LabelingMapping.
> I would recommend above solution for now.
>
> best regards,
> Tobias
>
> On 08 Sep 2015, at 09:11, Robert Haase <rhaase at mpi-cbg.de
> <mailto:rhaase at mpi-cbg.de>> wrote:
>
>> Hi All,
>>
>> I'm quite new in developing imagej-plugins using imglib2. I ran in
>> some issues working with Labeling and Regions in imglib2. Hopefully,
>> somebody of you can help me. This is what I would like to do:
>>
>> I have an image(Plus) where pixel values correspond to the desired
>> labeling. Thus, all pixels with value 1 belong to label 1, all pixels
>> with value 2 belong to label 2 and so on. Labelled regions cannot
>> overlap. Now, I would like to create an ImgLabeling from the given
>> ImagePlus to manage the corresponding regions of interest in imglib2
>> and to do the analysis using this library.
>> I was able to create some functions which appear to do the
>> transformation, however, the results are not fully understandable for
>> me. On bottom of this email you find "minimal" example code (which
>> runs fine in eclipse set up for ImageJ-development) which creates a
>> labelmap-ImagePlus, transforms it into ImgLabeling and displays
>> binary images corresponding to the regions. However, when I input a
>> label with 100 pixels, the corresponding output region may or may not
>> have the same number of pixels. So the output of the program is:
>>
>> Number of input pixels in label 0: 9400
>> Number of input pixels in label 1: 100
>> Number of input pixels in label 2: 200
>> Number of input pixels in label 3: 300
>> Number of input pixels in label 4: 0
>> Number of out pixels in region: 10000
>> Number of out pixels in region: 600
>> Number of out pixels in region: 500
>> Number of out pixels in region: 300
>>
>> As you can see, the number of read-in pixels is not equal to the
>> number of pixels which are positive afterwards in the corresponding
>> region. The program visualises the images as well. The mistake in the
>> result is obvious. My mistake in the code is not that obvious to me.
>>
>> I guess, I interpret the meaning of regions and/or labels wrong.
>> Hopefully somebody of you may point me in the right direction to do
>> the above mentioned transformation properly.
>>
>> Thanks a lot in advance!
>> Robert
>>
>> LabelingExample.java ----------------------------
>>
>>
>> import ij.ImagePlus;
>> import ij.gui.NewImage;
>> import ij.process.ImageProcessor;
>>
>> import java.awt.Rectangle;
>> import java.io.IOException;
>> import java.util.Set;
>>
>> import net.imglib2.Cursor;
>> import net.imglib2.RandomAccess;
>> import net.imglib2.RandomAccessibleInterval;
>> import net.imglib2.img.Img;
>> import net.imglib2.img.array.ArrayImgs;
>> import net.imglib2.img.display.imagej.ImageJFunctions;
>> import net.imglib2.roi.labeling.ImgLabeling;
>> import net.imglib2.roi.labeling.LabelRegion;
>> import net.imglib2.roi.labeling.LabelRegionCursor;
>> import net.imglib2.roi.labeling.LabelRegions;
>> import net.imglib2.roi.labeling.LabelingType;
>> import net.imglib2.type.logic.BitType;
>> import net.imglib2.type.logic.BoolType;
>> import net.imglib2.type.numeric.integer.IntType;
>> import net.imglib2.type.numeric.real.FloatType;
>>
>> public class LabelingExample {
>> LabelingExample()
>> {
>> new ij.ImageJ();
>>
>> //Create and show a simple test image, 100x100
>> ImagePlus imp = createTestImage();
>> imp.show();
>>
>> //Create an ImgLabeling from the ImagePlus
>> ImgLabeling<Integer, IntType> labeling =
>> getIntIntImgLabellingFromLabelMapImagePlus(imp);
>>
>> //Read out regions and labelNames
>> LabelRegions<Integer> regions = new
>> LabelRegions<Integer>(labeling);
>> Set<Integer> labelNames = labeling.getMapping().getLabels();
>>
>> //Visualise the labels as binary images.
>> for (Integer labelName : labelNames )
>> {
>> LabelRegion<Integer> lr = regions.getLabelRegion(labelName);
>> ImageJFunctions.show(labelRegionToBinaryImage(lr,
>> (Img<IntType>)labeling.getIndexImg()));
>> }
>> }
>>
>> //Create an image with three labels (+background)
>> //The three labels have an area of 100, 200 and 300.
>> private ImagePlus createTestImage()
>> {
>> ImagePlus imp = NewImage.createByteImage("Test iamge", 100,
>> 100, 1, NewImage.FILL_BLACK);
>> ImageProcessor ip = imp.getProcessor();
>> ip.setRoi(new Rectangle(10, 10, 10, 10));
>> ip.setColor(1);
>> ip.fill();
>> ip.setRoi(new Rectangle(20, 20, 10, 20));
>> ip.setColor(2);
>> ip.fill();
>> ip.setRoi(new Rectangle(40, 40, 10, 30));
>> ip.setColor(3);
>> ip.fill();
>>
>> return imp;
>> }
>>
>> //Transform an ImagePlus to a Labeling Imp. The original pixel
>> value should be the label afterwards.
>> public static ImgLabeling<Integer, IntType>
>> getIntIntImgLabellingFromLabelMapImagePlus(ImagePlus labelMap)
>> {
>> final RandomAccessibleInterval< IntType > img =
>> ImageJFunctions.wrapNumeric(labelMap);
>> Img< FloatType > img2 = ImageJFunctions.convertFloat(labelMap);
>> final long[] dims = new long[ img.numDimensions() ];
>>
>> ImgLabeling< Integer, IntType > labeling = new ImgLabeling<
>> Integer, IntType >( img );
>>
>> Cursor<LabelingType<Integer>> labelCursor = labeling.cursor();
>> RandomAccess<FloatType> imageRA = img2.randomAccess();
>>
>> // Go through the whole image again and again for every single
>> label, until no more label is found.
>> // If you know a more efficient way to do this, tell me...
>> int currentLabel = 0;
>> boolean anythingFound = true;
>> while (anythingFound)
>> {
>> anythingFound = false;
>> labelCursor.reset();
>>
>> //Go through the whole image and add every pixel, that
>> belongs to the currently processed label
>> int count = 0;
>> while (labelCursor.hasNext())
>> {
>> LabelingType<Integer> element = labelCursor.next();
>> imageRA.setPosition(labelCursor);
>>
>> int i = (int)(imageRA.get().get());
>> if (i == currentLabel)
>> {
>> element.add(i);
>> anythingFound = true;
>> count ++;
>> }
>> }
>> System.out.println("Number of input pixels in label " +
>> currentLabel + ": " + count);
>> currentLabel++;
>> }
>> ImageJFunctions.show(labeling.getIndexImg());
>> return labeling;
>> }
>>
>> //Transform a Region to a binary image, which can be displayed
>> public static < T, F > Img<BitType>
>> labelRegionToBinaryImage(LabelRegion<T> region, Img<F> img)
>> {
>> final long[] pos = new long[ img.numDimensions() ];
>> final long[] dims = new long[ img.numDimensions() ];
>> img.dimensions( dims );
>>
>> final Img< BitType > newImage = ArrayImgs.bits( dims );
>>
>> RandomAccess<BitType> imageRA = newImage.randomAccess();
>> LabelRegionCursor regionCursor = region.cursor();
>>
>> int count = 0;
>> while (regionCursor.hasNext())
>> {
>> //Read yes/no from region
>> BoolType regionElement = regionCursor.next();
>> regionCursor.localize(pos);
>> imageRA.setPosition(pos);
>> BitType imageElement = imageRA.get();
>>
>> //Draw binary image pixel by pixel
>> if (regionElement.get())
>> {
>> count++;
>> imageElement.set(true);
>> }
>> else
>> {
>> imageElement.set(false);
>> }
>> }
>> System.out.println("Number of output pixels in region: " + count);
>> return newImage;
>> }
>>
>>
>>
>> //Just to run it
>> public static void main(final String... args) throws IOException
>> {
>> new LabelingExample();
>> }
>> }
>>
>>
>>
>>
>> --
>> Robert Haase
>> Bio-Image informatics, Scientific Computing Facility
>>
>> Max Planck Institute CBG
>> Pfotenhauer Str. 108, 01307 Dresden
>> room: 106 (s)
>> phone: +49 351 210 2972
>> fax: +49 351 210 1689
>>
>>
>> _______________________________________________
>> ImageJ-devel mailing list
>> ImageJ-devel at imagej.net <mailto:ImageJ-devel at imagej.net>
>> http://imagej.net/mailman/listinfo/imagej-devel
>
--
Robert Haase
Bio-Image informatics, Scientific Computing Facility
Max Planck Institute CBG
Pfotenhauer Str. 108, 01307 Dresden
room: 106 (s)
phone: +49 351 210 2972
fax: +49 351 210 1689
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://imagej.net/pipermail/imagej-devel/attachments/20150910/fc115410/attachment-0001.html>
More information about the ImageJ-devel
mailing list