Overlay channels DAPI and bright-field

Hello all,

I am new to Fiji (apologies in advance…). I have photos with 2 channels (dapi and bright-field) of phytoplankton cells. I need to trace the cell size and the cell nucleus. So far, I have done all measurements manually (tracing and analysing both circles). I was wondering if I could improve things a bit. These are some options I was suggested by @VolkerH, but I am having a few issues:

  • merge channels into 1 and trace both cell nucleus and cell size from only 1 channel (issue: using Merge Channels, the dapi fluorescence is too weak and it gets lost when I overlay the bright-field photo of the cells. I tried playing with contrasts, max, min, etc. but no luck)

  • watershed to identify the nucleus, using MorphoLibJ. Works well to get either the nucleus or the cell. But it is not clear how I can use watershed to match the cells and nucleus. And importantly, is there a way to run it in batch mode?

Example attached

Thanks in advance for any help
Martino

Example.tif (16.1 MB)

Hi Martino,

I think a few of the things I mentioned got misunderstood there.
The “make composite” was suggested for visualization purposes. I am much more familiar with doing these sorts of analysis in Python or Cellprofiler but here is a quick run down on how to do it in Fiji.

  • Split the channels, rename one brightfield, and one dapi (you don’t have to do this but it helps here)
  • For the brightfield channels we want to enhance the edges. Apply a Gaussian filter first (radius 2 seems to work fine) then Process->Filter->Differentials and select Gradient Magnitude. After that you should have something like this:
  • The DAPI image will be used to create markers for the seeded watershed. Start by setting a threshold. I chose a manual threshold setThreshold(448, 65535); and apply it.
  • On the thresholded DAPI image, run Plugins->MorphlibJ->Binary Images->Connected Components Labelling
  • Remove small labels (noise) using Plugins->MorpholibJ->Label Images->Label Size Opening (100 pixels worked for me).
  • To better visualize the labels choose a different LUT, .e.g. glasbey on dark. You should have something like this:

Finally, use Plugins › MorphoLibJ › Segmentation › Marker-controlled Watershed, select the gradient image as input, select the label image as marker and uncheck binary Marker. You should see somthing like this:

Then you can run Plugins › MorphoLibJ › Analyze › Analyze Regions on both your nuclei label images and the cell label images. The labels should be the same for corresponding objects. (Alternatively use analyze particles).

An alternative to this approach would be to use Weka trainable segmentation.

This should get you started. Other members of the community will be in a much better position to help you with batching in Fiji.

I did run the macro recorder during those steps, but this is somewhat untidy and not quite in the order outlined above. Just pasting it here in case it helps. Just noticed that the macro recorder doesn’t record what type of Gradient was selected for Process -> Filter -> Differentials.

run("Split Channels");
rename("dapi");
selectWindow("C1-5d0c05c0fe3d2fcd45dd390ff4e970cd19c387bb(1).tif");
rename("transmitted");
selectWindow("dapi");
setAutoThreshold("Default dark");
//run("Threshold...");
setThreshold(448, 65535);
setOption("BlackBackground", false);
run("Convert to Mask");
run("Duplicate...", "title=markers");
run("Duplicate...", " ");
run("Connected Components Labeling", "connectivity=4 type=[16 bits]");
run("glasbey on dark");
run("Label Size Opening", "min=100");
selectWindow("markers-1-lbl");
selectWindow("transmitted");
run("Gaussian Blur...", "sigma=2");
run("Differentials");
selectWindow("markers-1-lbl-sizeOpening");
run("Marker-controlled Watershed", "input=transmitted marker=markers-1-lbl-sizeOpening mask=None calculate use");
selectWindow("transmitted-watershed");
run("Analyze Regions", "area perimeter circularity euler_number centroid inertia_ellipse ellipse_elong. convexity max._feret oriented_box oriented_box_elong. geodesic tortuosity max._inscribed_disc geodesic_elong.");
1 Like

Dear @VolkerH,

Thank you very much for your detailed answer… it helped incredibly much! I managed to write a code to reproduce all your instructions. It works on the previous image, but I am having trouble with other images.

The Marker-controlled Watershed doesn’t pick up any cells.

After I open the image (and I create an empty “Results” folder to store the output), this is the code I run:

directory = getDirectory("image")+File.separator+"Results";

selectWindow(getTitle);
rename(replace(getTitle,".lif",""));
name = getTitle;


run("Split Channels");
//saveAs("Tiff", directory+name+"_DAPI.tif");

// Work on the brightfield image
selectWindow("C1-"+name);
//saveAs("Tiff", "/Users/martinom/Downloads/brightfield.tif");

// My additions
//run("Enhance Local Contrast (CLAHE)", "blocksize=127 histogram=256 maximum=3 mask=*None* fast_(less_accurate)");
setMinAndMax(12684, 65535);
run("Subtract Background...", "rolling=50 light");

//setMinAndMax(1025, 3809);

run("Gaussian Blur...", "sigma=2");
//run("FeatureJ Edges", "compute smoothing=1.0 lower=[] higher=[]");
run("Differentials ", "operation=[Gradient Magnitude]");
//run("Differentials ", "operation=[Largest Hessian]");


// Work on the DAPI image
//selectWindow("DAPI.tif");
selectWindow("C2-"+name);
//setThreshold(448, 65535);

// To manually set the treshold
// to open the threshold window if not opened yet
run("Threshold...");
// pauses the execution and lets you access ImageJ manually
waitForUser("set the threshold and press OK, or cancel to exit macro");
// as long as you don't press OK, which resumes the macro execution

run("Convert to Mask");
// to binarize, if you use this command, don't press 'Apply' in the threshold window 

run("Connected Components Labeling", "connectivity=4 type=[16 bits]");
run("Label Size Opening", "min=200");


run("glasbey on dark");

// Save the DAPI image
//selectWindow("C2-"+replace(name,".tif","")+"-lbl-sizeOpening");// ...problematic
saveAs("Jpg", directory+File.separator+replace(name,".tif","")+"-DAPI");

// Analyze DAPI image
run("Analyze Regions", "area perimeter circularity centroid");

// Save DAPI results and close
saveAs("Results", directory+File.separator+replace(name,".tif","")+"-DAPI.csv");
run("Close");


run("Marker-controlled Watershed", "input=C1-"+replace(name,".tif","")+" marker=C2-"+replace(name,".tif","")+"-lbl-sizeOpening mask=None calculate use");
run("Analyze Regions", "area perimeter circularity centroid");

// Save results
//selectWindow("C1-"+replace(name,".tif","")+"-watershed-Morphometry"); // very problematic
saveAs("Results", directory+File.separator+replace(name,".tif","")+"-Cells.csv");
run("Close");

// I give up on adding the name of the image as a string column...
//setResult("Label", row, string);

// Save the Cell Image and close
selectWindow("C1-"+replace(name,".tif","")+"-watershed.tif");
saveAs("Jpg", directory+File.separator+replace(name,".tif","")+"-Cells");
//saveAs("Jpg", output + File.separator + filename);
close();

//close();
//close();
//close();
//close();

run("32-bit");
print("C1-"+name)
run("Merge Channels...", "c1="+getTitle+" c4=[C1-"+name+"] create");
//run("smart");
run("Flatten");
saveAs("Jpg", directory+File.separator+replace(name,".tif","")+"-COMP");
close()
close()
close()

print("Image "+name+" is COMPLETE")

C2.lif - Image009.tif (16.6 MB)

It now works! The issue when turning my code for batch analyses was about the call to Marker-controlled Watershed… somehow this function wants image names like “C1”, even if the actual name of the image in Fiji is “C1 - Image001”. Took me a while to figure out. You just have to rename() the image before calling the Marker-controlled Watershed.

Thanks hypes @VolkerH !!!

My final code is:

directory = getDirectory("image")+File.separator+"Results";

selectWindow(getTitle);
rename(replace(getTitle,".lif",""));
name = getTitle;


run("Split Channels");
//saveAs("Tiff", directory+name+"_DAPI.tif");

// Work on the brightfield image
selectWindow("C1-"+name);
//saveAs("Tiff", "/Users/martinom/Downloads/brightfield.tif");

// My additions
//run("Subtract Background...", "rolling=50 light");
//run("Enhance Local Contrast (CLAHE)", "blocksize=127 histogram=256 maximum=3 mask=*None* fast_(less_accurate)");
//setMinAndMax(12684, 65535);

//setMinAndMax(1025, 3809);
//run("Smooth");
run("Gaussian Blur...", "sigma=2");
run("Differentials ", "operation=[Gradient Magnitude]");
rename("BFDiff")

//run("Differentials ", "operation=[Largest Hessian]");

// Work on the DAPI image
//selectWindow("DAPI.tif");
selectWindow("C2-"+name);
//setThreshold(448, 65535);

// To manually set the treshold
// to open the threshold window if not opened yet
run("Threshold...");
// pauses the execution and lets you access ImageJ manually
waitForUser("set the threshold and press OK, or cancel to exit macro");
// as long as you don't press OK, which resumes the macro execution

run("Convert to Mask");
// to binarize, if you use this command, don't press 'Apply' in the threshold window 

run("Connected Components Labeling", "connectivity=4 type=[16 bits]");
run("Label Size Opening", "min=100");
run("glasbey on dark");

rename("LabelSizeOpening")

// Save the DAPI image
//selectWindow("C2-"+replace(name,".tif","")+"-lbl-sizeOpening");// ...problematic
saveAs("Jpg", directory+File.separator+replace(name,".tif","")+"-DAPI");

// Analyze DAPI image
run("Analyze Regions", "area perimeter circularity centroid");

// Save DAPI results and close
saveAs("Results", directory+File.separator+replace(name,".tif","")+"-DAPI.csv");
run("Close");

run("Marker-controlled Watershed", "input=BFDiff marker=LabelSizeOpening mask=None calculate use");
run("Analyze Regions", "area perimeter circularity centroid");

// Save results
//selectWindow("C1-"+replace(name,".tif","")+"-watershed-Morphometry"); // very problematic
saveAs("Results", directory+File.separator+replace(name,".tif","")+"-Cells.csv");
run("Close");

// I give up on adding the name of the image as a string column...
//setResult("Label", row, string);

// Save the Cell Image and close
//selectWindow("C1-"+replace(name,".tif","")+"-watershed.tif");
selectWindow("BFDiff-watershed");
saveAs("Jpg", directory+File.separator+replace(name,".tif","")+"-Cells");
//saveAs("Jpg", output + File.separator + filename);
close();

//close();
//close();
//close();
//close();

run("32-bit");
print("C1-"+name)
run("Merge Channels...", "c1=LabelSizeOpening c4=BFDiff");
//run("smart");
//run("Flatten");
saveAs("Jpg", directory+File.separator+replace(name,".tif","")+"-COMP");
close()
close()
close()

print("Image "+name+" is COMPLETE")
1 Like