How to find 6-well plate and clear background outside of the well

Background

Hi all, here are some image of coral juveniles settle on 6-well plate, I am trying to develop a macro on imageJ to identify coral and calculate their surface area. My lab had created a macro for it. It works pretty well in identifying coral if I manually select the coral and clear the background. The macro could measure the coral surface area and count the number of coral. However, I would like to bring this further to allow the macro to automatically identify the coral out of the well plate. Here is my work so far:

Sample image and/or code

Here is the sample photo: Coral juveniles in 6-well plate. The TIF file is too big so I have to attach a link to drive.

https://myjcuedu-my.sharepoint.com/:i:/g/personal/geoffreydominic_yau_my_jcu_edu_au/EUbuUzFUKdlNihj77JSeTPwBhcy6h3JxZY9RNDSODLydZg?e=gxiqus

Here is the image J macro that my lab developed to identify coral juveniles and calculate the surface area of them.

		//store file name in nameSTore variable for later use
		nameStore = getTitle();

		roiManager("reset");

		//calibrate file based on data i was orignally given that had a 4000um scale bar in it. Assumes all images were created the same
		run("Properties...", "channels=1 slices=1 frames=1 unit=µm pixel_width=18.1818 pixel_height=18.1818 voxel_depth=18.1818");

		//create a cpy of the orginal aimage called "For Prcoessing" to perfrom various processing to extract objects
		
		run("Duplicate...", "title=["+nameStore+"]"); 


		//flatten background and convert to 8 bit for even thresholding
	
		run("Subtract Background...", "rolling=150");
		run("8-bit");

		//threshold and convert to binary mask
		setAutoThreshold("Default dark");
		setOption("BlackBackground", true);
		run("Convert to Mask");

		//analyse the obejects, filter on size and add to the ROI manager
		run("Analyze Particles...", "size=900000-100000000 circularity=0.10-1.00 display summarize add");

		//count the number of ROIs in the manager
		numROIs= roiManager("count");
		
		//Then do an if to run only when that number is greater than 1
		if (numROIs>=1){
		
		
			//copy the measured ROIs over to the orignal image and burn them into it
			selectWindow(nameStore);
		
			
			run("From ROI Manager");
			run("Flatten");

Here is the result, you can see the corals were successfully identified, but there are lots of miss judge as well due to light refraction.

Analysis goals

To avoid the macro miss judge the reflection as coral. My idea is to remove the content outside the well before I use the above macro. I have noticed there is always a circle reflection of the well, I think it will be useful for developing the script to find the well after the image become binary.

  • What information are you interested in getting from this image?

Challenges

I have looked at others work on identifying well in well plate.
https://biii.eu/find-draw-and-measure-wells-multi-well-plate-picture
I have tried to modify their script to my work but got no luck on it. It would be great if someone could point me a direction on how I should approach the situation. Thank you in advance.

Hi @geoffrey-yau,

One potential solution for the image you provided would be the following:

Open the image and start the macro…

run("8-bit");
run("Gaussian Blur...", "sigma=64");
run("Variance...", "radius=64");
run("Auto Threshold", "method=Huang");
run("Fill Holes");
run("Analyze Particles...", "size=50000-Infinity pixel circularity=0.75-1.00 exclude clear add");
run("Revert");
//in case the circle would still be too big ant touch the outer rim of the well add the following
roiManager("Select", 0);
run("Enlarge...", "enlarge=-50 pixel");	//adapt the size as needed
run("Colors...", "foreground=white background=black selection=red");
run("Clear Outside");
run("Duplicate...", " ");

Since your image is pretty big, image scaling might make it run faster since the the filter radii will become smaller. But that is just a performance matter.

After the upper part, you can simply add your existing macro and adapt as needed.

My approach might not work if the images might differ quite strongly in lighting or if the well touches the borders of images. Then you will need to adapt the macro or the imaging setup.
Edit: Additionally, in case your images do have more than only 1 well, the upper approach will also not work, since it assumes having only 1 well per image. But that could be adapted as well.

Hope that helps.

1 Like

Thank you for your help @biovoxxel I have tried it out it works really well for this photo. I will work on modifying it for my other photo which have slightly different light intensity and some of them don’t have the whole well capture. There is only one well per photos so that would not be a concern. I may come back and ask for more guidance if needed. ONce again thank you for your help and time.

I have tried with my other photos, turns out each photos are slightly different due to light condition or reflection are not blocked properly. I have tried to play with the Gaussian Blur and Variance as well as circularity to enhance the performance of the macro. It works for most first 12 photos.
Even though all my photos are taken with the same camera setting, I notices the intensity of light was reducing due to light battery and daylight are running out. This cause photo from 13 to 72 are dimer than first 12 and the macro does not account for that. I have tried to change the brightness and contrast didn’t got any luck. I am thinking is that a way that could standardize the analysis, define and set the brightness of all photos as the first 12 photos before running the analysis?

There is another problem occur in AT.A03, the foam that I made to block the refection was broken. It cause the macro can not recognize the well. is that a way to increase the tolerance of the macro?

Thank you in advance.

Here is the code I adapted, I have add a if loop to include the condition that need another set of parameter of filtering.

//add the clear outside comment to the code 

open("D:/18 Nov/AT.A14.tif");
nameStore = getTitle();

run("8-bit");
run("Duplicate...", " ");

run("Gaussian Blur...", "sigma=64");// reduce noise, smaller valuse the less blur effect, lower value under low light condition
run("Variance...", "radius=64");
run("Auto Threshold", "method=Huang");
run("Fill Holes");
run("Analyze Particles...", "size=50000-Infinity pixel circularity=0.65-1.00 exclude clear add");  // 03- 0.65 reduce the circularity> give more torleerance to non circular shape to remain. 
run("Revert");
//in case the circle would still be too big ant touch the outer rim of the well add the following
if (nResults > 1){  // check if the filtering find the well
	roiManager("Select", 0); 
}
	else { // use another set of parameter if it cannot find the well 
		selectImage(nameStore);
		run("Gaussian Blur...", "sigma=30"); // reduce noise, smaller valuse the less blur effect, lower value under low light condition
	
run("Variance...", "radius=140");
run("Auto Threshold", "method=Yen");
run("8-bit");
run("Fill Holes");
run("Analyze Particles...", "size=50000-Infinity pixel circularity=0.65-1.00 exclude clear add");  // 03- 0.65 reduce the circularity> give more torleerance to non circular shape to remain. 
run("Revert");}
//in case the circle would still be too big ant touch the outer rim of the well add the following
roiManager("Select", 0);

run("Enlarge...", "enlarge=-130 pixel");	//adapt the size as needed, larger number thicer boundry exclusion // 03-130 
run("Colors...", "foreground=white background=black selection=red");
run("Clear Outside");
run("Duplicate...", " ");
//store file name in nameSTore variable for later use
		nameStore = getTitle();

		roiManager("reset");

		//calibrate file based on data i was orignally given that had a 4000um scale bar in it. Assumes all images were created the same
		run("Properties...", "channels=1 slices=1 frames=1 unit=µm pixel_width=18.1818 pixel_height=18.1818 voxel_depth=18.1818");

		//create a cpy of the orginal aimage called "For Prcoessing" to perfrom various processing to extract objects
		
		run("Duplicate...", "title=["+nameStore+"]"); 


		//flatten background and convert to 8 bit for even thresholding
	
		run("Subtract Background...", "rolling=150");
		run("8-bit");

		//threshold and convert to binary mask
		setAutoThreshold("Default dark");
		setOption("BlackBackground", true);
		run("Convert to Mask");

		//analyse the obejects, filter on size and add to the ROI manager
		run("Analyze Particles...", "size=900000-100000000 circularity=0.10-1.00 display summarize add");

		//count the number of ROIs in the manager
		numROIs= roiManager("count");
		
		//Then do an if to run only when that number is greater than 1
		if (numROIs>=1){
		
		
			//copy the measured ROIs over to the orignal image and burn them into it
			selectWindow(nameStore);
		
			
			run("From ROI Manager");
			run("Flatten");
		selectWindow(nameStore);
		run("Close");
		selectWindow("Summary");
		run("Close");

https://myjcuedu-my.sharepoint.com/:f:/g/personal/geoffreydominic_yau_my_jcu_edu_au/EkMaWuP5xZVMsk6-awFkHxgBlP65BDmmuLaw-ZhjDfuk8w?e=Ipx9wP

Before I would try to adapt a macro (in general) to all the variabilities you might have in your images, I would first work on the imaging setup. I am aware that you have to deal with those images now, but for future imaging I would try to build a setup e.g. with a carton box over/around the imaging device or anything that makes you block out daylight or room light from the setup. Otherwise you will constantly run into the same problems and will need to constantly adapt the macro. But changing the analysis is not really a desirable option since it will make the individual analyses not comparable and if you need to change it in one analysis it becomes worse.
For non-complete wells one needs to see how to adjust the parameters to extract those but this should be possible. Here, I would also suggest for future imaging, make sure to always have complete wells in the image by positioning them centered. Because if it is not centered, the wall and its reflections in the liquid will be different on different sides of the well (also again dependent on the incoming light).
Additionally, in image 25, there is a black line below the well (from the background material). These kind of irregularities might also negatively influence any extraction, mainly of the corals you are interested in.

What might work to adapt the current situation is if you add the following line in the beginning after the 8-bit conversion:
run("Enhance Contrast...", "saturated=5 normalize");
This might reduce differences in lighting a little bit, but I tested it just shortly on 5 images.
Thereafter, the extraction of the corals might need some adaptation in addition.

1 Like

Thank you for your suggestion, this is the first time I adapt this technique in my research, I will definitely improve the method before I start the next experiment. I will try out you suggestion later on as well thank you for the help!

1 Like

What you said here is that means I should not do the for loop if possible and try to use just one analysis method to run all the photos so I can keep the analysis consistence? I have tried to adapt your suggestion it helps to improve the program to analysis photo from 13 to 72 if I increase the saturated to higher. thank you for your help

What I meant with that was, that different images should not be analyzed by using different parameter settings, because otherwise you cannot compare the results among each other. But if the macro works now on all images and recognized the wells, then it is perfectly possible to apply it to all images equally.