Exporting randomly generated ROIs as TIFFs

Hi,

I am trying to write a macro that will randomly select square ROI’s of 1000x1000 pixels from a histology image and export each of these to a new TIFF file. I have found a macro that does the first part of this (ie will select 20 random 1000x1000 pixel squares), however at the end of this, all it does is “Measure” and “Label” them:

run(“Select None”);

saveSettings();
original=getTitle();
setForegroundColor(255,0,0);

width = getWidth()-1000; // width of the randomly placed ROI
height = getHeight()-1000; // height of the randomly placed ROI
RoisN =20; // number of ROIs
trials=100 ; //maximum trials to avoid infinite loop

i=0;
j=0;

xa=newArray(RoisN);
ya=newArray(RoisN);

run(“Duplicate…”, “title=Reference”);

selectWindow(“Reference”);
run(“8-bit”); //makes it greyscale
run(“RGB Color”); //RGB to display colours
run(“Restore Selection”);
run(“Make Inverse”);
run(“Fill”);
run(“Select None”);

while (i<RoisN && j<trials){
w = 1000;
h = 1000;
x = random()*width;
y = random()*height;
j++;
//Check for pixels with value (255,0,0):
flag= -1;
makeRectangle(x, y, w, h);
//Scanning the rectangle perimeter should be faster than scanning the whole box.
//This is slower, as checks all the points in the box:
for (xs=x;xs<x+w;xs++){
for (ys=y;ys<y+h;ys++){
if (getPixel(xs,ys)==-65536) // pixel is (255,0,0)
flag=0;
}
}
if (flag==-1){
xa[i]=x;
ya[i]=y;
run(“Fill”);
i++;
}
}

close();
selectWindow(original);
setForegroundColor(255,255,0);
for (j=0;j<i;j++){
makeRectangle(xa[j], ya[j], w, h);
run(“Measure”);
run(“Label”);
}

Can anyone provide some guidance as to how the randomly generated squares could each be exported to their own TIFF image? ie - they would need to be named with the original file name+n appended to them.

Any help would be greatly appreciated.
Alex.

Hello Alex -

It looks like the main two missing pieces are run ("Crop");
(Image > Crop) and saveAs ("Tiff", filename);
(File > Save As > Tiff...).

Here is a complete, runnable IJM macro that uses these commands:

newImage("example", "RGB ramp", 256, 256, 1);
x = 200 * random();
y = 200 * random();
makeRectangle(x, y, 50, 50);
run ("Crop");
saveAs("Tiff", "example_1.tif");

run ("Crop") replaces the active image with a new image cropped
down to the ROI applied to it by makeRectangle().

As noted above, the saveAs ("Tiff", ...) command will
“export” the cropped image. You will have to generate your
desired filename, and pass it as the second argument to
saveAs().

I would suggest that you try to write a simple macro where all
you do is generate filenames inside of a loop and print them
out. If you have trouble with that, please post your filename
macro (ideally complete and runnable) with follow-up questions.

Thanks, mm

Hi mountain_man,

Thank you for your very prompt and helpful response.
I am still having some difficulties though - perhaps my original question wasn’t clear?

I’ve added the two lines of code you suggest to my code, and they work inasmuch as the very first randomly generated “rectangle” is cropped from the original image and saved with whatever filename I choose. Then it stops.

However, what I then need it to do is save the next randomly generated rectangle (from the original, uncropped image) as an incrementally named tif file. Is this possible post “crop”?

Again, any help would be hugely appreciated.

Slight update - I added “+ i” to the SaveAs line of code -

saveAs(“tiff”, “G:\Images\filename.tif” + i);

It now tries to export additional images from the original, but the log states “Selection is outside image” - which is obviously true post crop :wink:

Me again!
I’ve altered the code so it now copies the 1000 x 1000 pixel selection, opens a new file, pastes that selection and saves the file as the original file name. The code does this until all the randomly generated “rectangles” are saved, however it saves over the top each time, so I only have the last image.

Is there a simple way to perhaps change this line:

saveAs(“tiff”, path+original);

So that it saves the first file as original01.tif, then the second as original02.tif and so on?

Hello Alex -

Good – you’ve found a scheme that works for you for saving a
random selection from your original image as a TIFF image.

Now you need to save different random selections as different
TIFF images.

It’s often helpful to work on separate problems independently
before putting their solutions back together to form your complete
solution.

Please follow the suggestion I made in my original reply and
work on just the filenames (leave out any image processing)
and see if you can write a loop that prints out the set of filenames
you want. If you still have questions, please post the complete
filename-loop macro with a description of what is going wrong.

Thanks, mm

Here’s a simple change to a macro online (Help>Macros…) that does what you want. You can replace line 26 with your image, or just delete it and have your image open when you run the macro. Lines 105…107 are mods that save the images. Make sure that the folder is available on your machine.

The original author was
Author:
Roberto Sotto-Maior Fortes de Oliveira, MSc,PhD
email: roberto@aparelho.com

___________________macro begin

// ImageJ Macro “RandomSamplePerimeterMethod.txt”
//
// This Macro is a modification of Gabriel Landini’s RandomSampleAndMeasure.txt macro.
//
// The perimeter scan method of the retangle area is implemented here improving the
// macro’s speed as suggested by Landini.
// Now the user can interact with the code by choosing the scan method (for comparison purpose)
// and inform the parameters by a Dialog Window.
// Another improvement is the use of the setBatchMode command that’s really speed up the process.
// In this Macro, the process can be monitored by ImageJ progress bar.
//
//
// Author:
// Roberto Sotto-Maior Fortes de Oliveira, MSc,PhD
// Center of Reproductive Biology
// Juiz de Fora Federal University
// Brazil
// email: roberto@aparelho.com
//
// *The author was supported by FAPEMIG -
// Fundacao de Amparo a Pesquisa de Minas Gerais
//

newImage(“Untitled”, “8-bit noise”, 500, 500, 1);

var flag=-1;

saveSettings();
original=getTitle();
setForegroundColor(255,0,0);

setBatchMode(true);// Speed up the entire process

// create the Dialog

Dialog.create(“Random Sample Configuration Dialog”);
Dialog.addNumber(“Roi Box Size:”, 30);// This is a Box Roi; width and height are equal
Dialog.addNumber(“Number of Samples:”, 50); // Number of Samples
Dialog.addNumber(“Max.Trials:”, 1000);// avoid infinite loop
Dialog.addCheckbox(“Fill Method”, false); // Perimeter Method by Default
Dialog.addCheckbox(“Show Process”, false); // No Show by Default
Dialog.show();
RoiSize = Dialog.getNumber();
RoisN = Dialog.getNumber();
Trials = Dialog.getNumber();
Method = Dialog.getCheckbox();
ProcessShow = Dialog.getCheckbox();
//

width = getWidth()-RoiSize; // width of ROi
height = getHeight()-RoiSize; // height of ROI

i=0;
j=0;

xa=newArray(RoisN);
ya=newArray(RoisN);

if (ProcessShow==true) {
setBatchMode(false);
}

run(“Duplicate…”, “title=Reference”);
run(“8-bit”); //make it greyscale
run(“RGB Color”); //RGB to display colours

while (i<RoisN && j<Trials){

x = random()*width;
y = random()*height;
   

	makeRectangle(x, y, RoiSize, RoiSize);
	flag=-1;

//Check for pixels with value (255,0,0)

if (Method==false) {
	perimetermethod(x,y,RoiSize);// using perimeter method
} else {
	fillmethod(x,y,RoiSize); // using fill method

}

    if (flag==-1){
        xa[i]=x;
        ya[i]=y;
        run("Fill");
        i++;
    }

j++;
showProgress(j/Trials);
}

close();
selectWindow(original);
setForegroundColor(255,255,0);

for (j=0;j<i;j++){
makeRectangle(xa[j], ya[j], RoiSize, RoiSize);
run(“Duplicate…”, " “);
save(“C:\Users\rdespain\Desktop\images\”+j+”.tif");
close;

    run("Measure");
    run("Label");

}

run(“Select None”);
restoreSettings();
setBatchMode(false);

// Declared Functions

function fillmethod(u,v,t) {

    //This scan method checks all the points in the box:

    for (xs=u;xs<u+t;xs++){
        for (ys=v;ys<v+t;ys++){
	checkpixel(xs,ys);
        }
    }

}

function perimetermethod(u,v,t) {

//This scan method checks only the perimeter points of the box:    

k=0;
x2 = u+t;
y2 = v+t;

do {
x1 = u+k;
y1 = v+k;
checkpixel(x1,v);
checkpixel(x1,y2);
checkpixel(u,y1);
checkpixel(x2,y1);
k++;

}
while (k<RoiSize && flag== -1);
}

function checkpixel(u,v) {

// Check if pixel is (255,0,0)

if (getPixel(u,v)==-65536) {
	flag=0;
}

}
__________________Macro end