Generating random points and tallying proportion of points that fall within object

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

Generating random points and tallying proportion of points that fall within object

Jeremy Adler
From your description the images are effectively binary - objects black, background white
You may want to ensure they are binary by using  Process/Binary/Make binary

Checking 1000 random points is a traditional approach for finding the fraction of the image that is occupied - it asks the user to decide point by point,  it is still useful if it is hard to decide on whether the point hits an object or not.
But you have binary images, so all you need to do is find the mean intensity of each image - in the ImageJ version of binary there are two values 0 and 255.
The fraction of the image that is white (255) is simply the mean intensity of the whole image divided by 255.
The mean intensity comes from  Analyze/Measure. You can chose what is measured using Analyze/Set measurements.

To measure the 300 images,
Process/Batch/Measure   - the software asks where the file containing the images is, and then prints out the results, which you can save and import into Excel or wherever.





-----Original Message-----
From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of atawewe
Sent: den 2 juni 2014 15:55
To: [hidden email]
Subject: Generating random points and tallying proportion of points that fall within object

I have over 300 images I need to process to obtain an unbiased estimate of the proportion of each image that is occupied by the object of interest. For each image, the objects of interest are black in color, mostly spherical in shape, but range in sizes, while the background of the image is white. The challenge for me is that I need to generate 1000 random points on each image, and determine the proportion of points that fall within the objects of interest in the image. I will appreciate information on how to achieve this using imageJ. After searching online, I really couldn't find any tips on where to start from or how to go about generating random points on an image and estimating whether they fall within the object of interest or not in imageJ.  

Thanks in advance.



--
View this message in context: http://imagej.1557.x6.nabble.com/Generating-random-points-and-tallying-proportion-of-points-that-fall-within-object-tp5007986.html
Sent from the ImageJ mailing list archive at Nabble.com.

--
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: Generating random points and tallying proportion of points that fall within object

atawewe
Your points are valid, and what you describe sounds quite practical. However, I need to generate random points to get an unbiased estimate of the proportion of the image occupied by the objects of interest. I already got a solution to this bit, as another kind contributor wrote a macro for me that will generate 1000 random points. What I need to figure out now is how to include a line of code in the macro that gets the pixel value for each of those points and determine if they fall within the object of interest i.e. black or have a value of 255. As it is, my guess is that the macro is checking if the x and y coordinates equal 255 and so the output is always 0.  Any thoughts on this?

See macro below:

// START OF MACRO
// This macro assumes you have a binary image.

// Number of points to generate
n_points = 1000;


name = getTitle(); // Name of the image
getDimensions(x,y,z,c,t); // Size of the image

// Initialize arrays that will contain point coordinates
xcoords = newArray(n_points);
ycoords = newArray(n_points);

// Seed the random number generator
random('seed', getTime());

// Create n_points points in XY
for (i=0; i<n_points; i++) {
        xcoords[i] = round(random()*x);
        ycoords[i] = round(random()*y);
}

// Overlay them on the image
makeSelection("point", xcoords, ycoords);

// Count points that have a value of 255
prevRes = nResults;
run("Measure");
count = 0;

for (i=0; i<n_points;i++) {
        val = getResult("Mean",i+prevRes);
        if (val == 255) {
                count++;
        }
}

// Output to log window.
print("Image "+name+": "+count+" points out of "+n_points+" inside objects of interest");

// END OF MACRO

Reply | Threaded
Open this post in threaded view
|

Re: Generating random points and tallying proportion of points that fall within object

Kenneth Sloan
I think this point needs elaboration.

First - yes, it would be nice to get the macro right.  I’ll let someone
else debug it.

That said - why do you believe that actually measuring *all* of the pixels
enclosed in the region of interest is inferior to sampling?  Sampling is, of
course, an excellent way to proceed when the evaluation at each point is
time consuming or tedious - but is it necessary when you have access to the
actual *answer*?  One possibility, of course, is that you want to compare
against data gathered manually in other cases.

Secondarily - are you sure that random sampling is preferable to regular grid
sampling?  There is a huge literature on stereology which suggests that
sampling on a regular grid may be preferable to random sampling.  For one thing,
you avoid “clumping” (leading to highly correlated measurements) and you
must be very careful to validate the “randomness” of the pseudo-random number generator.

And finally…be *very* careful about using custom code (the PRNG, the macro, …) that
you have not tested and validated.  There is a lot of “contributed” code out there
that does not do what it claims to do.

Dart-throwing is a time-honored way to estimate areas which are difficult to measure
in any other way - BUT - in my experience, they are grossly inferior to actual
area measurements (where possible).  In this case, it seems at first glance that you
can directly measure the area of interest - so…why not do that?

In particular, if your input is a binary image where 255 == foreground and 0 == background,
then the area of the foreground is simply the mean intensity of the image (appropriately scaled
by the area covered by the image and the magic value 255).

Even if the “mean value” were not easy to extract from ImageJ, I would iterate over the
ENTIRE image and count the number of 255 pixels.  Computation is cheap - use it!
If you want “proportion of 255 pixels” then count the 255’s and count the 0’s.  

I really fail to see the need to restrict your attention to a mere 1000 “random” points.

Again - there may well be a justification, that you didn’t feel necessary to elaborate on.
That’s certainly fair.

--
Kenneth Sloan
[hidden email]
"La lutte elle-même vers les sommets suffit à remplir un coeur d'homme; il faut imaginer Sisyphe heureux."


On Jun 2, 2014, at 12:14 , atawewe <[hidden email]> wrote:

> Your points are valid, and what you describe sounds quite practical. However,
> I need to generate random points to get an unbiased estimate of the
> proportion of the image occupied by the objects of interest. I already got a
> solution to this bit, as another kind contributor wrote a macro for me that
> will generate 1000 random points. What I need to figure out now is how to
> include a line of code in the macro that gets the pixel value for each of
> those points and determine if they fall within the object of interest i.e.
> black or have a value of 255. As it is, my guess is that the macro is
> checking if the x and y coordinates equal 255 and so the output is always 0.
> Any thoughts on this?
>
> See macro below:
>
> // START OF MACRO
> // This macro assumes you have a binary image.
>
> // Number of points to generate
> n_points = 1000;
>
>
> name = getTitle(); // Name of the image
> getDimensions(x,y,z,c,t); // Size of the image
>
> // Initialize arrays that will contain point coordinates
> xcoords = newArray(n_points);
> ycoords = newArray(n_points);
>
> // Seed the random number generator
> random('seed', getTime());
>
> // Create n_points points in XY
> for (i=0; i<n_points; i++) {
>        xcoords[i] = round(random()*x);
>        ycoords[i] = round(random()*y);
> }
>
> // Overlay them on the image
> makeSelection("point", xcoords, ycoords);
>
> // Count points that have a value of 255
> prevRes = nResults;
> run("Measure");
> count = 0;
>
> for (i=0; i<n_points;i++) {
>        val = getResult("Mean",i+prevRes);
>        if (val == 255) {
>                count++;
>        }
> }
>
> // Output to log window.
> print("Image "+name+": "+count+" points out of "+n_points+" inside objects
> of interest");
>
> // END OF MACRO
>
>
>
>
>
> --
> View this message in context: http://imagej.1557.x6.nabble.com/Generating-random-points-and-tallying-proportion-of-points-that-fall-within-object-tp5007988p5007991.html
> Sent from the ImageJ mailing list archive at Nabble.com.
>
> --
> 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: Generating random points and tallying proportion of points that fall within object

Jeremy Adler
In reply to this post by atawewe
There is nothing magic about 1000 random, or even non random points.

Measuring every point (the whole image) is self evidently better than sampling a subset of the points, you don't even need to write a macro to do it.
The whole image is as unbiased as you can get, any remaining bias orignatedin how you images were acquired.





________________________________________
From: ImageJ Interest Group [[hidden email]] on behalf of atawewe [[hidden email]]
Sent: 02 June 2014 19:14
To: [hidden email]
Subject: Re: Generating random points and tallying proportion of points that fall within object

Your points are valid, and what you describe sounds quite practical. However,
I need to generate random points to get an unbiased estimate of the
proportion of the image occupied by the objects of interest. I already got a
solution to this bit, as another kind contributor wrote a macro for me that
will generate 1000 random points. What I need to figure out now is how to
include a line of code in the macro that gets the pixel value for each of
those points and determine if they fall within the object of interest i.e.
black or have a value of 255. As it is, my guess is that the macro is
checking if the x and y coordinates equal 255 and so the output is always 0.
Any thoughts on this?

See macro below:

// START OF MACRO
// This macro assumes you have a binary image.

// Number of points to generate
n_points = 1000;


name = getTitle(); // Name of the image
getDimensions(x,y,z,c,t); // Size of the image

// Initialize arrays that will contain point coordinates
xcoords = newArray(n_points);
ycoords = newArray(n_points);

// Seed the random number generator
random('seed', getTime());

// Create n_points points in XY
for (i=0; i<n_points; i++) {
        xcoords[i] = round(random()*x);
        ycoords[i] = round(random()*y);
}

// Overlay them on the image
makeSelection("point", xcoords, ycoords);

// Count points that have a value of 255
prevRes = nResults;
run("Measure");
count = 0;

for (i=0; i<n_points;i++) {
        val = getResult("Mean",i+prevRes);
        if (val == 255) {
                count++;
        }
}

// Output to log window.
print("Image "+name+": "+count+" points out of "+n_points+" inside objects
of interest");

// END OF MACRO





--
View this message in context: http://imagej.1557.x6.nabble.com/Generating-random-points-and-tallying-proportion-of-points-that-fall-within-object-tp5007988p5007991.html
Sent from the ImageJ mailing list archive at Nabble.com.

--
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: Generating random points and tallying proportion of points that fall within object

atawewe
In reply to this post by Kenneth Sloan
I guess I omitted some important information on what I am trying to do. The actual estimate of the size, counts, and proportion of image area occupied by the objects of interest will likely be biased because some of the objects of interest (vessels) are only partially included within the image. I am working with images of cross sections of wood for different species. The nature of the distribution of the vessels within an image varies depending on species, however, many of the images have vessels only partially within the image. Including or excluding these partial vessels in the actual estimates is likely to introduce bias among species that vary in their vessel sizes. Do you have any other suggestion on how I should deal with this bias due to partial vessels in the images apart from my method (random generation of points and tallying the proportion of points that fall within vessels)?  

Thanks.
Reply | Threaded
Open this post in threaded view
|

Re: Generating random points and tallying proportion of points that fall within object

Anderson, Charles (DNR)
Do some preliminary measurements to identify approximately the radius of the largest vessel likely to be encountered for each species.  Record a buffer width larger than this radius for future use.

Do the thresholding and create a mask. Run analyze particles, including particles on the edge, recording centroids as well as areas.  Use the total vessel area and the image area to calculate proportion of image area occupied.  In post-processing with a stats program or spreadsheet, delete those records whose centroid falls within the buffer width of the edge of the image. The remaining particles give the size distribution of complete particles. The count of remaining particles and the area of the central region (image area - buffered area) allow an estimate of vessels / unit area.

-----Original Message-----
From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of atawewe
Sent: Monday, June 02, 2014 5:36 PM
To: [hidden email]
Subject: Re: Generating random points and tallying proportion of points that fall within object

I guess I omitted some important information on what I am trying to do. The actual estimate of the size, counts, and proportion of image area occupied by the objects of interest will likely be biased because some of the objects of interest (vessels) are only partially included within the image. I am working with images of cross sections of wood for different species. The nature of the distribution of the vessels within an image varies depending on species, however, many of the images have vessels only partially within the image. Including or excluding these partial vessels in the actual estimates is likely to introduce bias among species that vary in their vessel sizes. Do you have any other suggestion on how I should deal with this bias due to partial vessels in the images apart from my method (random generation of points and tallying the proportion of points that fall within vessels)?  

Thanks.



--
View this message in context: http://imagej.1557.x6.nabble.com/Generating-random-points-and-tallying-proportion-of-points-that-fall-within-object-tp5007988p5007995.html
Sent from the ImageJ mailing list archive at Nabble.com.

--
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: Generating random points and tallying proportion of points that fall within object

atawewe
Please I will appreciate some more clarification on your suggestion.
1. Should the buffer width vary with species? I think so, because species vary in their vessel sizes.
2. How will vessels whose centroids fall within the buffer width of the edge of the image be determined? My first thought is that vessels with centroid values less than the buffer width should be excluded, but I am not sure this is correct.

Thanks.
Reply | Threaded
Open this post in threaded view
|

Re: Generating random points and tallying proportion of points that fall within object

Anderson, Charles (DNR)
Yes, buffer size could vary among species. There is nothing gained by making the buffer much larger than necessary.

Use a stats program or a spreadsheet to delete records if the centroid falls near the edge. As a toy example, say the image is 256 by 256 pixels, and the buffer width is to be 10 pixels.  The X and Y values of the image will range from 0 to 255.  If the centroid X is < 10 or > 245, delete. If the centroid Y is < 10 or > 245, delete.  Those data editing steps are routine in any stats or spreadsheet program, and you doing additional statistical / graphical analyses of variation among images and among species anyway.

-----Original Message-----
From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of atawewe
Sent: Tuesday, June 03, 2014 3:31 PM
To: [hidden email]
Subject: Re: Generating random points and tallying proportion of points that fall within object

Please I will appreciate some more clarification on your suggestion.
1. Should the buffer width vary with species? I think so, because species vary in their vessel sizes.
2. How will vessels whose centroids fall within the buffer width of the edge of the image be determined? My first thought is that vessels with centroid values less than the buffer width should be excluded, but I am not sure this is correct.

Thanks.



--
View this message in context: http://imagej.1557.x6.nabble.com/Generating-random-points-and-tallying-proportion-of-points-that-fall-within-object-tp5007988p5008005.html
Sent from the ImageJ mailing list archive at Nabble.com.

--
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: Generating random points and tallying proportion of points that fall within object

atawewe
Thanks for the explanation! I am on it now, and will provide updates soon.