Issue with Polygons in Ops

Hi guys,

I’m having an issue with Polygons in Ops. I would like to measure the perimeter of an ROI, but Ops crashes or delivers strange results. Hopefully one of you can help. Here ist the code:

If I run it, I get this error message:

java.lang.AssertionError
    at net.imglib2.roi.util.ROIUtils.getBoundsReal(ROIUtils.java:98)
    at net.imglib2.roi.geometric.Polygon.<init>(Polygon.java:63)
    at net.imagej.ops.geom.geom2d.DefaultConvexHull2D.compute1(DefaultConvexHull2D.java:121)
    at net.imagej.ops.geom.geom2d.DefaultConvexHull2D.compute1(DefaultConvexHull2D.java:51)
    at net.imagej.ops.geom.geom2d.BoundaryPixelCountConvexHullPolygon.compute1(BoundaryPixelCountConvexHullPolygon.java:63)
    at net.imagej.ops.geom.geom2d.BoundaryPixelCountConvexHullPolygon.compute1(BoundaryPixelCountConvexHullPolygon.java:46)
    at net.imagej.ops.special.hybrid.UnaryHybridCF.compute1(UnaryHybridCF.java:62)
    at net.imagej.ops.special.hybrid.UnaryHybridCF.run(UnaryHybridCF.java:72)
    at net.imagej.ops.special.hybrid.UnaryHybridCF.run(UnaryHybridCF.java:98)
    at org.scijava.command.CommandModule.run(CommandModule.java:205)
    at net.imagej.ops.OpEnvironment.run(OpEnvironment.java:940)
    at net.imagej.ops.OpEnvironment.run(OpEnvironment.java:157)
    at net.imagej.ops.geom.GeomNamespace.boundaryPixelCountConvexHull(GeomNamespace.java:85)
    at de.mpicbg.scf.labelhandling.OpsPolygonTest.testOpsPolygonGeneration(OpsPolygonTest.java:64)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Furthermore, if I replace the input image at line 44

Img<FloatType> testImage = getNDimensionalTestImage(2, 20, 10, 4);

with line 45 (a larger image with a larger circle ):

Img<FloatType> testImage = getNDimensionalTestImage(2, 100, 25, 10);

I get: this output:

                     #########                                                                      
                    ###########                                                                     
                  ###############                                                                   
                  ###############                                                                   
                 #################                                                                  
                ###################                                                                 
                ###################                                                                 
                ###################                                                                 
                ###################                                                                 
                ###################                                                                 
                ###################                                                                 
                ###################                                                                 
                ###################                                                                 
                ###################                                                                 
                 #################                                                                  
                  ###############                                                                   
                  ###############                                                                   
                    ###########                                                                     
                     #########     
   
perimeter: 3.0

I wonder why, this circles convex hull appears to have three pixels… Or what is wrong with my input image…

Thanks in advance!
Robert

1 Like

@tibuch can you have a look?

What is the failing assertion?

java.lang.AssertionError
    at net.imglib2.roi.util.ROIUtils.getBoundsReal(ROIUtils.java:98):

Hi @haesleinhuepf

I guess I found something:

  1. I created a LabelRegion from the foreground-pixels of the testImage by adding this line of code to getIntIntImgLabellingFromLabelMapImg:
    return new LabelRegions<>(labeling).getLabelRegion(1);

  2. Updated test:

@Test
    public void testOpsPolygonGeneration()
    {
        OpService ops = new Context(OpService.class, OpMatchingService.class).getService(OpService.class);

        // create test image:
        // 2 dimensions
        // 20x20 in size
        // circle positioned at 10x10
        // circle radius 4
        Img<FloatType> testImage = getNDimensionalTestImage(2, 20, 10, 4);
        //Img<FloatType> testImage = getNDimensionalTestImage(2, 100, 25, 10);
        final long[] dims = new long[testImage.numDimensions()];
        testImage.dimensions(dims);

        // print test image on console
        System.out.println(ops.image().ascii(testImage));
        
        LabelRegion<Integer> labeling = getIntIntImgLabellingFromLabelMapImg(testImage);

        // get its polygon
        Polygon polygon = ops.geom().contour(labeling, true, true);

        // analyse polygon
        DoubleType measure = ops.geom().boundaryPixelCountConvexHull(polygon);
        System.out.println("perimeter: " + ops.geom().boundarySize(polygon));
        System.out.println("number of pixel: " + measure.get());

    }

As far as I understand the contour code, we have to call it with (Polygon, true, true) because we only have foreground pixels in our LabelRegion. The parameter description is probably misleading.

The boundaryPixelCountConvexHull-Op just counts the number of pixels needed to describe this convex hull. The boundarySize-Op should return the perimeter.

Maybe it would be a good idea to add some method called perimeter (2D) and surface area (3D) to the geom namespace.

1 Like

Actually, it’s just the last parameter (isInverted) of the contour function, which must be true in my case. So, the documentation probably just needs to be updated. And maybe the variable “isInverted” could be renamed to something more meaningful.

Thank you all for your support!

Cheers,
Robert

Hey @dietzc @tibuch,

its me again having a bit trouble with ops. I updated the the repository linked in the first post. I’m trying to get the centroid of the polygon. The issue this time is, that the centroid of the polygon and the centroid of the LabelRegion are way too different.

This is the interesting code snipped:

// get its polygon
Polygon polygon = ops.geom().contour(roi, true, true);

// analyse polygon
RealLocalizable point2 = ops.geom().centroid(Views.iterable(roi));
System.out.println("centroid region:  " + point2);
RealLocalizable point = ops.geom().centroid(polygon);
System.out.println("centroid polygon: " + point);

And this is the corresponding output:

centroid region: (100.0,100.0)
centroid of polygon: (121.56823671497584,120.66485507246377)

The first line is obviously right, but do you have any idea, why the second line is soo wrong?
I also observed a similar issue when measuring the size of the region and the polygon…

Any hints are welcome! Thank you in advance. :slight_smile:

Cheers,
Robert

1 Like

Hi again,

I think, I found the bug myself. If filed a pull request on github:

Cheers,
Robert

2 Likes