I am trying to write a macro that converts a 2D image of a surface into a 3D binary
With pixels turned on only where the surface is. To do this I create an image stack, one Layer for each binned range of the Z-height of the surface. I then check each pixel as show below, decide which bin it falls in, and switch the value From 0 (initially set up using newImage(title,"black",xsteps,ysteps,steps) To one in the appropriate layer as shown for(x=1; x<=xsteps; x++) { for(y=1; y<=ysteps; y++) { print(y); for(z=1; z<=zsteps; z++) { selectImage(id1); zval = getPixel(x,y); if(zval>=(min+(zstep*(z-1)))){ if(zval<(min+(zstep*z))){ selectImage(id2); setPixel(x-1,y-1,1); } } } } } The problem is that this is incredibly slow, only a couple of pixels per second as shown by the Temporary print(y) above (no, it's not obviously faster without that). I think the main reason may be The selectImage function. Each time it does this it flashes between images on the screen, and I'm guessing,the write time is what is slowing this down. My question, then, is there a better way to select between two images (callying them as something like 2 or 3D arrays?). Alternatively, is there a macro or plugin already out there for this that will save me the time ? The whole thing as it currently stands is below. Many thanks --Larry requires("1.34m"); //the purpose of this file is to create a 3D binary image with zeros //everywhere except at the locations of the surface //first open the TIFF file of the original image var min, max; // global variables open() id1=getImageID() getMinAndMax(min, max); //now create a 3D array, X and y range and steps should match image Dialog.create("Input Data"); Dialog.addNumber("x min:",0); Dialog.addNumber("x max:", 2000); Dialog.addNumber("x step:", 1); // step must be even fraction of xmax-xmin Dialog.addNumber("y min:", 0); Dialog.addNumber("y max:", 2000); Dialog.addNumber("y step:", 1); Dialog.addNumber("z min:", min); Dialog.addNumber("z max:", max); Dialog.addNumber("zsteps:", 1); Dialog.addString("image title:", "title") Dialog.show(); xmin= Dialog.getNumber(); xmax = Dialog.getNumber(); xstep = Dialog.getNumber(); ymin= Dialog.getNumber(); ymax = Dialog.getNumber(); ystep = Dialog.getNumber(); zmin= Dialog.getNumber(); zmax = Dialog.getNumber(); zsteps = Dialog.getNumber(); title = Dialog.getString() //make array to hold the results for the plot xsteps = (xmax-xmin)/xstep ysteps = (ymax-ymin)/ystep zstep = (max-min)/zsteps newImage(title,"black",xsteps,ysteps,zsteps) id2=getImageID() //black should fill array with zeros // now evaluate each point in the image, and change black to // white in the new array accordingly // need to fix the below for when x and y don’t start at zero //need to fix z ranges – will miss the highest value for(x=1; x<=xsteps; x++) { for(y=1; y<=ysteps; y++) { print(y); for(z=1; z<=zsteps; z++) { selectImage(id1); zval = getPixel(x,y); if(zval>=(min+(zstep*(z-1)))){ if(zval<(min+(zstep*z))){ selectImage(id2); setPixel(x-1,y-1,1); } } } } } -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Hi Larry,
Not sure I have understood clearly, do you want to create a binary mask of the "inside" of your surface ? the contrary of creating a mesh from a volume ? If yes you mean voxellisation. I've implemented such a algorithm in my 3DLibrary, it's quite fast with multithreading. The library is available s part of the 3D ImageJ Suite : http://imagejdocu.tudor.lu/doku.php?id=plugin:stacks:3d_ij_suite:start contact me if you want details on how to use it in your plugins. hope this helps Thomas Le 02/04/2013 05:53, Anovitz, Lawrence {Larry} M. a écrit : > I am trying to write a macro that converts a 2D image of a surface into a 3D binary > With pixels turned on only where the surface is. To do this I create an image stack, one > Layer for each binned range of the Z-height of the surface. > I then check each pixel as show below, decide which bin it falls in, and switch the value > From 0 (initially set up using > > newImage(title,"black",xsteps,ysteps,steps) > > > To one in the appropriate layer as shown > > > for(x=1; x<=xsteps; x++) { > > > > for(y=1; y<=ysteps; y++) { > > print(y); > > > > for(z=1; z<=zsteps; z++) { > > > > selectImage(id1); > > zval = getPixel(x,y); > > > > if(zval>=(min+(zstep*(z-1)))){ > > if(zval<(min+(zstep*z))){ > > selectImage(id2); > > setPixel(x-1,y-1,1); > > } > > } > > > > } > > } > > } > > > The problem is that this is incredibly slow, only a couple of pixels per second as shown by the > > Temporary print(y) above (no, it's not obviously faster without that). > > I think the main reason may be The selectImage function. Each time it does this it flashes between images on the screen, and > > I'm guessing,the write time is what is slowing this down. > > > My question, then, is there a better way to select between two images (callying them as something like > > 2 or 3D arrays?). Alternatively, is there a macro or plugin already out there for this that will save me the time ? > > > The whole thing as it currently stands is below. > > Many thanks > > --Larry > > > > > requires("1.34m"); > > //the purpose of this file is to create a 3D binary image with zeros > > //everywhere except at the locations of the surface > > > > //first open the TIFF file of the original image > > > > var min, max; // global variables > > > > open() > > > > id1=getImageID() > > > > getMinAndMax(min, max); > > > > //now create a 3D array, X and y range and steps should match image > > > > Dialog.create("Input Data"); > > Dialog.addNumber("x min:",0); > > Dialog.addNumber("x max:", 2000); > > Dialog.addNumber("x step:", 1); > > // step must be even fraction of xmax-xmin > > Dialog.addNumber("y min:", 0); > > Dialog.addNumber("y max:", 2000); > > Dialog.addNumber("y step:", 1); > > Dialog.addNumber("z min:", min); > > Dialog.addNumber("z max:", max); > > Dialog.addNumber("zsteps:", 1); > > Dialog.addString("image title:", "title") > > Dialog.show(); > > xmin= Dialog.getNumber(); > > xmax = Dialog.getNumber(); > > xstep = Dialog.getNumber(); > > ymin= Dialog.getNumber(); > > ymax = Dialog.getNumber(); > > ystep = Dialog.getNumber(); > > zmin= Dialog.getNumber(); > > zmax = Dialog.getNumber(); > > zsteps = Dialog.getNumber(); > > title = Dialog.getString() > > > > //make array to hold the results for the plot > > > > xsteps = (xmax-xmin)/xstep > > ysteps = (ymax-ymin)/ystep > > > > zstep = (max-min)/zsteps > > > > newImage(title,"black",xsteps,ysteps,zsteps) > > id2=getImageID() > > > > //black should fill array with zeros > > > > // now evaluate each point in the image, and change black to > > // white in the new array accordingly > > > > > > // need to fix the below for when x and y don’t start at zero > > //need to fix z ranges – will miss the highest value > > for(x=1; x<=xsteps; x++) { > > > > for(y=1; y<=ysteps; y++) { > > print(y); > > > > for(z=1; z<=zsteps; z++) { > > > > selectImage(id1); > > zval = getPixel(x,y); > > > > if(zval>=(min+(zstep*(z-1)))){ > > if(zval<(min+(zstep*z))){ > > selectImage(id2); > > setPixel(x-1,y-1,1); > > } > > } > > > > } > > } > > } > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > -- /**********************************************************/ Thomas Boudier, MCU Université Pierre et Marie Curie, Modélisation Cellulaire et Imagerie Biologique (EE1), IFR 83, Bat B 7ème étage, porte 723, Campus Jussieu. Tel : 01 44 27 46 92 Fax : 01 44 27 22 91 /*******************************************************/ -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
In reply to this post by LMAnovitz
Hi Larry,
> The problem is that this is incredibly slow, only a couple of pixels > per second as shown by the Temporary print(y) above (no, it's not > obviously faster without that). > > I think the main reason may be The selectImage function. Each time it > does this it flashes between images on the screen, and I'm > guessing,the write time is what is slowing this down. You can mitigate this issue by adding "setBatchMode(true);" at the beginning of your macro, and "setBatchMode(false);" at the end. Hopefully you will observe a manyfold speed increase. Ultimately, switching to Java code can net an even greater increase, but "setBatchMode(true);" is sufficient in many situations. Regards, Curtis On Mon, Apr 1, 2013 at 10:53 PM, Anovitz, Lawrence {Larry} M. < [hidden email]> wrote: > I am trying to write a macro that converts a 2D image of a surface into a > 3D binary > With pixels turned on only where the surface is. To do this I create an > image stack, one > Layer for each binned range of the Z-height of the surface. > I then check each pixel as show below, decide which bin it falls in, and > switch the value > From 0 (initially set up using > > newImage(title,"black",xsteps,ysteps,steps) > > > To one in the appropriate layer as shown > > > for(x=1; x<=xsteps; x++) { > > > > for(y=1; y<=ysteps; y++) { > > print(y); > > > > for(z=1; z<=zsteps; z++) { > > > > selectImage(id1); > > zval = getPixel(x,y); > > > > if(zval>=(min+(zstep*(z-1)))){ > > if(zval<(min+(zstep*z))){ > > selectImage(id2); > > setPixel(x-1,y-1,1); > > } > > } > > > > } > > } > > } > > > The problem is that this is incredibly slow, only a couple of pixels per > second as shown by the > > Temporary print(y) above (no, it's not obviously faster without that). > > I think the main reason may be The selectImage function. Each time it does > this it flashes between images on the screen, and > > I'm guessing,the write time is what is slowing this down. > > > My question, then, is there a better way to select between two images > (callying them as something like > > 2 or 3D arrays?). Alternatively, is there a macro or plugin already out > there for this that will save me the time ? > > > The whole thing as it currently stands is below. > > Many thanks > > --Larry > > > > > requires("1.34m"); > > //the purpose of this file is to create a 3D binary image with zeros > > //everywhere except at the locations of the surface > > > > //first open the TIFF file of the original image > > > > var min, max; // global variables > > > > open() > > > > id1=getImageID() > > > > getMinAndMax(min, max); > > > > //now create a 3D array, X and y range and steps should match image > > > > Dialog.create("Input Data"); > > Dialog.addNumber("x min:",0); > > Dialog.addNumber("x max:", 2000); > > Dialog.addNumber("x step:", 1); > > // step must be even fraction of xmax-xmin > > Dialog.addNumber("y min:", 0); > > Dialog.addNumber("y max:", 2000); > > Dialog.addNumber("y step:", 1); > > Dialog.addNumber("z min:", min); > > Dialog.addNumber("z max:", max); > > Dialog.addNumber("zsteps:", 1); > > Dialog.addString("image title:", "title") > > Dialog.show(); > > xmin= Dialog.getNumber(); > > xmax = Dialog.getNumber(); > > xstep = Dialog.getNumber(); > > ymin= Dialog.getNumber(); > > ymax = Dialog.getNumber(); > > ystep = Dialog.getNumber(); > > zmin= Dialog.getNumber(); > > zmax = Dialog.getNumber(); > > zsteps = Dialog.getNumber(); > > title = Dialog.getString() > > > > //make array to hold the results for the plot > > > > xsteps = (xmax-xmin)/xstep > > ysteps = (ymax-ymin)/ystep > > > > zstep = (max-min)/zsteps > > > > newImage(title,"black",xsteps,ysteps,zsteps) > > id2=getImageID() > > > > //black should fill array with zeros > > > > // now evaluate each point in the image, and change black to > > // white in the new array accordingly > > > > > > // need to fix the below for when x and y don’t start at zero > > //need to fix z ranges – will miss the highest value > > for(x=1; x<=xsteps; x++) { > > > > for(y=1; y<=ysteps; y++) { > > print(y); > > > > for(z=1; z<=zsteps; z++) { > > > > selectImage(id1); > > zval = getPixel(x,y); > > > > if(zval>=(min+(zstep*(z-1)))){ > > if(zval<(min+(zstep*z))){ > > selectImage(id2); > > setPixel(x-1,y-1,1); > > } > > } > > > > } > > } > > } > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
In reply to this post by LMAnovitz
Hi Larry,
it will be faster with 'setBatchMode(true);' at the beginning. Even then, it might be quite slow when done in a macro; unless you need it very few times it would be worthwhile writing a plugin. It's very easy: - For the Dialog commands there are essentially the same functions in the GenericDialog class. There is an example at: http://rsb.info.nih.gov/ij/source/ij/gui/GenericDialog.java - The current image is ImagePlus currentImp=WindowManager.getCurrentImage(); If you write a PlugInFilter, you will even get the current ImagePlus as an argument. - New image: Use IJ.createImage(String title, int width, int height, int depth, int bitdepth). This returns an ImagePlus (let's say, named imp); you can get the ImageStack it contains with imp.getStack(). - Access (for read) the input data by currentImp.getProcessor().getPixelValue(x,y) - Access the pixels of slice n of the ImageStack with (byte[])((stack.getImageArray())[n-1]), which gives you a byte array for slice n. In the desired byte array you can set pixel[x+y*width] to the 'on'-value. Michael ________________________________________________________________ On Apr 2, 2013, at 05:53, Anovitz, Lawrence {Larry} M. wrote: > I am trying to write a macro that converts a 2D image of a surface into a 3D binary > With pixels turned on only where the surface is. To do this I create an image stack, one > Layer for each binned range of the Z-height of the surface. > > I then check each pixel as show below, decide which bin it falls in, and switch the value > From 0 (initially set up using > newImage(title,"black",xsteps,ysteps,steps) > To one in the appropriate layer as shown > > for(x=1; x<=xsteps; x++) { > for(y=1; y<=ysteps; y++) { > print(y); > for(z=1; z<=zsteps; z++) { > selectImage(id1); > zval = getPixel(x,y); > if(zval>=(min+(zstep*(z-1)))){ > if(zval<(min+(zstep*z))){ > selectImage(id2); > setPixel(x-1,y-1,1); > } > } > } > } > } > > The problem is that this is incredibly slow, only a couple of pixels per second as shown by the Temporary print(y) above (no, it's not obviously faster without that). > I think the main reason may be The selectImage function. Each time it does this it flashes between images on the screen, and I'm guessing,the write time is what is slowing this down. > My question, then, is there a better way to select between two images (callying them as something like 2 or 3D arrays?). Alternatively, is there a macro or plugin already out there for this that will save me the time ? > The whole thing as it currently stands is below. > > Many thanks > > --Larry > > requires("1.34m"); > //the purpose of this file is to create a 3D binary image with zeros > //everywhere except at the locations of the surface > //first open the TIFF file of the original image > var min, max; // global variables > open() > id1=getImageID() > getMinAndMax(min, max); > //now create a 3D array, X and y range and steps should match image > Dialog.create("Input Data"); > Dialog.addNumber("x min:",0); > Dialog.addNumber("x max:", 2000); > Dialog.addNumber("x step:", 1); > // step must be even fraction of xmax-xmin > Dialog.addNumber("y min:", 0); > Dialog.addNumber("y max:", 2000); > Dialog.addNumber("y step:", 1); > Dialog.addNumber("z min:", min); > Dialog.addNumber("z max:", max); > Dialog.addNumber("zsteps:", 1); > Dialog.addString("image title:", "title") > Dialog.show(); > xmin= Dialog.getNumber(); > xmax = Dialog.getNumber(); > xstep = Dialog.getNumber(); > ymin= Dialog.getNumber(); > ymax = Dialog.getNumber(); > ystep = Dialog.getNumber(); > zmin= Dialog.getNumber(); > zmax = Dialog.getNumber(); > zsteps = Dialog.getNumber(); > title = Dialog.getString() > //make array to hold the results for the plot > xsteps = (xmax-xmin)/xstep > ysteps = (ymax-ymin)/ystep > zstep = (max-min)/zsteps > newImage(title,"black",xsteps,ysteps,zsteps) > id2=getImageID() > //black should fill array with zeros > // now evaluate each point in the image, and change black to > // white in the new array accordingly > // need to fix the below for when x and y don’t start at zero > //need to fix z ranges – will miss the highest value > for(x=1; x<=xsteps; x++) { > for(y=1; y<=ysteps; y++) { > print(y); > for(z=1; z<=zsteps; z++) { > selectImage(id1); > zval = getPixel(x,y); > if(zval>=(min+(zstep*(z-1)))){ > if(zval<(min+(zstep*z))){ > selectImage(id2); > setPixel(x-1,y-1,1); > } > } > } > } > } -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Hi
Many thanks - that solved that problem. A 2000 x 2000 image now takes abt 15 sec to run on my laptop. Not too bad. I may yet go to trying to learn to write a Plugin, but at least I can test it. However, this left me with a new problem. At the end of the run the first file, which Contains the initial data, appears, but the new stack does not, and I'm not sure how to Find it, or if it is really there. In addition, what I really need is a stack of binary images, can I change "8-bit black" in newImage to "binary black"? Thanks again. The current version is below --Larry requires("1.34m"); setBatchMode(true); //the purpose of this file is to create a 3D binary image with zeros //everywhere except at the locations of the surface //first open the TIFF file of the original image var min, max; // global variables open() id1=getImageID() getMinAndMax(min, max); //now create a 3D array, X and y range and steps should match image Dialog.create("Input Data"); Dialog.addNumber("x min:",0); Dialog.addNumber("x max:", 2000); Dialog.addNumber("x step:", 1); // step must be even fraction of xmax-xmin Dialog.addNumber("y min:", 0); Dialog.addNumber("y max:", 2000); Dialog.addNumber("y step:", 1); Dialog.addNumber("z min:", min); Dialog.addNumber("z max:", max); Dialog.addNumber("zsteps:", 1); Dialog.addString("image title:", "title") Dialog.show(); xmin= Dialog.getNumber(); xmax = Dialog.getNumber(); xstep = Dialog.getNumber(); ymin= Dialog.getNumber(); ymax = Dialog.getNumber(); ystep = Dialog.getNumber(); zmin= Dialog.getNumber(); zmax = Dialog.getNumber(); zsteps = Dialog.getNumber(); title = Dialog.getString() //make array to hold the results for the plot xsteps = (xmax-xmin)/xstep ysteps = (ymax-ymin)/ystep zstep = (max-min)/zsteps newImage(title,"8-bit black",xsteps,ysteps,zsteps) id2=getImageID() //black should fill array with zeros // now evaluate each point in the image, and change black to // white in the new array accordingly // need to fix the below for when x and y dont start at zero //need to fix z ranges it will miss the highest values for(x=1; x<=xsteps; x++) { print(x); for(y=1; y<=ysteps; y++) { for(z=1; z<=zsteps; z++) { selectImage(id1); zval = getPixel(x,y); if(zval>=(min+(zstep*(z-1)))){ if(zval<(min+(zstep*z))){ selectImage(id2); setPixel(x-1,y-1,1); } } } } } setBatchMode(false); On 4/2/13 10:52 AM, "Michael Schmid" <[hidden email]> wrote: >Hi Larry, > >it will be faster with 'setBatchMode(true);' at the beginning. > >Even then, it might be quite slow when done in a macro; unless you need >it very few times it would be worthwhile writing a plugin. It's very easy: > >- For the Dialog commands there are essentially the same functions in the >GenericDialog class. There is an example at: > http://rsb.info.nih.gov/ij/source/ij/gui/GenericDialog.java >- The current image is ImagePlus >currentImp=WindowManager.getCurrentImage(); > If you write a PlugInFilter, you will even get the current ImagePlus as >an argument. >- New image: Use IJ.createImage(String title, int width, int height, int >depth, int bitdepth). This returns an ImagePlus (let's say, named imp); >you can get the ImageStack it contains with imp.getStack(). >- Access (for read) the input data by >currentImp.getProcessor().getPixelValue(x,y) >- Access the pixels of slice n of the ImageStack with > (byte[])((stack.getImageArray())[n-1]), which gives you a byte array >for slice n. > In the desired byte array you can set pixel[x+y*width] to the >'on'-value. > > >Michael >________________________________________________________________ >On Apr 2, 2013, at 05:53, Anovitz, Lawrence {Larry} M. wrote: >> I am trying to write a macro that converts a 2D image of a surface into >>a 3D binary >> With pixels turned on only where the surface is. To do this I create an >>image stack, one >> Layer for each binned range of the Z-height of the surface. >> >> I then check each pixel as show below, decide which bin it falls in, >>and switch the value >> From 0 (initially set up using >> newImage(title,"black",xsteps,ysteps,steps) >> To one in the appropriate layer as shown >> >> for(x=1; x<=xsteps; x++) { >> for(y=1; y<=ysteps; y++) { >> print(y); >> for(z=1; z<=zsteps; z++) { >> selectImage(id1); >> zval = getPixel(x,y); >> if(zval>=(min+(zstep*(z-1)))){ >> if(zval<(min+(zstep*z))){ >> selectImage(id2); >> setPixel(x-1,y-1,1); >> } >> } >> } >> } >> } >> >> The problem is that this is incredibly slow, only a couple of pixels >>per second as shown by the Temporary print(y) above (no, it's not >>obviously faster without that). >> I think the main reason may be The selectImage function. Each time it >>does this it flashes between images on the screen, and I'm guessing,the >>write time is what is slowing this down. >> My question, then, is there a better way to select between two images >>(callying them as something like 2 or 3D arrays?). Alternatively, is >>there a macro or plugin already out there for this that will save me the >>time ? >> The whole thing as it currently stands is below. >> >> Many thanks >> >> --Larry >> >> requires("1.34m"); >> //the purpose of this file is to create a 3D binary image with zeros >> //everywhere except at the locations of the surface >> //first open the TIFF file of the original image >> var min, max; // global variables >> open() >> id1=getImageID() >> getMinAndMax(min, max); >> //now create a 3D array, X and y range and steps should match image >> Dialog.create("Input Data"); >> Dialog.addNumber("x min:",0); >> Dialog.addNumber("x max:", 2000); >> Dialog.addNumber("x step:", 1); >> // step must be even fraction of xmax-xmin >> Dialog.addNumber("y min:", 0); >> Dialog.addNumber("y max:", 2000); >> Dialog.addNumber("y step:", 1); >> Dialog.addNumber("z min:", min); >> Dialog.addNumber("z max:", max); >> Dialog.addNumber("zsteps:", 1); >> Dialog.addString("image title:", "title") >> Dialog.show(); >> xmin= Dialog.getNumber(); >> xmax = Dialog.getNumber(); >> xstep = Dialog.getNumber(); >> ymin= Dialog.getNumber(); >> ymax = Dialog.getNumber(); >> ystep = Dialog.getNumber(); >> zmin= Dialog.getNumber(); >> zmax = Dialog.getNumber(); >> zsteps = Dialog.getNumber(); >> title = Dialog.getString() >> //make array to hold the results for the plot >> xsteps = (xmax-xmin)/xstep >> ysteps = (ymax-ymin)/ystep >> zstep = (max-min)/zsteps >> newImage(title,"black",xsteps,ysteps,zsteps) >> id2=getImageID() >> //black should fill array with zeros >> // now evaluate each point in the image, and change black to >> // white in the new array accordingly >> // need to fix the below for when x and y don¹t start at zero >> //need to fix z ranges will miss the highest value >> for(x=1; x<=xsteps; x++) { >> for(y=1; y<=ysteps; y++) { >> print(y); >> for(z=1; z<=zsteps; z++) { >> selectImage(id1); >> zval = getPixel(x,y); >> if(zval>=(min+(zstep*(z-1)))){ >> if(zval<(min+(zstep*z))){ >> selectImage(id2); >> setPixel(x-1,y-1,1); >> } >> } >> } >> } >> } > >-- >ImageJ mailing list: http://imagej.nih.gov/ij/list.html -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Hi Larry,
use setBatchMode("exit and display"); to display images created during BatchMode. Alternatively, enter BatchMode after you have created the stack. For a binary image, simply set the values of 'on' pixels of a normal 8-bit image to 255. If there are no other pixel values than 0 and 255, it is a binary image. The initial (as created) image should have pixel values of 0 (as you will get with "8-bit Black"). If you have white background for binary images (Binary Options with 'Black Background' off), invert the LUT of your stack. Michael ________________________________________________________________ On Apr 2, 2013, at 20:41, Anovitz, Lawrence {Larry} M. wrote: > Hi > Many thanks - that solved that problem. A 2000 x 2000 image now takes > abt > 15 sec to run on my laptop. Not too bad. I may yet go to trying to learn > to write a > Plugin, but at least I can test it. > > However, this left me with a new problem. At the end of the run the first > file, which > Contains the initial data, appears, but the new stack does not, and I'm > not sure how to > Find it, or if it is really there. In addition, what I really need is a > stack of binary images, > can I change "8-bit black" in newImage to "binary black"? > > Thanks again. The current version is below > > --Larry > > > > > requires("1.34m"); > setBatchMode(true); > //the purpose of this file is to create a 3D binary image with zeros > //everywhere except at the locations of the surface > > //first open the TIFF file of the original image > > var min, max; // global variables > > open() > > id1=getImageID() > > getMinAndMax(min, max); > > //now create a 3D array, X and y range and steps should match image > > Dialog.create("Input Data"); > Dialog.addNumber("x min:",0); > Dialog.addNumber("x max:", 2000); > Dialog.addNumber("x step:", 1); > // step must be even fraction of xmax-xmin > Dialog.addNumber("y min:", 0); > Dialog.addNumber("y max:", 2000); > Dialog.addNumber("y step:", 1); > Dialog.addNumber("z min:", min); > Dialog.addNumber("z max:", max); > Dialog.addNumber("zsteps:", 1); > Dialog.addString("image title:", "title") > Dialog.show(); > xmin= Dialog.getNumber(); > xmax = Dialog.getNumber(); > xstep = Dialog.getNumber(); > ymin= Dialog.getNumber(); > ymax = Dialog.getNumber(); > ystep = Dialog.getNumber(); > zmin= Dialog.getNumber(); > zmax = Dialog.getNumber(); > zsteps = Dialog.getNumber(); > title = Dialog.getString() > > //make array to hold the results for the plot > > xsteps = (xmax-xmin)/xstep > ysteps = (ymax-ymin)/ystep > > zstep = (max-min)/zsteps > > newImage(title,"8-bit black",xsteps,ysteps,zsteps) > id2=getImageID() > > //black should fill array with zeros > > // now evaluate each point in the image, and change black to > // white in the new array accordingly > > > // need to fix the below for when x and y dont start at zero > //need to fix z ranges it will miss the highest values > for(x=1; x<=xsteps; x++) { > print(x); > for(y=1; y<=ysteps; y++) { > > for(z=1; z<=zsteps; z++) { > > selectImage(id1); > zval = getPixel(x,y); > > if(zval>=(min+(zstep*(z-1)))){ > if(zval<(min+(zstep*z))){ > selectImage(id2); > setPixel(x-1,y-1,1); > } > } > > } > } > } > setBatchMode(false); > > > > > > > On 4/2/13 10:52 AM, "Michael Schmid" <[hidden email]> wrote: > >> Hi Larry, >> >> it will be faster with 'setBatchMode(true);' at the beginning. >> >> Even then, it might be quite slow when done in a macro; unless you need >> it very few times it would be worthwhile writing a plugin. It's very easy: >> >> - For the Dialog commands there are essentially the same functions in the >> GenericDialog class. There is an example at: >> http://rsb.info.nih.gov/ij/source/ij/gui/GenericDialog.java >> - The current image is ImagePlus >> currentImp=WindowManager.getCurrentImage(); >> If you write a PlugInFilter, you will even get the current ImagePlus as >> an argument. >> - New image: Use IJ.createImage(String title, int width, int height, int >> depth, int bitdepth). This returns an ImagePlus (let's say, named imp); >> you can get the ImageStack it contains with imp.getStack(). >> - Access (for read) the input data by >> currentImp.getProcessor().getPixelValue(x,y) >> - Access the pixels of slice n of the ImageStack with >> (byte[])((stack.getImageArray())[n-1]), which gives you a byte array >> for slice n. >> In the desired byte array you can set pixel[x+y*width] to the >> 'on'-value. >> >> >> Michael >> ________________________________________________________________ >> On Apr 2, 2013, at 05:53, Anovitz, Lawrence {Larry} M. wrote: >>> I am trying to write a macro that converts a 2D image of a surface into >>> a 3D binary >>> With pixels turned on only where the surface is. To do this I create an >>> image stack, one >>> Layer for each binned range of the Z-height of the surface. >>> >>> I then check each pixel as show below, decide which bin it falls in, >>> and switch the value >>> From 0 (initially set up using >>> newImage(title,"black",xsteps,ysteps,steps) >>> To one in the appropriate layer as shown >>> >>> for(x=1; x<=xsteps; x++) { >>> for(y=1; y<=ysteps; y++) { >>> print(y); >>> for(z=1; z<=zsteps; z++) { >>> selectImage(id1); >>> zval = getPixel(x,y); >>> if(zval>=(min+(zstep*(z-1)))){ >>> if(zval<(min+(zstep*z))){ >>> selectImage(id2); >>> setPixel(x-1,y-1,1); >>> } >>> } >>> } >>> } >>> } >>> >>> The problem is that this is incredibly slow, only a couple of pixels >>> per second as shown by the Temporary print(y) above (no, it's not >>> obviously faster without that). >>> I think the main reason may be The selectImage function. Each time it >>> does this it flashes between images on the screen, and I'm guessing,the >>> write time is what is slowing this down. >>> My question, then, is there a better way to select between two images >>> (callying them as something like 2 or 3D arrays?). Alternatively, is >>> there a macro or plugin already out there for this that will save me the >>> time ? >>> The whole thing as it currently stands is below. >>> >>> Many thanks >>> >>> --Larry >>> >>> requires("1.34m"); >>> //the purpose of this file is to create a 3D binary image with zeros >>> //everywhere except at the locations of the surface >>> //first open the TIFF file of the original image >>> var min, max; // global variables >>> open() >>> id1=getImageID() >>> getMinAndMax(min, max); >>> //now create a 3D array, X and y range and steps should match image >>> Dialog.create("Input Data"); >>> Dialog.addNumber("x min:",0); >>> Dialog.addNumber("x max:", 2000); >>> Dialog.addNumber("x step:", 1); >>> // step must be even fraction of xmax-xmin >>> Dialog.addNumber("y min:", 0); >>> Dialog.addNumber("y max:", 2000); >>> Dialog.addNumber("y step:", 1); >>> Dialog.addNumber("z min:", min); >>> Dialog.addNumber("z max:", max); >>> Dialog.addNumber("zsteps:", 1); >>> Dialog.addString("image title:", "title") >>> Dialog.show(); >>> xmin= Dialog.getNumber(); >>> xmax = Dialog.getNumber(); >>> xstep = Dialog.getNumber(); >>> ymin= Dialog.getNumber(); >>> ymax = Dialog.getNumber(); >>> ystep = Dialog.getNumber(); >>> zmin= Dialog.getNumber(); >>> zmax = Dialog.getNumber(); >>> zsteps = Dialog.getNumber(); >>> title = Dialog.getString() >>> //make array to hold the results for the plot >>> xsteps = (xmax-xmin)/xstep >>> ysteps = (ymax-ymin)/ystep >>> zstep = (max-min)/zsteps >>> newImage(title,"black",xsteps,ysteps,zsteps) >>> id2=getImageID() >>> //black should fill array with zeros >>> // now evaluate each point in the image, and change black to >>> // white in the new array accordingly >>> // need to fix the below for when x and y don¹t start at zero >>> //need to fix z ranges will miss the highest value >>> for(x=1; x<=xsteps; x++) { >>> for(y=1; y<=ysteps; y++) { >>> print(y); >>> for(z=1; z<=zsteps; z++) { >>> selectImage(id1); >>> zval = getPixel(x,y); >>> if(zval>=(min+(zstep*(z-1)))){ >>> if(zval<(min+(zstep*z))){ >>> selectImage(id2); >>> setPixel(x-1,y-1,1); >>> } >>> } >>> } >>> } >>> } >> >> -- >> 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 |
Hi Larry,
You can get a faster script by using the setThreshold(...) function rather than scanning your whole image. Here is the synopsis of a script in pseudo-code for (value = min, value < max; value+=step) binary = threshold(0,value) copy_and_paste_binary_into_stack end for I have such a script (not for the same purpose) here : http://crazybiocomputing.blogspot.fr/2011/10/gray-level-images-and-morphology.html Hope that helps. Jean-Christophe. 2013/4/2 Michael Schmid <[hidden email]> > Hi Larry, > > use setBatchMode("exit and display"); to display images created during > BatchMode. > Alternatively, enter BatchMode after you have created the stack. > > For a binary image, simply set the values of 'on' pixels of a normal 8-bit > image to 255. If there are no other pixel values than 0 and 255, it is a > binary image. The initial (as created) image should have pixel values of 0 > (as you will get with "8-bit Black"). > If you have white background for binary images (Binary Options with 'Black > Background' off), invert the LUT of your stack. > > Michael > ________________________________________________________________ > On Apr 2, 2013, at 20:41, Anovitz, Lawrence {Larry} M. wrote: > > > Hi > > Many thanks - that solved that problem. A 2000 x 2000 image now takes > > abt > > 15 sec to run on my laptop. Not too bad. I may yet go to trying to learn > > to write a > > Plugin, but at least I can test it. > > > > However, this left me with a new problem. At the end of the run the first > > file, which > > Contains the initial data, appears, but the new stack does not, and I'm > > not sure how to > > Find it, or if it is really there. In addition, what I really need is a > > stack of binary images, > > can I change "8-bit black" in newImage to "binary black"? > > > > Thanks again. The current version is below > > > > --Larry > > > > > > > > > > requires("1.34m"); > > setBatchMode(true); > > //the purpose of this file is to create a 3D binary image with zeros > > //everywhere except at the locations of the surface > > > > //first open the TIFF file of the original image > > > > var min, max; // global variables > > > > open() > > > > id1=getImageID() > > > > getMinAndMax(min, max); > > > > //now create a 3D array, X and y range and steps should match image > > > > Dialog.create("Input Data"); > > Dialog.addNumber("x min:",0); > > Dialog.addNumber("x max:", 2000); > > Dialog.addNumber("x step:", 1); > > // step must be even fraction of xmax-xmin > > Dialog.addNumber("y min:", 0); > > Dialog.addNumber("y max:", 2000); > > Dialog.addNumber("y step:", 1); > > Dialog.addNumber("z min:", min); > > Dialog.addNumber("z max:", max); > > Dialog.addNumber("zsteps:", 1); > > Dialog.addString("image title:", "title") > > Dialog.show(); > > xmin= Dialog.getNumber(); > > xmax = Dialog.getNumber(); > > xstep = Dialog.getNumber(); > > ymin= Dialog.getNumber(); > > ymax = Dialog.getNumber(); > > ystep = Dialog.getNumber(); > > zmin= Dialog.getNumber(); > > zmax = Dialog.getNumber(); > > zsteps = Dialog.getNumber(); > > title = Dialog.getString() > > > > //make array to hold the results for the plot > > > > xsteps = (xmax-xmin)/xstep > > ysteps = (ymax-ymin)/ystep > > > > zstep = (max-min)/zsteps > > > > newImage(title,"8-bit black",xsteps,ysteps,zsteps) > > id2=getImageID() > > > > //black should fill array with zeros > > > > // now evaluate each point in the image, and change black to > > // white in the new array accordingly > > > > > > // need to fix the below for when x and y dont start at zero > > //need to fix z ranges it will miss the highest values > > for(x=1; x<=xsteps; x++) { > > print(x); > > for(y=1; y<=ysteps; y++) { > > > > for(z=1; z<=zsteps; z++) { > > > > selectImage(id1); > > zval = getPixel(x,y); > > > > if(zval>=(min+(zstep*(z-1)))){ > > if(zval<(min+(zstep*z))){ > > selectImage(id2); > > setPixel(x-1,y-1,1); > > } > > } > > > > } > > } > > } > > setBatchMode(false); > > > > > > > > > > > > > > On 4/2/13 10:52 AM, "Michael Schmid" <[hidden email]> wrote: > > > >> Hi Larry, > >> > >> it will be faster with 'setBatchMode(true);' at the beginning. > >> > >> Even then, it might be quite slow when done in a macro; unless you need > >> it very few times it would be worthwhile writing a plugin. It's very > easy: > >> > >> - For the Dialog commands there are essentially the same functions in > the > >> GenericDialog class. There is an example at: > >> http://rsb.info.nih.gov/ij/source/ij/gui/GenericDialog.java > >> - The current image is ImagePlus > >> currentImp=WindowManager.getCurrentImage(); > >> If you write a PlugInFilter, you will even get the current ImagePlus as > >> an argument. > >> - New image: Use IJ.createImage(String title, int width, int height, int > >> depth, int bitdepth). This returns an ImagePlus (let's say, named imp); > >> you can get the ImageStack it contains with imp.getStack(). > >> - Access (for read) the input data by > >> currentImp.getProcessor().getPixelValue(x,y) > >> - Access the pixels of slice n of the ImageStack with > >> (byte[])((stack.getImageArray())[n-1]), which gives you a byte array > >> for slice n. > >> In the desired byte array you can set pixel[x+y*width] to the > >> 'on'-value. > >> > >> > >> Michael > >> ________________________________________________________________ > >> On Apr 2, 2013, at 05:53, Anovitz, Lawrence {Larry} M. wrote: > >>> I am trying to write a macro that converts a 2D image of a surface into > >>> a 3D binary > >>> With pixels turned on only where the surface is. To do this I create an > >>> image stack, one > >>> Layer for each binned range of the Z-height of the surface. > >>> > >>> I then check each pixel as show below, decide which bin it falls in, > >>> and switch the value > >>> From 0 (initially set up using > >>> newImage(title,"black",xsteps,ysteps,steps) > >>> To one in the appropriate layer as shown > >>> > >>> for(x=1; x<=xsteps; x++) { > >>> for(y=1; y<=ysteps; y++) { > >>> print(y); > >>> for(z=1; z<=zsteps; z++) { > >>> selectImage(id1); > >>> zval = getPixel(x,y); > >>> if(zval>=(min+(zstep*(z-1)))){ > >>> if(zval<(min+(zstep*z))){ > >>> selectImage(id2); > >>> setPixel(x-1,y-1,1); > >>> } > >>> } > >>> } > >>> } > >>> } > >>> > >>> The problem is that this is incredibly slow, only a couple of pixels > >>> per second as shown by the Temporary print(y) above (no, it's not > >>> obviously faster without that). > >>> I think the main reason may be The selectImage function. Each time it > >>> does this it flashes between images on the screen, and I'm guessing,the > >>> write time is what is slowing this down. > >>> My question, then, is there a better way to select between two images > >>> (callying them as something like 2 or 3D arrays?). Alternatively, is > >>> there a macro or plugin already out there for this that will save me > the > >>> time ? > >>> The whole thing as it currently stands is below. > >>> > >>> Many thanks > >>> > >>> --Larry > >>> > >>> requires("1.34m"); > >>> //the purpose of this file is to create a 3D binary image with zeros > >>> //everywhere except at the locations of the surface > >>> //first open the TIFF file of the original image > >>> var min, max; // global variables > >>> open() > >>> id1=getImageID() > >>> getMinAndMax(min, max); > >>> //now create a 3D array, X and y range and steps should match image > >>> Dialog.create("Input Data"); > >>> Dialog.addNumber("x min:",0); > >>> Dialog.addNumber("x max:", 2000); > >>> Dialog.addNumber("x step:", 1); > >>> // step must be even fraction of xmax-xmin > >>> Dialog.addNumber("y min:", 0); > >>> Dialog.addNumber("y max:", 2000); > >>> Dialog.addNumber("y step:", 1); > >>> Dialog.addNumber("z min:", min); > >>> Dialog.addNumber("z max:", max); > >>> Dialog.addNumber("zsteps:", 1); > >>> Dialog.addString("image title:", "title") > >>> Dialog.show(); > >>> xmin= Dialog.getNumber(); > >>> xmax = Dialog.getNumber(); > >>> xstep = Dialog.getNumber(); > >>> ymin= Dialog.getNumber(); > >>> ymax = Dialog.getNumber(); > >>> ystep = Dialog.getNumber(); > >>> zmin= Dialog.getNumber(); > >>> zmax = Dialog.getNumber(); > >>> zsteps = Dialog.getNumber(); > >>> title = Dialog.getString() > >>> //make array to hold the results for the plot > >>> xsteps = (xmax-xmin)/xstep > >>> ysteps = (ymax-ymin)/ystep > >>> zstep = (max-min)/zsteps > >>> newImage(title,"black",xsteps,ysteps,zsteps) > >>> id2=getImageID() > >>> //black should fill array with zeros > >>> // now evaluate each point in the image, and change black to > >>> // white in the new array accordingly > >>> // need to fix the below for when x and y don¹t start at zero > >>> //need to fix z ranges will miss the highest value > >>> for(x=1; x<=xsteps; x++) { > >>> for(y=1; y<=ysteps; y++) { > >>> print(y); > >>> for(z=1; z<=zsteps; z++) { > >>> selectImage(id1); > >>> zval = getPixel(x,y); > >>> if(zval>=(min+(zstep*(z-1)))){ > >>> if(zval<(min+(zstep*z))){ > >>> selectImage(id2); > >>> setPixel(x-1,y-1,1); > >>> } > >>> } > >>> } > >>> } > >>> } > >> > >> -- > >> 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 |
Free forum by Nabble | Edit this page |