ImageJ stack to images & rename images - macros

I have a small problem with imagej:
I have .tif files in a folder, which consist of three different files (blue channel, green channel, red channel).
I would like to convert them to separate pictures, then to only keep the green one
I want to do this with a macro, but i can't get it to work.
I can open the .tif, then convert it to separate images (Image-0001, Image-0002 and Image-0003). But then i want to rename them to blueImage, greenImage and redImage.
Googling got me to this, but this one saves the images as separate files and it gives an error.
macro split_color{
dir1 = getDirectory("InputDir");
list = getFileList(dir1);
dir2 = getDirectory("OutpurDir");
for (i=0; i<list.length; i++) {
open(dir1+list[i]);
title1=File.nameWithoutExtension;
for (j=1; j<=3; j++){
run("Stack to Images")
" slices="+j);
run("8-bit");
if (j==1) c = "blue";
else if(j==2) c = "green";
else c = "red";
saveAs("tif", dir2+title1+"-"+c+".tif");
wait(100);
close();
}
close();
}
showMessage("Macro is finished");
}
I can't get this to work, anyone who could help me?
Thanks

Related

ImageJ: Wrong transferrence of Coordinates from picture to picture

for my Thesis I must count cells on pictures stained with Immunofluorescence and I am writing a macro in ImageJ to do it for me.
For this I coloursplit the picture, analyse particles in the red channel (my Antibody´s colour) and then I want to take the coordinates of analysed particles and only count them if at the same coordinates in the blue channel there is also a staining (DAPI - just a general cell staining).
This way I assure that there is as little dirt counted as possible.
The problem is that when I get the coordinates from the results table and use them to makePoint(x,y) the coordinates are "distorted" - usually the correct coordinates but plus 4ish, though never in exactly the same, which is why i can´t simply distract a number from the coordinates
Below I first write down the critical lines of code, then the whole code.
Thank you very much in advance
run("Analyze Particles...", " circularity=r1-r2 display clear in_situ");
roiManager("deselect");
z=nResults;
for (j=0; j<z; j++) { //loops through the Results table and adds to "counter" if a match is found
selectImage(channelsplit[2]); //selects blue window
setThreshold(d,l);
run("Threshold...");
setOption("BlackBackground", true);
run("Convert to Mask", "method=Default background=Default black");
run("Coordinates...", "left=0 right=19373 top=0 bottom=13600"); //I tried to set the boundaries of the pictures equally, but it didnt work
makePoint(getResult("X", j)), (getResult("Y", j));
print ("X" + j + ": " + getResult("X",j)); //this and the following line are not to be in the program, once it works
print ("Y" + j + ": " + getResult("Y",j));
run ("Measure");
if (getResult("Mean", nResults-1)>100) {
counter++;
}
} //for j
print (i + ": " + counter);
setBatchMode(true);
if (isOpen("ROI Manager")) {
r=roiManager("count");
} else {
setBatchMode(false);
exit("You need a ROI Manager open with the ROIs of all the pictures to be measured");
}
Dialog.create ("Variables")
Dialog.addCheckbox ("red", true);
Dialog.addCheckbox ("green", false);
Dialog.addCheckbox ("blue", false);
Dialog.addCheckbox ("watershed", true);
Dialog.addNumber ("Thresholddark:", 110);
Dialog.addNumber ("Thresholdlight:", 255);
Dialog.addNumber ("greenThresholddark:", 110);
Dialog.addNumber ("greenThresholdlight:", 253);
Dialog.addNumber ("pmin:", 15);
Dialog.addNumber ("pmax:", 100);
Dialog.addNumber ("roundness1:", 0.5);
Dialog.addNumber ("roundness2:", 1.0);
Dialog.addMessage("batch - select 'true' for your macro to run faster, but you will not see what it does until finished\nstack - selecht this box if you use unstacked pictures and want them stacked, deselect if you use a readied stack or a single picture\nred - select this box if you want to count red coloured cells \ngreen - select this box if you want to count green coloured cells \nblue - select this box if you want to count blue coloured cells\nall variables are the same for the colours you count. It may be better to adjust variables for each colour and count seperately\nwatershed - select this box only if you have overlapping cells in your image\nThresholdlight - particles lighter than this won't be measured/counted \nThresholddark - particles darker than this won't be measured/counted \nThresholdlight and Thresholddark can be between 0 and 255 \ntry thresholding manually at least once manually to get best results \npmin - particles with a size smaller than this won't be counted \npmax - particles with a size greater than this won't be counted")
Dialog.show ();
cr=Dialog.getCheckbox();
cg=Dialog.getCheckbox();
cb=Dialog.getCheckbox();
w=Dialog.getCheckbox();
d=Dialog.getNumber();
l=Dialog.getNumber();
dg=Dialog.getNumber();
lg=Dialog.getNumber();
pmin=Dialog.getNumber();
pmax=Dialog.getNumber();
r1=Dialog.getNumber();
r2=Dialog.getNumber();
dir = getDirectory("Choose a Directory "); //choose the folder with all the pictures to be measured
listFiles(dir); //I found this in a listFiles recursively Demo and changed it to open my pictures
function listFiles(dir) {
list = getFileList(dir);
for (o=0; o<list.length; o++) { //loops through the file list, opening then analysing then closing one after another
if (endsWith(list[o], "/")) {
listFiles(""+dir+list[i]);
} else {
open(dir + list[o]);
//the previous opens all pictures in a given folder in a way i do not understand
//I only use this function because I could not use the variable list.length outside of it for unknown reasons
//following is my cellcount program to be executed for each picture
//then the picture will be closed before the new one is opened
run("Split Channels");
channelsplit = getList("image.titles");
if (cr==1) {
a=0;
}
if (cg==1) {
a=1;
}
selectImage(channelsplit[a]); //selects red or green window, depending on input in the Dialog
setThreshold(d,l);
run("Threshold...");
setOption("BlackBackground", true);
run("Convert to Mask", "method=Default background=Default black");
run("Coordinates...", "left=0 right=19373 top=0 bottom=13600");
for (i=2*o; i<=((2*o)+1); i++) { //loops through two ROIs of the ROIManager
counter=0;
selectImage(channelsplit[a]);
roiManager("deselect");
roiManager("select", i);
if (w==1) {
run("Watershed", "slice");
}
run("Analyze Particles...", " circularity=r1-r2 display clear in_situ");
roiManager("deselect");
z=nResults;
for (j=0; j<z; j++) { //loops through the Results table and adds to "counter" if a match is found
selectImage(channelsplit[2]); //selects blue window
setThreshold(d,l);
run("Threshold...");
setOption("BlackBackground", true);
run("Convert to Mask", "method=Default background=Default black");
run("Coordinates...", "left=0 right=19373 top=0 bottom=13600"); //I tried to set the boundaries of the pictures equally, but it didnt work
makePoint(getResult("X", j)), (getResult("Y", j));
print ("X" + j + ": " + getResult("X",j)); //this and the following line are not to be in the program, once it works
print ("Y" + j + ": " + getResult("Y",j));
run ("Measure");
if (getResult("Mean", nResults-1)>100) {
counter++;
}
} //for j
print (i + ": " + counter);
close("Results"); //closes Results to get the variables in order for the next window
// IJ.renameResults("res" + i);
} //for i
close("*"); //closes all image windows to save RAM
} //else
} //for o
} //function
setBatchMode(false);

Macro for multiple images analysis in the calculator plus

I have a set of images in a folder which their names are: 2 days.bmp 3 days.bmp ..... 28 days.bmp. Also, I have a folder with the background images exactly with the same names. I want to use the calculator plus and divide each image to its relevant background. I want to save time and do that at the same time instead of doing it for each image one by one. Is there any idea how can I do that? I have written a macro but it didn't work for me.
macro "Batch calculate images [1]" {
LocationOfFiles = getDirectory("Select Folder");
LocationOfbackgrounds = getDirectory("Select Folder of backgrounds");
LocationOfSave = getDirectory("Select Save Location");
setBatchMode(true);
FileList = getFileList(LocationOfFiles);
NumberOfFiles = FileList.length;
for (i=0; i<NumberOfFiles; i+=1) {
FileName = FileList[i];
pathtofile1 = LocationOfFiles+FileName;
open(pathtofile1);
name1 = getTitle();
pathtofile2 = LocationOfbackgrounds+FileName;
open(pathtofile2);
name2 = getTitle();
run("Calculator Plus", "i1="+name1+" i2="+name2+" operation=[Divide: i2 = (i1/i2) x k1 + k2] k1=255 k2=0 create");
selectWindow("Result");
SaveName = replace(name, ".bmp", "_backgroud subtracted.jpg");
saveAs("BMP", LocationOfSave+SaveName);
selectWindow(BackgroundImage);
close("\\Others");

How to batch combine 2 photos into 1 in python

I'm trying to find a way to batch combine multiple pairs of images into a single image horizontally. I have a folder of hundreds of photos (img01, img02,etc) and I'm trying to merge pairs of these:
img1 + img2 --> img1_2
img 519 + img 520 --> img519_520
The images are 3 x 4 inches and I want to combine them into pairs of horizontal 6 x 4 inch images.
I have found a way to do this for 2 specific photos but I don't know how to loop the code for all the photos in my image folder and save this as a 6x4 photo.
import numpy as np
from PIL import Image
images_list = ['img52.JPG', 'img53.JPG']
imgs = [ Image.open(i) for i in images_list ]
min_img_shape = sorted( [(np.sum(i.size), i.size ) for i in imgs])[0][1]
img_merge = np.hstack( (np.asarray( i.resize(min_img_shape,Image.ANTIALIAS) ) for i in imgs )
img_merge = Image.fromarray( img_merge)
img_merge.save( 'Merged image.jpg' )
I am using a Mac OS High Sierra 10.13.4 and python Python 3.6.4.
Any help would be really appreciated!
Source of the above code: https://kanoki.org/2017/07/12/merge-images-with-python/
Update (as of 12 April 2018):
The following should work for a folder with an even number of photos, where the photos are named: img1.jpg, img2.jpg, etc. The script will take a pair of photos (e.g. img1.jpg and img2.jpg) and combine them.
#Note: I run the program in terminal after I change directory to my folder.
import numpy as np
from PIL import Image
images_list = []
for i in range(1,78): #insert last number of photo + 1 (in this case, I have 77 photos)
images_list.append('img'+str(i)+'.JPG')
count = 1;
directory = "path of directory" #change to directory where your photos are
ext = ".jpg"
new_file_name = "vimage-" #change to what you would like to name your photos
new_directory = "path of directory" # change to path of new directory where you want your photos to be saved
for j in range(0,len(images_list),2):
name = new_file_name + str(j) + ext
two_images_list = [images_list[j],images_list[j+1]]
imgs = [ Image.open(i) for i in two_images_list ]
min_img_shape = sorted( [(np.sum(i.size), i.size ) for i in imgs])[0][1]
imgs_comb = np.hstack( (np.asarray( i.resize(min_img_shape) ) for i in imgs ) )
imgs_comb = Image.fromarray( imgs_comb)
imgs_comb.save(new_directory+'/'+name )
count +=1
Thanks a lot to #C. Tim for the helpful response!
Update (as of 12 April 2018):
If your images have a name as "img01.JPG", "img42.JPG", this code should work :
you generate all the names and put them in a list. For each pair of images your algorithm converts them into one image and the name of the images created change for every pair.
You must have an even number of images and the images need to be of the same dimension. Thanks a lot to #C. Tim for the helpful response.
# Note: I run the program in terminal after I change directory to my folder.
import numpy as np
from PIL import Image
images_list = []
for i in range(1,78): #insert last number of photo
images_list.append('img'+str(i)+'.JPG')
count = 1;
directory = "path of photos to resize" #change to directory where your photos are
ext = ".jpg"
new_file_name = "vimage-"
new_directory = "path to save in" # change to path of new directory where you want your photos to be saved
for j in range(0,len(images_list),2):
name = new_file_name + str(j) + ext
two_images_list = [images_list[j],images_list[j+1]]
imgs = [ Image.open(i) for i in two_images_list ]
min_img_shape = sorted( [(np.sum(i.size), i.size ) for i in imgs])[0][1]
imgs_comb = np.hstack( (np.asarray( i.resize(min_img_shape) ) for i in imgs ) )
imgs_comb = Image.fromarray( imgs_comb)
imgs_comb.save(new_directory+'/'+name )
count +=1

Strange filename import behavior in ImageJ macro

I'm writing an ImageJ macro to iterate through a folder of .lsm confocal microscope images, make a Z Project from each, combine the two channels into red and green, and save as an RGB image. The code works fine for one directory, but now it's throwing an error that has something to do with the filename from getFileList.
Here's the relevant part of the code:
dir1 = getDirectory("Choose Source Directory ");
format = getFormat();
dir2 = getDirectory("Choose Destination Directory ");
list = getFileList(dir1);
setBatchMode(true);
for (i = 0; i < list.length; i++) {
showProgress(i+1, list.length);
open(dir1+list[i]);
run("Z Project...", "projection=[Max Intensity]");
run("Split Channels");
run("Merge Channels...", "c1=C1-MAX_" + list[i] + " c2=C2-MAX_" + list[i]);
saveAs(format, dir2 + list[i]);
close();
}
It's necessary that "C1-MAX_" is appended to the input string because those prefixes are added to the image name during the calls to Z Project and Split Channels.
For reference, the name of the files look like Negative 1 5x.lsm, Negative 2 5x.lsm, Positive 1 5x.lsm, etc. Based on these filenames, I expect ImageJ to call the Merge Channels command with the strings "C1-MAX_Negative 1 5x.lsm" and "C2-MAX_Negative 1 5x.lsm".
Instead, I get the error message "C1-MAX_Negative" is not a valid choice for "C1 (red):"
I don't understand why ImageJ is trying to call Merge Channels with the string "C1-MAX_Negative" and not "C1-MAX_Negative 1 5x.lsm". Why isn't list[i] returning what I think it should?
It is probably because of the space in the filename. Try putting the name in square brackets like that:
run("Merge Channels...", "c1=[C1-MAX_" + list[i] + "] c2=[C2-MAX_" + list[i] + "]");

Match Tesseract-OCR results to .uzn regions

When specifying the regions using a .uzn file, is there a way to then match the text output to the .uzn region where the text came from?
I found a way to do it by getting the bounding boxes for each character, and using that information to see which region every character belongs to.
// Load the .box file output by Tesseract-OCR, and match each bounding box
// to a character from the text. This is not trivial, because whitespaces
// are present in the text from the .txt, but are missing from the .box
// file.
std::vector<RECT> loadBoxFile(const wchar_t *fileName, const std::wstring &text, int imageHeight)
{
// Open file.
std::ifstream st(fileName);
if (!st.is_open())
throw std::runtime_error("Could not open .box file.");
std::string line;
std::string symbolAscii;
std::wstring symbol;
RECT r = { -1, -1, -1, -1 };
std::vector<RECT> ret;
ret.resize(text.size(), r);
size_t textPos = 0;
while (std::getline(st, line)) {
// Parse a line.
std::istringstream iss(line);
if (!(iss >> symbolAscii >> r.left >> r.top >> r.right >> r.bottom))
throw std::runtime_error("Could not parse .box file line.");
symbol = utf8to16(symbolAscii.c_str());
// We don't try to get the bounding box for '~', because sometimes
// there is a '~' in .box file that is not there in .txt file. It's
// a bug in Tesseract-OCR as far as I know. This is a workaround
// for that case.
if (L"~" == symbol)
continue;
// Now match the symbol for that line to a symbol in the .txt file.
textPos = text.find(symbol, textPos);
// If we couldn't match it then fail.
if (text.npos == textPos)
throw std::runtime_error(std::string() + "Could not match symbol \"" + symbolAscii + "\" from .box file to .txt file.");
// Write the bounding box in the array, at index matching the symbol
// in the .txt file.
r.bottom = imageHeight - r.bottom;
r.top = imageHeight - r.top;
for (int ii = 0; ii < symbol.size(); ii++)
ret[textPos + ii] = r;
// Now increment textPos() so we start searching after the last
// symbol of the currently found symbol.
textPos += symbol.size();
}
return ret;
}