[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