Plugin - assigning roi measurements to a variable

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

Plugin - assigning roi measurements to a variable

dplatten
I'm sure that this is straightforward, but I am new to Java and writing
ImageJ plugins. I would be extremely grateful for a little help.

I have written a macro that creates a signal-to-noise map of the open image
(see the bottom of this message). I am a medical physicist working in a
hospital - this routine is useful for checking the response of digital x-ray
detectors. However, I'd like to use it with 10x10 pixel samples, but this
takes ages. I have therefore started to translate the macro into a plugin.
This is where I am having trouble. I need to assign the std_dev measured in
an roi to a variable. An example of how to do this would be great. I want to
avoid displaying and updating the results table if possible. Here's a
(non-working) code snippet:

ip.setRoi(x, y, sub_sample_size, sub_sample_size);
Analyzer ana = new Analyzer();
int measurements = Analyzer.getMeasurements();
measurements = (ana.STD_DEV);
IJ.write(Integer.toString(measurements));

This just returns the value 4.

Many thanks for any help,

David Platten
Clinical Scientist
Northampton General Hospital
Billing Road
Northampton NN1 5BD
tel +44 (0)1604 54 4369


//-----------------------------------------------------------
macro "Signal to noise map" {
  // Calculates the signal to noise of sub-samples
  // over an image.
  // Displays the results as a new image.
  // SNR taken as mean pixel value in ROI divided
  // by standard deviation in the region.
  // David Platten, July 2007

  // Ask the user for the size of the sub-samples.
  Dialog.create("Signal to noise image");
  Dialog.addMessage("Click OK to analyze, or cancel to exit (!).");
  Dialog.addNumber("Sub-sample size:", 50);
  Dialog.show();
  sub_sample_size = Dialog.getNumber();

  // Find the dimensions of the image and then
  // determine the number of sub-samples that
  // will go into it.
  width = getWidth;
  height = getHeight;
  i_max = floor(width/sub_sample_size) + 1;
  j_max = floor(height/sub_sample_size) + 1;

  // Create an array to hold the results
  results = newArray(i_max * j_max);

  // Loop through the image, stepping through in
  // increments equal to the sub-sample size.
  i = 0;
  j = 0;
  max_snr = 0; // Used to scale the results image

  for(x=0; x<width; x+=sub_sample_size) {
    j = 0;
    for(y=0; y<height; y+=sub_sample_size) {
      // Specify the width, height and position of the ROI, then
      // measure the standard deviation and mean within it.
      // SNR is calculated as mean / standard deviation and
      // written into the appropriate element of the results array.
      run("Specify...", "width="+sub_sample_size+"
height="+sub_sample_size+" x="+x+" y="+y);
      run("Set Measurements...", "mean standard decimal=5");
      run("Measure");

      mean = getResult("Mean", nResults-1);
      stdev = getResult("StdDev", nResults-1);

      results[i + (j*i_max)] = mean / stdev;
               
      // Check to see if this is a new maximum snr. This is
      // used to scale the results at the end.
      if(results[i + (j*i_max)] > max_snr) max_snr = results[i + (j*i_max)];

      j++;
    }
    i ++;
  }

  // Create new image to display the results.
  // At the moment this is an 8-bit image, 256 shades of grey.
  image_title = "SNR, " + sub_sample_size + " pixel sub-samples";
  newImage(image_title, "8-bit Black", i_max, j_max, 1);

  // Step through the results array, scaling the values using
  // the known maximum figure and then allocating the value to
  // the appropriate pixel.
  for(i=0;i<i_max; i++) {
    for(j=0;j<j_max; j++) {
      temp = round(results[i + (j*i_max)] / max_snr * 256);
      setPixel(i, j, temp);
    }
  }

  // Resize the results image to have the same dimensions
  // as the original and then enhance the contrast (an
  // auto window and level).
  run("Size...", "width="+width+" height="+height+" constrain");
  run("Enhance Contrast", "saturated=0.5");
}
//-----------------------------------------------------------
Reply | Threaded
Open this post in threaded view
|

Re: Plugin - assigning roi measurements to a variable

Volker Baecker
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,
try something like this:

image.setRoi(x, y, sub_sample_size, sub_sample_size);
ResultsTable measurements = new ResultsTable();
Analyzer analyzer = new Analyzer(image,
                                 Measurements.STD_DEV, measurements);
analyzer.run(image.getProcessor());
double stdDev = measurements.getValue(ResultsTable.STD_DEV, 0);
System.out.println(stdDev);

The 4 you get is just the constant STD_DEV that is used to specify which
measurements you want, not the result of a measurement.
Volker

> ip.setRoi(x, y, sub_sample_size, sub_sample_size);
> Analyzer ana = new Analyzer();
> int measurements = Analyzer.getMeasurements();
> measurements = (ana.STD_DEV);
> IJ.write(Integer.toString(measurements));
>
> This just returns the value 4.
>
> Many thanks for any help,
>
> David Platten
> Clinical Scientist
> Northampton General Hospital
> Billing Road
> Northampton NN1 5BD
> tel +44 (0)1604 54 4369
>
>
> //-----------------------------------------------------------
> macro "Signal to noise map" {
>   // Calculates the signal to noise of sub-samples
>   // over an image.
>   // Displays the results as a new image.
>   // SNR taken as mean pixel value in ROI divided
>   // by standard deviation in the region.
>   // David Platten, July 2007
>
>   // Ask the user for the size of the sub-samples.
>   Dialog.create("Signal to noise image");
>   Dialog.addMessage("Click OK to analyze, or cancel to exit (!).");
>   Dialog.addNumber("Sub-sample size:", 50);
>   Dialog.show();
>   sub_sample_size = Dialog.getNumber();
>
>   // Find the dimensions of the image and then
>   // determine the number of sub-samples that
>   // will go into it.
>   width = getWidth;
>   height = getHeight;
>   i_max = floor(width/sub_sample_size) + 1;
>   j_max = floor(height/sub_sample_size) + 1;
>
>   // Create an array to hold the results
>   results = newArray(i_max * j_max);
>
>   // Loop through the image, stepping through in
>   // increments equal to the sub-sample size.
>   i = 0;
>   j = 0;
>   max_snr = 0; // Used to scale the results image
>
>   for(x=0; x<width; x+=sub_sample_size) {
>     j = 0;
>     for(y=0; y<height; y+=sub_sample_size) {
>       // Specify the width, height and position of the ROI, then
>       // measure the standard deviation and mean within it.
>       // SNR is calculated as mean / standard deviation and
>       // written into the appropriate element of the results array.
>       run("Specify...", "width="+sub_sample_size+"
> height="+sub_sample_size+" x="+x+" y="+y);
>       run("Set Measurements...", "mean standard decimal=5");
>       run("Measure");
>
>       mean = getResult("Mean", nResults-1);
>       stdev = getResult("StdDev", nResults-1);
>
>       results[i + (j*i_max)] = mean / stdev;
>
>       // Check to see if this is a new maximum snr. This is
>       // used to scale the results at the end.
>       if(results[i + (j*i_max)] > max_snr) max_snr = results[i + (j*i_max)];
>
>       j++;
>     }
>     i ++;
>   }
>
>   // Create new image to display the results.
>   // At the moment this is an 8-bit image, 256 shades of grey.
>   image_title = "SNR, " + sub_sample_size + " pixel sub-samples";
>   newImage(image_title, "8-bit Black", i_max, j_max, 1);
>
>   // Step through the results array, scaling the values using
>   // the known maximum figure and then allocating the value to
>   // the appropriate pixel.
>   for(i=0;i<i_max; i++) {
>     for(j=0;j<j_max; j++) {
>       temp = round(results[i + (j*i_max)] / max_snr * 256);
>       setPixel(i, j, temp);
>     }
>   }
>
>   // Resize the results image to have the same dimensions
>   // as the original and then enhance the contrast (an
>   // auto window and level).
>   run("Size...", "width="+width+" height="+height+" constrain");
>   run("Enhance Contrast", "saturated=0.5");
> }
> //-----------------------------------------------------------
>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFGlJtTxZKX7A/4oMERAp9IAJ9na74BMeUR4y8rX54vHOPlVMMgoQCePzUU
JIymQSFCGAmt2J7z0NhW+WQ=
=Y3TZ
-----END PGP SIGNATURE-----

--
passerelle antivirus du campus CNRS de Montpellier
--
Reply | Threaded
Open this post in threaded view
|

Re: Plugin - assigning roi measurements to a variable

Michael Schmid
In reply to this post by dplatten
Hi David,

you can use the Process/Filters/Variance command, it gives
the average mean square deviation of a circular surrounding with
a given radius. For the size of the surrounding, see
Process/Filters/Show Circular Mask. It is best to convert the
image to float (32 bit) before, otherwise you may reach
saturation.
For the standard deviation, calculate the square root of the
variance, and maybe multiply by sqrt(n/(n-1)) (see Process/Math).

Process/Filters/Mean gives the average, then you can use
Process/Image Calculator to get the result (again, you should
use 32-bit images).

Since version 1.38u, Process/Filters/Mean and Variance uses
an algorithm that is faster than summing over all pixels in
the surrounding, so even if you do everything in a macro, it
should be quite fast.

Michael
________________________________________________________________

On 11 Jul 2007, at 09:52, David Platten wrote:

> I'm sure that this is straightforward, but I am new to Java and  
> writing
> ImageJ plugins. I would be extremely grateful for a little help.
>
> I have written a macro that creates a signal-to-noise map of the  
> open image
> (see the bottom of this message). I am a medical physicist working  
> in a
> hospital - this routine is useful for checking the response of  
> digital x-ray
> detectors. However, I'd like to use it with 10x10 pixel samples,  
> but this
> takes ages. I have therefore started to translate the macro into a  
> plugin.
> This is where I am having trouble. I need to assign the std_dev  
> measured in
> an roi to a variable. An example of how to do this would be great.  
> I want to
> avoid displaying and updating the results table if possible. Here's a
> (non-working) code snippet:
>
> ip.setRoi(x, y, sub_sample_size, sub_sample_size);
> Analyzer ana = new Analyzer();
> int measurements = Analyzer.getMeasurements();
> measurements = (ana.STD_DEV);
> IJ.write(Integer.toString(measurements));
>
> This just returns the value 4.
>
> Many thanks for any help,
>
> David Platten
> Clinical Scientist
> Northampton General Hospital
> Billing Road
> Northampton NN1 5BD
> tel +44 (0)1604 54 4369
>
>
> //-----------------------------------------------------------
> macro "Signal to noise map" {
>   // Calculates the signal to noise of sub-samples
>   // over an image.
>   // Displays the results as a new image.
>   // SNR taken as mean pixel value in ROI divided
>   // by standard deviation in the region.
>   // David Platten, July 2007
>
>   // Ask the user for the size of the sub-samples.
>   Dialog.create("Signal to noise image");
>   Dialog.addMessage("Click OK to analyze, or cancel to exit (!).");
>   Dialog.addNumber("Sub-sample size:", 50);
>   Dialog.show();
>   sub_sample_size = Dialog.getNumber();
>
>   // Find the dimensions of the image and then
>   // determine the number of sub-samples that
>   // will go into it.
>   width = getWidth;
>   height = getHeight;
>   i_max = floor(width/sub_sample_size) + 1;
>   j_max = floor(height/sub_sample_size) + 1;
>
>   // Create an array to hold the results
>   results = newArray(i_max * j_max);
>
>   // Loop through the image, stepping through in
>   // increments equal to the sub-sample size.
>   i = 0;
>   j = 0;
>   max_snr = 0; // Used to scale the results image
>
>   for(x=0; x<width; x+=sub_sample_size) {
>     j = 0;
>     for(y=0; y<height; y+=sub_sample_size) {
>       // Specify the width, height and position of the ROI, then
>       // measure the standard deviation and mean within it.
>       // SNR is calculated as mean / standard deviation and
>       // written into the appropriate element of the results array.
>       run("Specify...", "width="+sub_sample_size+"
> height="+sub_sample_size+" x="+x+" y="+y);
>       run("Set Measurements...", "mean standard decimal=5");
>       run("Measure");
>
>       mean = getResult("Mean", nResults-1);
>       stdev = getResult("StdDev", nResults-1);
>
>       results[i + (j*i_max)] = mean / stdev;
>
>       // Check to see if this is a new maximum snr. This is
>       // used to scale the results at the end.
>       if(results[i + (j*i_max)] > max_snr) max_snr = results[i +  
> (j*i_max)];
>
>       j++;
>     }
>     i ++;
>   }
>
>   // Create new image to display the results.
>   // At the moment this is an 8-bit image, 256 shades of grey.
>   image_title = "SNR, " + sub_sample_size + " pixel sub-samples";
>   newImage(image_title, "8-bit Black", i_max, j_max, 1);
>
>   // Step through the results array, scaling the values using
>   // the known maximum figure and then allocating the value to
>   // the appropriate pixel.
>   for(i=0;i<i_max; i++) {
>     for(j=0;j<j_max; j++) {
>       temp = round(results[i + (j*i_max)] / max_snr * 256);
>       setPixel(i, j, temp);
>     }
>   }
>
>   // Resize the results image to have the same dimensions
>   // as the original and then enhance the contrast (an
>   // auto window and level).
>   run("Size...", "width="+width+" height="+height+" constrain");
>   run("Enhance Contrast", "saturated=0.5");
> }
> //-----------------------------------------------------------
Reply | Threaded
Open this post in threaded view
|

Re: Plugin - assigning roi measurements to a variable

Gabriel Landini
In reply to this post by dplatten
On Wednesday 11 July 2007 08:52:24 David Platten wrote:

> I have written a macro that creates a signal-to-noise map of the open image
> (see the bottom of this message). I am a medical physicist working in a
> hospital - this routine is useful for checking the response of digital
> x-ray detectors. However, I'd like to use it with 10x10 pixel samples, but
> this takes ages.

I would do this differently because your method spends a lot of time in
setting ROIs and getting the mean and stdvev from it.

You can speed this up quite dramatically just by using the convolution filters
for mean and variance (and get the sd by applying the sqrt of it):
Here is the macro for a kernel of radius=5 (diameter=11) that calcuates the
SNR as mean/sd:

run("Lena (68K)");
setBatchMode(true);
run("Duplicate...", "title=lena-mean");
run("32-bit");
run("Duplicate...", "title=lena-sd");
selectWindow("lena-mean");
run("Mean...", "radius=5");
selectWindow("lena-sd");
run("Variance...", "radius=5");
run("Square Root");
imageCalculator("Divide create 32-bit", "lena-mean","lena-sd");
rename("SNR");
setBatchMode(false);

Now you can find the maximum of the SNR image (by filtering with a Maximum
filter) and subsample the image if you need to do a low resolution map.
I would have thought that have this image is more informative that having
non-overlapping ROIs, but perhaps you have some reason to do it that way.

I hope it helps.

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

Re: Plugin - assigning roi measurements to a variable

dplatten
In reply to this post by dplatten
Many thanks for your help with this. I now have the plugin working and it
runs around 15x faster than the equivalent macro.

Thanks again,

David