Accessing image stacks

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

Accessing image stacks

Alexandre Santos Abreu
Hello!

I have a problem in writing a filter plugin which should operate on an  
image stack and give me another stack as an output.

First I want to get access to the gray values of a stack opened in ImageJ  
but I don't know how to do this. After some operations I want to define an  
array for every slice of the output stack. I want to use this array to  
generate the slices of the output stack like in the following example:

ImageStack Stapel = new ImageStack(w,h);

ByteProcessor ipStack = new ByteProcessor(w,h);
for (int i=0; i<w; i++) {
        for (int j=0; j<h; j++) {
                ipStack.putPixel(i,j, ARRAY[h*i+j]);
        }
}
Stapel.addSlice("Thresholded image",ipStack);


ImagePlus impStack = new ImagePlus("Clustered stack",Stapel);
impStack.setStack(null,Stapel);
impStack.show();

Can anybody help me with accessing the pixel values of the original stack?

Thanks Alex

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

Re: Accessing image stacks

Michael Schmid
Hi Alex,

if you a stack with have 8-bit data (say named originalStapel), you can use

    /** Returns the pixel array for the specified slice, were 1<=n<=nslices. */
    byte[] pixelsArray = (byte[])originalStapel.getPixels(n);

This gives access to the array of pixels in slice n of the stack 'originalStapel'
Note that you have to convert the bytes to int if you want to do any processing on them:
    int pixelValue = pixelsArray[x+y*width] & 255;

If you want the slice of 'originalStapel' as ImageProcessor, to extract pixels at (x,y), you can use this:
    /** Returns an ImageProcessor for the specified slice, were 1<=n<=nslices. */
    /*Returns null if the stack is empty.    */
    ImageProcessor originalStapelSchicht = originalStapel.getProcessor(int n);


By the way, if the ARRAY in your code has already the correct size and type (byte) for the stack slice, you can also replace your code by
    /** assumes that you won't modify ARRAY any more: */
    ByteProcessor ipOfSlice = new ByteProcessor(w, h, ARRAY);
or you can use (if ARRAY is a byte array)
    ByteProcessor ipOfSlice = new ByteProcessor(w,h);
    byte[] pixels = (byte[])ipOfSlice.getPixels();
    System.arraycopy(ARRAY, 0, pixels, 0, pixels.length);
or
    ByteProcessor ipOfSlice = new ByteProcessor(w,h);
    byte[] pixels = (byte[])ipOfSlice.getPixels();
    for (int i; i<pixels.length; i++)
        pixels[i] = ARRAY[i];



Michael
________________________________________________________________
On Jan 9, 2013, at 12:45, Alexandre Santos Abreu wrote:

> Hello!
>
> I have a problem in writing a filter plugin which should operate on an image stack and give me another stack as an output.
>
> First I want to get access to the gray values of a stack opened in ImageJ but I don't know how to do this. After some operations I want to define an array for every slice of the output stack. I want to use this array to generate the slices of the output stack like in the following example:
>
> ImageStack Stapel = new ImageStack(w,h);
>
> ByteProcessor ipStack = new ByteProcessor(w,h);
> for (int i=0; i<w; i++) {
> for (int j=0; j<h; j++) {
> ipStack.putPixel(i,j, ARRAY[h*i+j]);
> }
> }
> Stapel.addSlice("Thresholded image",ipStack);
>
>
> ImagePlus impStack = new ImagePlus("Clustered stack",Stapel);
> impStack.setStack(null,Stapel);
> impStack.show();
>
> Can anybody help me with accessing the pixel values of the original stack?
>
> Thanks Alex

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

Re: Accessing image stacks

Alexandre Santos Abreu
In reply to this post by Alexandre Santos Abreu
Hello Michael,

I learned that I can use the voxel data. So i wrote the following code  
just to check if it wors in principle:

        public void run(ImageProcessor ip) {
               
               
                ImagePlus imp = IJ.getImage();
                ImageStack stack = imp.getStack();
                int w = stack.getWidth();
                int h = stack.getHeight();
                int zMax = stack.getSize();
                ImageStack NewStack = new ImageStack(w,h,zMax);
                NewStack = stack;
                double gray;
                ImageStack Stapel = new ImageStack(w,h);
                double [] SliceX = new double [w*h];
               
                for (int z=0; z<zMax; z++) {
                        for (int i=0; i<w; i++) {
                                for (int j=0; j<h; j++) {
                                        gray = stack.getVoxel(i,j,z);
                                        NewStack.setVoxel(i,j,z,Math.round(gray/2));
                                }
                        }
                }
               
                ImagePlus impStack = new ImagePlus("Clustered stack",NewStack);
                impStack.setStack(null,NewStack);
                impStack.show();
        }

I meant the plugin to do the following. Read an open stack. Divide all  
gray values by two. Give a new stack as output which exhibits the  
calculated gray values.

In principle this works, but the input stack is altered, though I want it  
to stay as it was.

Where lies my mistake?

Thanks a lot for your help!

Alex




Am 09.01.2013, 15:20 Uhr, schrieb Michael Epping <[hidden email]>:

> Hello Alex,
>
> i think your problem is that the PluginFilter Interface is designed to  
> perform an operation for each slice of a stacks. That is why the  
> ImageProcessor ip at the run() method is useless for you.
>
> But the original stack can be accessed by using die ImagePlus imp at the  
> setup() method. Just use "stack=imp.getStack()" where "ImageStack stack"  
> is a field of you plugin-class.
>
> At the run() method you can use the stack for your calculations. Michael  
> Schmid already wrote how to do that.
>
> Michael
>
> Am 09.01.2013 12:45, schrieb Alexandre Santos Abreu:
>> Hello!
>>
>> I have a problem in writing a filter plugin which should operate on an
>> image stack and give me another stack as an output.
>>
>> First I want to get access to the gray values of a stack opened in
>> ImageJ but I don't know how to do this. After some operations I want to
>> define an array for every slice of the output stack. I want to use this
>> array to generate the slices of the output stack like in the following
>> example:
>>
>> ImageStack Stapel = new ImageStack(w,h);
>>
>> ByteProcessor ipStack = new ByteProcessor(w,h);
>> for (int i=0; i<w; i++) {
>>      for (int j=0; j<h; j++) {
>>          ipStack.putPixel(i,j, ARRAY[h*i+j]);
>>      }
>> }
>> Stapel.addSlice("Thresholded image",ipStack);
>>
>>
>> ImagePlus impStack = new ImagePlus("Clustered stack",Stapel);
>> impStack.setStack(null,Stapel);
>> impStack.show();
>>
>> Can anybody help me with accessing the pixel values of the original  
>> stack?
>>
>> Thanks Alex
>>
>> --
>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>
> --
> ImageJ mailing list: http://imagej.nih.gov/ij/list.html


--
Universität Augsburg
Institut für Physik
Lehrstuhl für Experimentalphysik II
Universitätsstr. 1
86159 Augsburg

Tel.: 0821 598 3453
Fax: 0821 598 3411
e-mail: [hidden email]

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

Re: Accessing image stacks

Rasband, Wayne (NIH/NIMH) [E]
On Jan 9, 2013, at 11:32 AM, Alexandre Santos Abreu wrote:

> Hello Michael,
>
> I learned that I can use the voxel data. So i wrote the following code  
> just to check if it wors in principle:

Here is a plugin that duplicates an existing stack and divides the pixel values by 2.

import ij.*;
import ij.process.*;
import ij.plugin.*;

   public class My_Plugin implements PlugIn {

      public void run(String arg) {
         ImagePlus imp = IJ.getImage();
         ImagePlus imp2 = new Duplicator().run(imp);
         ImageStack stack2 = imp2.getStack();
         int w = stack2.getWidth();
         int h = stack2.getHeight();
         int d = stack2.getSize();
         for (int z=0; z<d; z++) {
            for (int y=0; y<h; y++) {
               for (int x=0; x<w; x++) {
                  double gray = stack2.getVoxel(x,y,z);
                  stack2.setVoxel(x,y,z,gray/2);
               }
            }
         }
         imp2.show();
      }

   }



> public void run(ImageProcessor ip) {
>
>
> ImagePlus imp = IJ.getImage();
> ImageStack stack = imp.getStack();
> int w = stack.getWidth();
> int h = stack.getHeight();
> int zMax = stack.getSize();
> ImageStack NewStack = new ImageStack(w,h,zMax);
> NewStack = stack;
> double gray;
> ImageStack Stapel = new ImageStack(w,h);
> double [] SliceX = new double [w*h];
>
> for (int z=0; z<zMax; z++) {
> for (int i=0; i<w; i++) {
> for (int j=0; j<h; j++) {
> gray = stack.getVoxel(i,j,z);
> NewStack.setVoxel(i,j,z,Math.round(gray/2));
> }
> }
> }
>
> ImagePlus impStack = new ImagePlus("Clustered stack",NewStack);
> impStack.setStack(null,NewStack);
> impStack.show();
> }
>
> I meant the plugin to do the following. Read an open stack. Divide all  
> gray values by two. Give a new stack as output which exhibits the  
> calculated gray values.
>
> In principle this works, but the input stack is altered, though I want it  
> to stay as it was.
>
> Where lies my mistake?
>
> Thanks a lot for your help!
>
> Alex
>
>
>
>
> Am 09.01.2013, 15:20 Uhr, schrieb Michael Epping <[hidden email]>:
>
>> Hello Alex,
>>
>> i think your problem is that the PluginFilter Interface is designed to  
>> perform an operation for each slice of a stacks. That is why the  
>> ImageProcessor ip at the run() method is useless for you.
>>
>> But the original stack can be accessed by using die ImagePlus imp at the  
>> setup() method. Just use "stack=imp.getStack()" where "ImageStack stack"  
>> is a field of you plugin-class.
>>
>> At the run() method you can use the stack for your calculations. Michael  
>> Schmid already wrote how to do that.
>>
>> Michael
>>
>> Am 09.01.2013 12:45, schrieb Alexandre Santos Abreu:
>>> Hello!
>>>
>>> I have a problem in writing a filter plugin which should operate on an
>>> image stack and give me another stack as an output.
>>>
>>> First I want to get access to the gray values of a stack opened in
>>> ImageJ but I don't know how to do this. After some operations I want to
>>> define an array for every slice of the output stack. I want to use this
>>> array to generate the slices of the output stack like in the following
>>> example:
>>>
>>> ImageStack Stapel = new ImageStack(w,h);
>>>
>>> ByteProcessor ipStack = new ByteProcessor(w,h);
>>> for (int i=0; i<w; i++) {
>>>     for (int j=0; j<h; j++) {
>>>         ipStack.putPixel(i,j, ARRAY[h*i+j]);
>>>     }
>>> }
>>> Stapel.addSlice("Thresholded image",ipStack);
>>>
>>>
>>> ImagePlus impStack = new ImagePlus("Clustered stack",Stapel);
>>> impStack.setStack(null,Stapel);
>>> impStack.show();
>>>
>>> Can anybody help me with accessing the pixel values of the original  
>>> stack?
>>>
>>> Thanks Alex
>>>
>>> --
>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>>
>> --
>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>
>
> --
> Universität Augsburg
> Institut für Physik
> Lehrstuhl für Experimentalphysik II
> Universitätsstr. 1
> 86159 Augsburg
>
> Tel.: 0821 598 3453
> Fax: 0821 598 3411
> e-mail: [hidden email]
>
> --
> 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: Accessing image stacks

Michael Schmid
In reply to this post by Alexandre Santos Abreu
Hi Alex,

if you write 'NewStack = stack' you assign the pointer (Object reference) to NewStack. The old stack created with 'new ImageStack(w,h,zMax)' will have no reference to it and eventually it gets discarded by the Garbage Collector.

The easiest way to duplicate a stack is
  ij.plugin.Duplicator.run(ImagePlus imp, int firstC, int lastC, int firstZ, int lastZ, int firstT, int lastT)
It needs an ImagePlus with the stack; if you don't have one create one using new ImagePlus(title, stack).
You need the dimensions of the image; you can get these with 'getDimensions' of the ImagePlus; it returns an array with
        d[0] = width;
        d[1] = height;
        d[2] = nChannels;
        d[3] = nSlices;
        d[4] = nFrames;
So, lastC should be d[2], lastZ should be d[3] and lastT should be d[4], and all the 'first?' variables should be 1.

If you don't want the overhead of an ImagePlus, simply loop over all slices, for each slice create a new byte array, set the values, and use ImageStack.addSlice.
Roughly like this (I have not tried it):

  ImageStack newStack = new ImageStack(width, height);
  for (int n=1; n<= nChannels; n++) {
    byte[] origPixels = (byte[])origStack.getPixels(n);
    byte[] newPixels = new byte[origPixels.length];
    for (int i=0; i<origPixels.length; i++)
      newPixels[i] = (byte)((origPixels[i] & 255) / 2);
    newStack.addSlice(origStack.getSliceLabel(n), newPixels);
  }

Michael
________________________________________________________________
On Jan 9, 2013, at 17:32, Alexandre Santos Abreu wrote:

> Hello Michael,
>
> I learned that I can use the voxel data. So i wrote the following code just to check if it wors in principle:
>
> public void run(ImageProcessor ip) {
>
>
> ImagePlus imp = IJ.getImage();
> ImageStack stack = imp.getStack();
> int w = stack.getWidth();
> int h = stack.getHeight();
> int zMax = stack.getSize();
> ImageStack NewStack = new ImageStack(w,h,zMax);
> NewStack = stack;
> double gray;
> ImageStack Stapel = new ImageStack(w,h);
> double [] SliceX = new double [w*h];
>
> for (int z=0; z<zMax; z++) {
> for (int i=0; i<w; i++) {
> for (int j=0; j<h; j++) {
> gray = stack.getVoxel(i,j,z);
> NewStack.setVoxel(i,j,z,Math.round(gray/2));
> }
> }
> }
>
> ImagePlus impStack = new ImagePlus("Clustered stack",NewStack);
> impStack.setStack(null,NewStack);
> impStack.show();
> }
>
> I meant the plugin to do the following. Read an open stack. Divide all gray values by two. Give a new stack as output which exhibits the calculated gray values.
>
> In principle this works, but the input stack is altered, though I want it to stay as it was.
>
> Where lies my mistake?
>
> Thanks a lot for your help!
>
> Alex
>
>
>
>
> Am 09.01.2013, 15:20 Uhr, schrieb Michael Epping <[hidden email]>:
>
>> Hello Alex,
>>
>> i think your problem is that the PluginFilter Interface is designed to perform an operation for each slice of a stacks. That is why the ImageProcessor ip at the run() method is useless for you.
>>
>> But the original stack can be accessed by using die ImagePlus imp at the setup() method. Just use "stack=imp.getStack()" where "ImageStack stack" is a field of you plugin-class.
>>
>> At the run() method you can use the stack for your calculations. Michael Schmid already wrote how to do that.
>>
>> Michael
>>
>> Am 09.01.2013 12:45, schrieb Alexandre Santos Abreu:
>>> Hello!
>>>
>>> I have a problem in writing a filter plugin which should operate on an
>>> image stack and give me another stack as an output.
>>>
>>> First I want to get access to the gray values of a stack opened in
>>> ImageJ but I don't know how to do this. After some operations I want to
>>> define an array for every slice of the output stack. I want to use this
>>> array to generate the slices of the output stack like in the following
>>> example:
>>>
>>> ImageStack Stapel = new ImageStack(w,h);
>>>
>>> ByteProcessor ipStack = new ByteProcessor(w,h);
>>> for (int i=0; i<w; i++) {
>>>     for (int j=0; j<h; j++) {
>>>         ipStack.putPixel(i,j, ARRAY[h*i+j]);
>>>     }
>>> }
>>> Stapel.addSlice("Thresholded image",ipStack);
>>>
>>>
>>> ImagePlus impStack = new ImagePlus("Clustered stack",Stapel);
>>> impStack.setStack(null,Stapel);
>>> impStack.show();
>>>
>>> Can anybody help me with accessing the pixel values of the original stack?
>>>
>>> Thanks Alex
>>>
>>> --
>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>>
>> --
>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>
>
> --
> Universität Augsburg
> Institut für Physik
> Lehrstuhl für Experimentalphysik II
> Universitätsstr. 1
> 86159 Augsburg
>
> Tel.: 0821 598 3453
> Fax: 0821 598 3411
> e-mail: [hidden email]
>
> --
> 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: Accessing image stacks

Alexandre Santos Abreu
In reply to this post by Rasband, Wayne (NIH/NIMH) [E]
Thanks a lot for all the help! Now it works as i hoped it would!

Alex



Am 09.01.2013, 18:00 Uhr, schrieb Rasband, Wayne (NIH/NIMH) [E]  
<[hidden email]>:

> On Jan 9, 2013, at 11:32 AM, Alexandre Santos Abreu wrote:
>
>> Hello Michael,
>>
>> I learned that I can use the voxel data. So i wrote the following code
>> just to check if it wors in principle:
>
> Here is a plugin that duplicates an existing stack and divides the pixel  
> values by 2.
>
> import ij.*;
> import ij.process.*;
> import ij.plugin.*;
>
>    public class My_Plugin implements PlugIn {
>
>       public void run(String arg) {
>          ImagePlus imp = IJ.getImage();
>          ImagePlus imp2 = new Duplicator().run(imp);
>          ImageStack stack2 = imp2.getStack();
>          int w = stack2.getWidth();
>          int h = stack2.getHeight();
>          int d = stack2.getSize();
>          for (int z=0; z<d; z++) {
>             for (int y=0; y<h; y++) {
>                for (int x=0; x<w; x++) {
>                   double gray = stack2.getVoxel(x,y,z);
>                   stack2.setVoxel(x,y,z,gray/2);
>                }
>             }
>          }
>          imp2.show();
>       }
>
>    }
>
>
>
>> public void run(ImageProcessor ip) {
>>
>>
>> ImagePlus imp = IJ.getImage();
>> ImageStack stack = imp.getStack();
>> int w = stack.getWidth();
>> int h = stack.getHeight();
>> int zMax = stack.getSize();
>> ImageStack NewStack = new ImageStack(w,h,zMax);
>> NewStack = stack;
>> double gray;
>> ImageStack Stapel = new ImageStack(w,h);
>> double [] SliceX = new double [w*h];
>>
>> for (int z=0; z<zMax; z++) {
>> for (int i=0; i<w; i++) {
>> for (int j=0; j<h; j++) {
>> gray = stack.getVoxel(i,j,z);
>> NewStack.setVoxel(i,j,z,Math.round(gray/2));
>> }
>> }
>> }
>>
>> ImagePlus impStack = new ImagePlus("Clustered stack",NewStack);
>> impStack.setStack(null,NewStack);
>> impStack.show();
>> }
>>
>> I meant the plugin to do the following. Read an open stack. Divide all
>> gray values by two. Give a new stack as output which exhibits the
>> calculated gray values.
>>
>> In principle this works, but the input stack is altered, though I want  
>> it
>> to stay as it was.
>>
>> Where lies my mistake?
>>
>> Thanks a lot for your help!
>>
>> Alex
>>
>>
>>
>>
>> Am 09.01.2013, 15:20 Uhr, schrieb Michael Epping <[hidden email]>:
>>
>>> Hello Alex,
>>>
>>> i think your problem is that the PluginFilter Interface is designed to
>>> perform an operation for each slice of a stacks. That is why the
>>> ImageProcessor ip at the run() method is useless for you.
>>>
>>> But the original stack can be accessed by using die ImagePlus imp at  
>>> the
>>> setup() method. Just use "stack=imp.getStack()" where "ImageStack  
>>> stack"
>>> is a field of you plugin-class.
>>>
>>> At the run() method you can use the stack for your calculations.  
>>> Michael
>>> Schmid already wrote how to do that.
>>>
>>> Michael
>>>
>>> Am 09.01.2013 12:45, schrieb Alexandre Santos Abreu:
>>>> Hello!
>>>>
>>>> I have a problem in writing a filter plugin which should operate on an
>>>> image stack and give me another stack as an output.
>>>>
>>>> First I want to get access to the gray values of a stack opened in
>>>> ImageJ but I don't know how to do this. After some operations I want  
>>>> to
>>>> define an array for every slice of the output stack. I want to use  
>>>> this
>>>> array to generate the slices of the output stack like in the following
>>>> example:
>>>>
>>>> ImageStack Stapel = new ImageStack(w,h);
>>>>
>>>> ByteProcessor ipStack = new ByteProcessor(w,h);
>>>> for (int i=0; i<w; i++) {
>>>>     for (int j=0; j<h; j++) {
>>>>         ipStack.putPixel(i,j, ARRAY[h*i+j]);
>>>>     }
>>>> }
>>>> Stapel.addSlice("Thresholded image",ipStack);
>>>>
>>>>
>>>> ImagePlus impStack = new ImagePlus("Clustered stack",Stapel);
>>>> impStack.setStack(null,Stapel);
>>>> impStack.show();
>>>>
>>>> Can anybody help me with accessing the pixel values of the original
>>>> stack?
>>>>
>>>> Thanks Alex
>>>>
>>>> --
>>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>>>
>>> --
>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>>
>>
>> --
>> Universität Augsburg
>> Institut für Physik
>> Lehrstuhl für Experimentalphysik II
>> Universitätsstr. 1
>> 86159 Augsburg
>>
>> Tel.: 0821 598 3453
>> Fax: 0821 598 3411
>> e-mail: [hidden email]
>>
>> --
>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>
> --
> ImageJ mailing list: http://imagej.nih.gov/ij/list.html


--
Universität Augsburg
Institut für Physik
Lehrstuhl für Experimentalphysik II
Universitätsstr. 1
86159 Augsburg

Tel.: 0821 598 3453
Fax: 0821 598 3411
e-mail: [hidden email]

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