Error in batch merging images (x.tif is not a valid choice for "C2 (green):") - imagej

I want to merge two sets of fluorescence microscope images into a green & blue image, but I'm having trouble with the macro (haven't used ImageJ before). I have a folder of FITC-images to be coloured green and a folder of DAPI-images to be coloured blue. I have been using this modified version of a macro I found online:
macro "batch_merge_channel"{
count = 1;
setBatchMode(true);
file1= getDirectory("Choose a Directory");
list1= getFileList(file1);
n1=lengthOf(list1);
file2= getDirectory("Choose a Directory");
list2= getFileList(file2);
n2=lengthOf(list2);
open(file1+list1[1]);
open(file2+list2[1]);
small = n1;
if(small<n2)
small = n2;
for(i=0;i<small;i++)
{
run("Merge Channels...", "c2="+list1[1]+ " c3="+list2[1]+ " keep");
name = substring(list1, 0, 13)+")_merge";
saveAs("tiff", "C:\\Merge\\"+name);
first += 2;
close();
setBatchMode(false);
}
This, however returns an error
x.tif is not a valid choice for "C2 (green):"
with x being the name of the first file in the first folder.
If I merge the images manually, two by two, there is no error. So I'm presuming the problem is in the macro code.
I found several cases of this error online, but none of the solutions that seemed to work for those people work for me.
Any help would be appreciated!

In case you didn't solve this already, a great place to get help on ImageJ questions is the forum.
I can suggest a couple of ideas:
Is your image successfully opened by the macro? You could set the batch mode to false to check this.
It looks to me like the for loop does not employ the variable i. It works on the first pair of
images (list1[1], list2[1]), then closes the merged image, but then
tries to process image 1 again. To actually loop through all the
images in the folder, you have to put inside the loop something
like this (you don't need 'keep' -- better to leave it out so the source images will automatically be closed)
open(file1+list1[i]);
open(file2+list2[i]);
run("Merge Channels...", "c2="+list1[i]+ " c3="+list2[i]);
-- Turning off batch mode should be done after the loop, not within the loop.
Here's a version that works for me.
// #File(label = "Green images", style = "directory") file1
// #File(label = "Blue images", style = "directory") file2
// #File(label = "Output directory", style = "directory") output
// Do not delete or move the top 3 lines! They contain essential parameters
setBatchMode(true);
list1= getFileList(file1);
n1=lengthOf(list1);
print("n1 = ",n1);
list2= getFileList(file2);
n2=lengthOf(list2);
small = n1;
if(small<n2)
small = n2;
for(i=0;i<small;i++)
{
image1=list1[i];
image2=list2[i];
open(file1+File.separator+list1[i]);
open(file2+File.separator+list2[i]);
print("processing image",i);
run("Merge Channels...", "c2=&image1 c3=&image2");
name = substring(image1, 0, 13)+"_merge";
saveAs("tiff", output+File.separator+name);
close();
}
setBatchMode(false);
Hope this helps.

Related

ImageJ/Fiji - Save CSV using macro

I am not a coder but trying to turn ThunderSTORM's batch process into an automated one where I have a single input folder and a single output folder.
input_directory = newArray("C:\\Users\\me\\Desktop\\Images");
output_directory = ("C:\\Users\\me\\Desktop\\Results");
for(i = 0; i < input_directory.length; i++) {
open(input_directory[i]);
originalName = getTitle();
originalNameWithoutExt = replace( originalName , ".tif" , "" );
fileName = originalNameWithoutExt;
run("Run analysis", "filter=[Wavelet filter (B-Spline)] scale=2.0 order=3 detector "+
"detector=[Local maximum] connectivity=8-neighbourhood threshold=std(Wave.F1) "+
"estimator=[PSF: Integrated Gaussian] sigma=1.6 method=[Weighted Least squares] fitradius=3 mfaenabled=false "+
"renderer=[Averaged shifted histograms] magnification=5.0 colorizez=true shifts=2 "+
"repaint=50 threed=false");
saveAs(fileName+"_Results", output_directory);
}
This probably looks like a huge mess but the original batch file used arrays and I can't figure out what that is. Taking it out brakes it so I left it in. The main issues I have revolve around the saveAs part not working.
Using run("Export Results") works but I need to manually pick a location and file name. I tried to set this up to take the file name and rename it to the generic image name so it can save a CSV using that name.
Any help pointing out why I'm a moron? I would also love to only open one file at a time (this opens them all) and close it when the analysis is complete. But I will settle for that happening on a different day if I can just manage to save the damn CSV automatically.
For the most part, I broke the code a whole bunch of times but it's in a working condition like this.
I appreciate any and all help. Thank you!

Extraction text as csv from scanned pdf file using tesseract

enter image description hereI need help to extract text from scanned pdf. I have tried to extract it using pymupdf and pillow and pytesseract, but I am not getting correct results, there are some text are returned incorrectly.
I tried to increase sharpness and brightness but still did not get a good result.
I have already checked many answers using OpenCV, but I am fairly new to OpenCV. Please help.
def pdf_to_text(pdf_file,text_file_name,rotate_pdf=False,adj_sharpness=False,adj_contract=False,adj_brightness=False):
try:
doc = fitz.open(pdf_file)
zoom_x=2.5
zoom_y=2.5
mat = fitz.Matrix(zoom_x,zoom_y)
files = []
for n in range(doc.page_count):
#print(f'Extracting {n} image')
page = doc.load_page(n)
if rotate_pdf:
page.set_rotation(-90)
#pix = page.get_pixmap(dpi=600)
pix = page.get_pixmap(alpha=False,matrix=mat,dpi=300)
folder=os.path.join(os.getcwd(),"images")
if not os.path.exists(folder):
os.makedirs(folder)
fname = os.path.join(folder,"page-%i.png"%n)
pix.save(fname)
im = Image.open(fname)
im = adjust_sharpness(im,2.5)
im = adjust_brightness(im,1.1)
im = adjust_contrast(im,2.8)
#im = im.filter(ImageFilter.SMOOTH)
im.save(fname)
#remove_lines(fname)
files.append(fname)
#if n>1:
# break
print("Extracting Images Completed")
print("Now Extracting data from image file")
for file in files:
#file = "./images/page-0.png"
text = image_to_string(file, lang_code="eng")
#text = image_to_string(file, lang_code="fra+eng")
make_textfile(text, text_file_name)
print("Extracting and saving text files completed")
except FileNotFoundError:
print(f"File not available {pdf_file}")
return None
pytesseract.image_to_string(image=Image.open(image_name))
The image:
To process tables in Tesseract you are likely to need to remove table lines to help the OCR engine with the segmentation of the image. However, you may try this first to see how Tesseract will perform.
text = image_to_data(file, lang="eng", config="--psm 6")
This will treat your image as a block to avoid missing as much text as possible, but removing the lines and binarizing the image will lead to better results. This link would help you with the removal of lines.

Releasing Mat images with openCV(.release() and =Mat() doesn't work)

I have tried to release a Mat image from my program, however, no matter how I tried it, the same image (result) still appear when I click on the "process button" to process another image (from loading or snapping an image). The old results will always be displayed.
I have to close the whole program, open the next image I want to process and click the "process button" to get the actual result. However, this is not ideal, as I want my program to immediately process the image I load or snap and not having to close the whole program(or rather stop run and click run again)
Most of the results I searched from google suggested these methods:
imagep.release(); //where imagep is the image after going through processing
imagep=Mat();
UPDATE:
My code is goes something along this line. In my program.h file, the image and image p and declared like this:
class program : public QMainWindow
{
Q_OBJECT
public:
program(QWidget *parent = 0);
~program();
cv::Mat image, imagep; //original image and image processed
The coding for the button in the .cpp file goes something like this:
imagep = image.clone(); //also tried: imagep=image, and imagep=image+0 already.
.
.
.
processing/segmenting steps
.
.
cv::imshow("new image", imagep);
cvWaitKey(10);
imagep=Mat(); //also tried cvDestroyWindow("new image"), //imagep.release();
The setting of the picture of imagep(where I changed the values of the pixels based on results from the image processing. ) is created via:
for (int i=0; i< imagep.rows; ++i)
{
for (int j=0; j<imagep.cols; ++j)
{
//imagep.at<cv::Vec3b>(i,j)= v_char[i]; Note that this is commented. This method doesn't work, hence the below method. But it doesn't work too.
Vec3b temp=v_char[i];
imagep.at<cv::Vec3b>(i,j)[0]=temp[0];
imagep.at<cv::Vec3b>(i,j)[1]=temp[1];
imagep.at<cv::Vec3b>(i,j)[2]=temp[2];
}
}
However, these methods doesn't work. Any suggestions of how I can release the Mat image?
waitKey(-1) wait for a keyboard input while waitKey(10) uses 10 ms to update UI and then passes to control further on; It seems to that your problem is not release but proper update.
Normally one don’t need to release Mat (though I saw some release() calls in Java), just reassign it. Your problem may also be related to smart pointers that got killed when the number of references goes to zero but it is hard to say without seeing your code.
There are some tricky things happening when creating, assigning, and declaring Mats. Also, note for example that Mat m = n, copies the reference only but Mat m = n + 0, copies the whole object.

HOW to add histo in ROOT-framework?

i choose to ask a question here well aware that i can infringe some rules of StackExchange maybe becouse this isn't the right place to ask that, but i saw a lot of question related to CERN ROOT. I know that here people that answer the questions prefer to show the way instead to give a cooked solution, but i need some help and i have no time to learn from the answers, i only want a solution for my problem. I apologize in advance!
Here is my problem: i have two .root files:
one of a spectrum ("sezione_misura_90.root"),
one from background ("sezione_fondo_90.root").
I have to subtract the second from the first and get a final histogram. Usually i open the file with the TBroswer and i have no idea how to implement a macro of a script to open a .root file or doing everything else, first of all becouse i hate ROOT and all programming related, and i have only a course where i am supposed to use that, without someone tell me how!!! Even the prof. don't know how to use...
If some one that read have a macro or a script ready to use, I will be forever indebted to him for sharing that with me. Thanks in advance!
EDIT
I write down a file named run.cxx with the following lines
int run()
{
// Open both files side-by-side
TFile* sezione_misura_90 = new TFile("sezione_misura_90.root");
TFile* sezione_fondo_90 = new TFile("sezione_fondo_90.root");
// Get the histograms from the file
// Since you didn't say from your post, I'm going to assume that
// the histograms are called "hist" and that they hold floating
// point values (meaning, they're TH1F histograms. The "F" means float)
TH1F* h_misura = (TH1F*) sezione_misura_90->Get("hist");
TH1F* h_fondo = (TH1F*) sezione_fondo_90->Get("hist");
// Now we add them together
TH1F* h_sum = h_misura->Add(*h_fondo, -1);
}
There was some typos like ( and ;, i correct them but i get back the following.
Error: illegal pointer to class object h_misura 0x0 139 run.cxx:21:
** Interpreter error recovered **
A simple way to accomplish this is to write a script that opens the two files, reads the histograms from the files, and subtracts them (which is the same as adding them using a factor of -1). This can be done using a block of code similar to the following:
{
// Open both files side-by-side
TFile* sezione_misura_90 = new TFile("sezione_misura_90.root");
TFile* sezione_fondo_90 = new TFile(("sezione_fondo_90.root");
// Get the histograms from the file
// Since you didn't say from your post, I'm going to assume that
// the histograms are called "hist" and that they hold floating
// point values (meaning, they're TH1F histograms. The "F" means float)
TH1F* h_misura = (TH1F*) sezione_misura_90->Get("hist");
TH1F* h_fondo = (TH1F*) sezione_fondo_90->Get("hist");
// Now we add them together
TH1F* h_sum = h_misura->Add(*h_fondo, -1);
}
At this point, h_sum should be the histogram you want. You can save it to a file for later reading, or you can draw it to the screen if you're running an interactive root session.
The above code can be run by doing one of the following:
An interactive root session just by typing root and then typing the above lines)
As a root script (by pasting them into a file which, for example, could be named "file.C" and typing "root file.C")
A larger program (by putting the above lines in a function and calling that function)
You can read more about the methods available for a Histogram in ROOT's documentation:
http://root.cern.ch/root/html/TH1.html#TH1:Add#1
Hope that helps.
I see at least two problems. One problem has to do with the way ROOT manages memory, more specifically ROOT objects in memory:
// Each ROOT object derives from a TNamed class,
// hence has a <name>, which ROOT uses internally
// to keep track of the objects
TH1F* h_misura = (TH1F*) sezione_misura_90->Get("hist");
// now you have a histogram named "hist" in memory;
//btw, better to name it something more unique, e.g. hist1, at least
TH1F* h_fondo = (TH1F*) sezione_fondo_90->Get("hist");
// And now, you are trying to get another histogram named "hist",
// which creates a problem: Two different histograms with the same
// name - you can't do that.
// At the very least ROOT is going to overwrite the first hist
// and replace it with the second, or bug out
Solution to problem one:
// Rename the "hist"s to something like "hist1" and "hist2"
TH1F* h_misura = (TH1F*) sezione_misura_90->Get("hist");
h_misura->SetName("hist1");
TH1F* h_fondo = (TH1F*) sezione_fondo_90->Get("hist");
h_fondo->SetName("hist2");
// now, you have to histograms in memory with unique names
Problem two: when you open a TFile with
// TFile * f = new TFile("file.root");
it opens it in a read-only mode, therefore you can't write to them if you want to save your sum of histograms. Instead do this:
TFile * f = TFile::Open("file.root", "write");
// and do a null pointer check
if (!f) { std::cout << "file not found" << std::endl; exit(1); }
// if you want to save the results to file f
// ...
f->cd();
hist->Write();
f->Close();

pixFRET - running the plugin for time lapse images // looping?

I just recently started to work with ImageJ (and thus do not have much experience with macro programming) to analyze my microscopy pictures.
In order to generate FRET pixel-by-pixel images that are corrected for spectral bleed through I am using the plug in: pixFRET. This plug in requires a stack of 3 images to work: FRET, Donor, Acceptor. So far, I have to open every picture myself and this is REALLY inconvenient for large time stacks (> 1000 images). I am looking for a way to loop the plug in or create some kind of macro to do this.
A short description of my Data structure:
workfolder\filename_t001c1 (Channel 1 Image - Donor at time point 001),
filename_t001c2 (Channel 2 Image - FRET at time point 001),
...t001c3 (can be neglected)
...t001c4 (Channel 4 Image - Acceptor at time point 001).
I would have to create a stack of C2/C1/C4 at each time point that is automatically analyzed by pixFRET (with set parameters) and the result should be saved in an output folder.
I am grateful for every suggestion as my biggest problem is the looping of this whole stack generation/pixFRET analysis (can only do this manual right now).
Thanks
David
I did not find a way to directly include the parameters and commands from the pixFRET PlugIn. However, here I show a work around that works with IJ_Robot to add these commands. I further included some stuff to perform a alignment of the camera channels based on the first images of the time series.
// Macro for creating time resolved pixFRET images with a alignment of both cameras used
// a separate setting file is required for pixFRET -> put this into the same folder as the pixFRET plugin
// the background region has to be set manually in this macro
// IJ_robot uses cursor movements - DO NOT move the cursor while excuting the macro + adjust IJ_robot coordinates when changing the resolution/system.
dir = getDirectory("Select Directory");
list = getFileList(dir);
//single alignment
run("Image Sequence...", "open=[dir] number=2 starting=1 increment=1 scale=100 file=[] or=[] sort");
rename(File.getName(dir));
WindowTitle=getTitle()
rename(WindowTitle+toString(" Main"))
MainWindow=getTitle()
NSlices=getSliceNumber()
xValue=getWidth()/2
yValue=getHeight()/2
//setTool("rectangle");
makeRectangle(0, 0, xValue, yValue);
run("Align slices in stack...", "method=5 windowsizex="+toString(xValue*2-20)+" windowsizey="+toString(yValue*2-20)+" x0=10 y0=10 swindow=0 ref.slice=1 show=true");
selectWindow("Results");
XShift=getResult("dX", 0);
YShift=getResult("dY", 0);
File.makeDirectory(toString(File.getParent(dir))+toString("\\")+"test"+" FRET");
for(i=0;i<list.length;i+=4){
open(dir+list[i+1]);
run("Translate...", "x=XShift y=YShift interpolation=None stack");
open(dir+list[i]);
open(dir+list[i+3]);
run("Translate...", "x=XShift y=YShift interpolation=None stack");
wait(1000);
run("Images to Stack", "name=Stack title=[] use");
selectWindow("Stack");
makeRectangle(15, 147, 82, 75); //background region
run("PixFRET...");
run("IJ Robot", "order=Left_Click x_point=886 y_point=321 delay=500 keypress=[]");
run("IJ Robot", "order=Left_Click x_point=874 y_point=557 delay=500 keypress=[]");
selectWindow("NFRET (x100) of Stack");
save(toString(File.getParent(dir))+toString("\\")+"test"+" FRET"+toString(i) +".tif");
selectWindow("Stack");
close();
selectWindow("FRET of Stack");
close();
selectWindow("NFRET (x100) of Stack");
close();
run("IJ Robot", "order=Left_Click x_point=941 y_point=57 delay=300 keypress=[]");
}
Thanks for your help Jan. If you can think of a way to call these pixFRET commands directly rather than using Ij_robot, please let me know.
Take this tutorial from Fiji (is just ImageJ) as a starting point, and use the macro recorder (Plugins > Macros > Record...) to get the neccessary commands.
Your macro code could then look something like this:
function pixfret(path, commonfilename) {
open(path + commonfilename + "c2");
open(path + commonfilename + "c1");
open(path + commonfilename + "c4");
run("Images to Stack", "name=Stack title=[] use");
run("PixFRET"); // please adjust this to your needs
}
setBatchMode(true);
n_timepoints = 999;
dir = "/path/to/your/images/";
for (i = 0; i < n_timepoints; i++)
pixfret(dir, "filename_t" + IJ.pad(i, 4));
setBatchMode(false);
Hope that helps.

Resources