Iterator over Roi points anywhere?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

Iterator over Roi points anywhere?

Burger Wilhelm
Hello all,

does anyone know of a straight way to enumerate/iterate over all points contained in an (arbitrary) Roi? That is (in Java terms), something like this:

...
Roi roi = im.getRoi();
for (Point p : roi.getContainedPoints()) {
   ... // process p
}

Any help appreciated!
--Wilhelm


--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Iterator over Roi points anywhere?

Marcel
I posted a similar solution in Jython here:

http://forum.imagej.net/t/pointroi-input-different-from-output-point-positions/1038

So you can get, e.g., points, etc., in Java with:

Roi roi = im.getRoi();
int [] xArr = roi.getPolygon().xpoints
int [] yArr = roi.getPolygon().ypoints

See:

http://javadoc.imagej.net/ImageJ1/ij/gui/PolygonRoi.html#getNCoordinates%28%29

Reply | Threaded
Open this post in threaded view
|

Re: Iterator over Roi points anywhere?

Rasband, Wayne (NIH/NIMH) [E]
In reply to this post by Burger Wilhelm
> On Apr 10, 2016, at 11:08 AM, Burger Wilhelm <[hidden email]> wrote:
>
> Hello all,
>
> does anyone know of a straight way to enumerate/iterate over all points contained in an (arbitrary) Roi? That is (in Java terms), something like this:
>
> ...
> Roi roi = im.getRoi();
> for (Point p : roi.getContainedPoints()) {
>   ... // process p
> }

Get the ROI mask and use it to determine which pixels are contained in the ROI. The following JavaScript/BeanShell code calculates the mean value of the pixels contained in the current ROI or the mean of the entire image if there is no ROI.

-wayne

  img = IJ.getImage();
  ip = img.getProcessor();
  bounds = ip.getRoi();
  mask = img.getMask();
  sum = 0;
  count = 0;
  for (y=0; y<bounds.height; y++) {
     for (x=0; x<bounds.width; x++) {
        if (mask==null||mask.getPixel(x,y)!=0) {
           count++;
           sum += ip.getf(x+bounds.x, y+bounds.y);
        }
     }
  }
  IJ.log("mean,count: "+IJ.d2s(sum/count,4)+" "+count);

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Iterator over Roi points anywhere?

Eric Barnhill
In reply to this post by Burger Wilhelm
Following up on this, does anyone have a plugin or algo to do the opposite, namely, collect a group of contiguous points into an ImageJ ROi?

Eric

Sent from [ProtonMail](https://protonmail.ch), encrypted email based in Switzerland.


----------------------------------------------------------------------

Date: Sun, 10 Apr 2016 15:08:40 +0000
From: Burger Wilhelm <[hidden email]>
Subject: Iterator over Roi points anywhere?

Hello all,

does anyone know of a straight way to enumerate/iterate over all points contained in an (arbitrary) Roi? That is (in Java terms), something like this:

...
Roi roi = im.getRoi();
for (Point p : roi.getContainedPoints()) {
... // process p
}

Any help appreciated!
--Wilhelm


--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html

------------------------------

Date: Sun, 10 Apr 2016 09:21:57 -0700
From: Bio7 <[hidden email]>
Subject: Re: Iterator over Roi points anywhere?

I posted a similar solution in Jython here:

http://forum.imagej.net/t/pointroi-input-different-from-output-point-positions/1038

So you can get, e.g., points, etc., in Java with:

Roi roi = im.getRoi();
int [] xArr = roi.getPolygon().xpoints
int [] yArr = roi.getPolygon().ypoints

See:

http://javadoc.imagej.net/ImageJ1/ij/gui/PolygonRoi.html#getNCoordinates%28%29

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Iterator over Roi points anywhere?

Burger Wilhelm
In reply to this post by Rasband, Wayne (NIH/NIMH) [E]
Thanks Wayne,

this works nicely for some types of ROIs (polygon, ellipse, freehand). However, ROIs of sub-type rectangle, line, point and multi-point do not seem to define a mask.

--Wilhelm


-----Original Message-----
From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of Rasband, Wayne (NIH/NIMH) [E]
Sent: Montag, 11. April 2016 04:48
To: [hidden email]
Subject: Re: Iterator over Roi points anywhere?

> On Apr 10, 2016, at 11:08 AM, Burger Wilhelm <[hidden email]> wrote:
>
> Hello all,
>
> does anyone know of a straight way to enumerate/iterate over all points contained in an (arbitrary) Roi? That is (in Java terms), something like this:
>
> ...
> Roi roi = im.getRoi();
> for (Point p : roi.getContainedPoints()) {
>   ... // process p
> }

Get the ROI mask and use it to determine which pixels are contained in the ROI. The following JavaScript/BeanShell code calculates the mean value of the pixels contained in the current ROI or the mean of the entire image if there is no ROI.

-wayne

  img = IJ.getImage();
  ip = img.getProcessor();
  bounds = ip.getRoi();
  mask = img.getMask();
  sum = 0;
  count = 0;
  for (y=0; y<bounds.height; y++) {
     for (x=0; x<bounds.width; x++) {
        if (mask==null||mask.getPixel(x,y)!=0) {
           count++;
           sum += ip.getf(x+bounds.x, y+bounds.y);
        }
     }
  }
  IJ.log("mean,count: "+IJ.d2s(sum/count,4)+" "+count);

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Iterator over Roi points anywhere?

Michael Schmid
Hi Wilhelm,

Wayne's code should work for rectangles. They do not have a masks - the
if (mask==null...) clause is meant for that case.

For non-area rois, I fear that it is not so easy to get all points.

For lines, you can use the 'Line to Area' command first. For Multi-Point
Rois, you can use Roi.contains, or take the detour via 'Create Mask' and
'Create Selection'.

The 'Roi.contains' method seems to be meant for this purpose, but
unfortunately it does not work with lines. An implementation to make it
work for lines would be nice (anyone out there who could do this?)

A nasty problem with Roi.contains: For polygons, the pixels reported by
'Roi.contains' and those affected by 'Fill' and are not the same. It
seems that there is a half-pixel offset in x and y between them. The
reason is that PolygonRoi.contains uses FloatPolygon.contains instead of
the mask.
(The mask, which uses the ImageJ PolygonFiller, better fits the ImageJ
conventions, i.e., it better fits what you see at high magnification).

Another small inconsistency, if someone should find time to look at
this: Both 'Fill' and 'Roi.contains' for rectangular rois with
non-integer position do not round coordinates to the nearest integer but
truncate them. For rectangles with positions like 9.99, this will cause
an operation to be almost 1 pixel off from what you see at the screen.
This seems to be a remainder from the days when ImageJ Rois could only
have integer coordinates. Nothing is perfect...

Michael
________________________________________________________________

On 2016-04-11 13:36, Burger Wilhelm wrote:

> Thanks Wayne,
>
> this works nicely for some types of ROIs (polygon, ellipse, freehand). However, ROIs of sub-type rectangle, line, point and multi-point do not seem to define a mask.
>
> --Wilhelm
>
>
> -----Original Message-----
> From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of Rasband, Wayne (NIH/NIMH) [E]
> Sent: Montag, 11. April 2016 04:48
> To: [hidden email]
> Subject: Re: Iterator over Roi points anywhere?
>
>> On Apr 10, 2016, at 11:08 AM, Burger Wilhelm <[hidden email]> wrote:
>>
>> Hello all,
>>
>> does anyone know of a straight way to enumerate/iterate over all points contained in an (arbitrary) Roi? That is (in Java terms), something like this:
>>
>> ...
>> Roi roi = im.getRoi();
>> for (Point p : roi.getContainedPoints()) {
>>    ... // process p
>> }
>
> Get the ROI mask and use it to determine which pixels are contained in the ROI. The following JavaScript/BeanShell code calculates the mean value of the pixels contained in the current ROI or the mean of the entire image if there is no ROI.
>
> -wayne
>
>    img = IJ.getImage();
>    ip = img.getProcessor();
>    bounds = ip.getRoi();
>    mask = img.getMask();
>    sum = 0;
>    count = 0;
>    for (y=0; y<bounds.height; y++) {
>       for (x=0; x<bounds.width; x++) {
>          if (mask==null||mask.getPixel(x,y)!=0) {
>             count++;
>             sum += ip.getf(x+bounds.x, y+bounds.y);
>          }
>       }
>    }
>    IJ.log("mean,count: "+IJ.d2s(sum/count,4)+" "+count);
>
> --
> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>
> --
> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Iterator over Roi points anywhere?

Burger Wilhelm
You are certainly right. Then again, multi-rectangle ROIS *do* have a mask ...
Guess to make this generic I could revert to my original plan of merging the result of painting the ROI with its mask (if provided). I also noticed that Roi.contains() may be quite slow.

Of course this will not eliminate the fill/contains discrepancies you mentioned.

Thanks,
Wilhelm


-----Original Message-----
From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of Michael Schmid
Sent: Montag, 11. April 2016 14:57
To: [hidden email]
Subject: Re: Iterator over Roi points anywhere?

Hi Wilhelm,

Wayne's code should work for rectangles. They do not have a masks - the if (mask==null...) clause is meant for that case.

For non-area rois, I fear that it is not so easy to get all points.

For lines, you can use the 'Line to Area' command first. For Multi-Point Rois, you can use Roi.contains, or take the detour via 'Create Mask' and 'Create Selection'.

The 'Roi.contains' method seems to be meant for this purpose, but unfortunately it does not work with lines. An implementation to make it work for lines would be nice (anyone out there who could do this?)

A nasty problem with Roi.contains: For polygons, the pixels reported by 'Roi.contains' and those affected by 'Fill' and are not the same. It seems that there is a half-pixel offset in x and y between them. The reason is that PolygonRoi.contains uses FloatPolygon.contains instead of the mask.
(The mask, which uses the ImageJ PolygonFiller, better fits the ImageJ conventions, i.e., it better fits what you see at high magnification).

Another small inconsistency, if someone should find time to look at
this: Both 'Fill' and 'Roi.contains' for rectangular rois with non-integer position do not round coordinates to the nearest integer but truncate them. For rectangles with positions like 9.99, this will cause an operation to be almost 1 pixel off from what you see at the screen.
This seems to be a remainder from the days when ImageJ Rois could only have integer coordinates. Nothing is perfect...

Michael
________________________________________________________________

On 2016-04-11 13:36, Burger Wilhelm wrote:

> Thanks Wayne,
>
> this works nicely for some types of ROIs (polygon, ellipse, freehand). However, ROIs of sub-type rectangle, line, point and multi-point do not seem to define a mask.
>
> --Wilhelm
>
>
> -----Original Message-----
> From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of
> Rasband, Wayne (NIH/NIMH) [E]
> Sent: Montag, 11. April 2016 04:48
> To: [hidden email]
> Subject: Re: Iterator over Roi points anywhere?
>
>> On Apr 10, 2016, at 11:08 AM, Burger Wilhelm <[hidden email]> wrote:
>>
>> Hello all,
>>
>> does anyone know of a straight way to enumerate/iterate over all points contained in an (arbitrary) Roi? That is (in Java terms), something like this:
>>
>> ...
>> Roi roi = im.getRoi();
>> for (Point p : roi.getContainedPoints()) {
>>    ... // process p
>> }
>
> Get the ROI mask and use it to determine which pixels are contained in the ROI. The following JavaScript/BeanShell code calculates the mean value of the pixels contained in the current ROI or the mean of the entire image if there is no ROI.
>
> -wayne
>
>    img = IJ.getImage();
>    ip = img.getProcessor();
>    bounds = ip.getRoi();
>    mask = img.getMask();
>    sum = 0;
>    count = 0;
>    for (y=0; y<bounds.height; y++) {
>       for (x=0; x<bounds.width; x++) {
>          if (mask==null||mask.getPixel(x,y)!=0) {
>             count++;
>             sum += ip.getf(x+bounds.x, y+bounds.y);
>          }
>       }
>    }
>    IJ.log("mean,count: "+IJ.d2s(sum/count,4)+" "+count);
>
> --
> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>
> --
> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Iterator over Roi points anywhere?

Rasband, Wayne (NIH/NIMH) [E]
In reply to this post by Burger Wilhelm
> On Apr 10, 2016, at 11:08 AM, Burger Wilhelm <[hidden email]> wrote:
>
> Hello all,
>
> does anyone know of a straight way to enumerate/iterate over all points contained in an (arbitrary) Roi? That is (in Java terms), something like this:
>
> ...
> Roi roi = im.getRoi();
> for (Point p : roi.getContainedPoints()) {
> ... // process p
> }

The latest ImageJ daily build (1.51a5) adds an Roi.getContainedPoints() method which works with arbitrary ROIs, including point and line selections. Here is example Java code that calculates the mean pixel value of the current ROI:

 ImagePlus img = IJ.getImage();
 ImageProcessor ip = img.getProcessor();
 Roi roi = img.getRoi();
 double sum=0;
 int count=0;
 for (Point p : roi.getContainedPoints()) {
    count++;
    sum += ip.getf(p.x, p.y);
 }
 IJ.log("mean,count: "+IJ.d2s(sum/count,4)+" "+count);

-wayne
--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Iterator over Roi points anywhere?

Dimitri Vanhecke
Hi,



Great question. Is there any chance there is an equally nice solution on
macro writing level? Currently I use a (time consuming) workaround by
making all pixels outside the ROI black and subtracting 1 from all pixels
in the image. Then I iterate through the bounding box of the ROI and use an
if statement to check if the value of the pixel. If -1, then we must be
outside the ROI...
A nice solution like the getcontainedpoints method would be great (and much
faster, I assume).
Kind greetings,
Dimitri Vanhecke

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Iterator over Roi points anywhere?

Burger Wilhelm
In reply to this post by Rasband, Wayne (NIH/NIMH) [E]
Awesome, works great -- thanks much, Wayne!

--Wilhelm


-----Original Message-----
From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of Rasband, Wayne (NIH/NIMH) [E]
Sent: Dienstag, 12. April 2016 03:19
To: [hidden email]
Subject: Re: Iterator over Roi points anywhere?

> On Apr 10, 2016, at 11:08 AM, Burger Wilhelm <[hidden email]> wrote:
>
> Hello all,
>
> does anyone know of a straight way to enumerate/iterate over all points contained in an (arbitrary) Roi? That is (in Java terms), something like this:
>
> ...
> Roi roi = im.getRoi();
> for (Point p : roi.getContainedPoints()) { ... // process p }

The latest ImageJ daily build (1.51a5) adds an Roi.getContainedPoints() method which works with arbitrary ROIs, including point and line selections. Here is example Java code that calculates the mean pixel value of the current ROI:

 ImagePlus img = IJ.getImage();
 ImageProcessor ip = img.getProcessor();  Roi roi = img.getRoi();  double sum=0;  int count=0;  for (Point p : roi.getContainedPoints()) {
    count++;
    sum += ip.getf(p.x, p.y);
 }
 IJ.log("mean,count: "+IJ.d2s(sum/count,4)+" "+count);

-wayne
--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Iterator over Roi points anywhere?

Rasband, Wayne (NIH/NIMH) [E]
In reply to this post by Dimitri Vanhecke
On Apr 12, 2016, at 2:17 AM, Dimitri Vanhecke <[hidden email]> wrote:
>
> Hi,
> Great question. Is there any chance there is an equally nice solution on macro writing level? Currently I use a (time consuming) workaround by making all pixels outside the ROI black and subtracting 1 from all pixels in the image. Then I iterate through the bounding box of the ROI and use an if statement to check if the value of the pixel. If -1, then we must be outside the ROI...
> A nice solution like the getcontainedpoints method would be great (and much faster, I assume).

The latest ImageJ daily build (1.51a9) adds the Roi.getContainedPoints() macro function. Here is an example macro that uses this function to calculate the mean pixel value of the current selection:


 sum=0; count=0;
  Roi.getContainedPoints(x,y);
  for (i=0; i<x.length; i++) {
     count++;
     sum += getPixel(x[i], y[i]);
  }
  print("mean,count: "+d2s(sum/count,4)+" "+count);

-wayne
--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html