Measuring inhibition zones with ImageJ

Hi,

I am working on a solution for reading areas (diameters) of inhibition zones which were obtained by performing a micrbiological assay of antibiotics. Since I have to read every plate by using a ruler, I thought using ImageJ should make a big difference in accuracy and simplicity.

Now doing it in ImageJ using the measuring tool…well, it works.
However, Each plate has 36 zones and I would like to do all the 36 zones at once and that’s a bit more difficult than I thought.

I have played with threshold , FFT but didn’t get all the zones in the proper way. I also tried to use the DetectCircles plugin but that didn’t do the job either and it took quite some time to detect the zones.

I hope somebody can get me on the way. I would really help since I have to read these plates on daily base.

I will add the picture in the following post.

I tried to upload it but get an error. I will try it later again

Here is the picture. As you see it has holes in the middle but I am interested in the complete zone.

Please improve the image acquisition process:
– Illumination is uneven and differently coloured.
– Defects and reflections must be avoided (e.g. left bottom).
– Never ever use JPG-compressed images.

What type of camera and optics do you use?

With proper images, the task can easily be handled.

That is indeed not ideal.
I have to experiment with the setting to get a better picture. Hopefully it should be easier to detect.
I have used a normal camera… a mirrorless FUJI with a 20-80mm lens.

So, not using JPG? is it better to use RAW then?

Great!

This appears being well-suited.

RAW or any un-compressed or lossless format should do.
In any case, check if ImageJ can open the format.
If the camera allows one to export gray-level images, you should use this option.

Hi Ricco,
Trying to get the best possible images is always a good idea, but not all is lost. I think the brief macro code below does a pretty good job at measuring most of your circles (see below). It uses the green channel of your colour image (copying your sample image to ImageJ opened it as a stack with three channels), followed by a background subtraction to slightly even the background and a default threshold to detect the circles. The circles can then be measured with the Analyze Particle function.
The main problem is the reflection in the bottom left corner of the image. But using the Feret diameter or fit ellipse measurement options might help. You could also try to use the Hough transform to complete the circles.
Hope this helps,
Volko

Stack.setActiveChannels("010");
run("Duplicate...", " ");
run("Subtract Background...", "rolling=100 light");
setAutoThreshold("Default");
setOption("BlackBackground", true);
run("Convert to Mask");
run("Set Measurements...", "area center fit feret's redirect=None decimal=1");
run("Analyze Particles...", "size=500-Infinity show=Masks display clear include add");

image

Hi Volko,

It looks very promissing but I am not into macro’s so much. Could you please help me to set it up.
When I make a txt file with the macro and run it, I get an error: “stack required in line 1”…
I suppose I have to fill in the macro.
If you can help me a bit more step by step it would be very appreciated. Thank you for all our time.

  1. Paste the below macro code to an empty macro window (Plugins >> New >> Macro).
  2. Open the sample image in ImageJ.
  3. Run the macro code.
// "begin imagej-macro
run("Set Measurements...", "fit redirect=None decimal=2");
run("Duplicate...", " ");
run("Canvas Size...", "width="+(getWidth-50)+" height="+(getHeight-50)+" position=Center");
run("Split Channels");
close();
close();
run("Bandpass Filter...", "filter_large=500 filter_small=0 suppress=None tolerance=0");
setAutoThreshold("Default");
setOption("BlackBackground", true);
run("Convert to Mask");
run("Analyze Particles...", "size=5000-Infinity show=[Overlay Masks] display exclude clear");
run("Labels...", "color=black font=14 show bold");
d = Table.getColumn("Major");
mi = Table.getColumn("Minor");
for ( i=0; i<d.length; i++ )  d[i] = ( d[i] + mi[i] ) * 0.5;
Table.renameColumn("Angle", "Mean Diameter");
Table.setColumn("Mean Diameter", d);
exit();
// "end imagej-macro
1 Like

Hi Ricco,

When I copied your sample image into ImageJ, it opened as a three channel stacked image. However, I assume your original image format is RGB. You can covert an RGB image to an RGB stack using (Image->Type->RGB stack).
I have added this to the macro below.
To run the macro code, save it as a text or ijm file, open your image and then use Plugins->Macros->Run.
Alternatively, open a script editor (in Fiji use File->New->Script…), open/copy the code into the script editor, make sure to select Language->IJ1 Macro and then run the code from there.

Good luck,
Volko

run("RGB Stack");
Stack.setActiveChannels("100");
run("Duplicate...", " ");
run("Subtract Background...", "rolling=100 light");
setAutoThreshold("Default");
setOption("BlackBackground", true);
run("Convert to Mask");
run("Set Measurements...", "area center fit feret's redirect=None decimal=1");
run("Analyze Particles...", "size=500-Infinity show=Masks display clear include add");

Thank you so much !
It worked and it is awesome. Especially with the calculation to diameters… it is absolutely fantastic,

One very small request and hopefully it is possible, can you get the numbers in the picture in the correct following order (1,2,3 etc…)?

If not… than it’s okay anyway. I am very pleased with this already :pray:

Thank you Volko. It worked!
I am very happy with the result.

Try the following ImageJ-macro (there may be more elegant solutions):

//-- begin imagej-macro --
requires("1.53g")
run("Set Measurements...", "fit redirect=None decimal=2");
Table.reset("Results");
setBatchMode(true);
run("Duplicate...", " ");
run("Canvas Size...", "width="+(getWidth-50)+" height="+(getHeight-50)+" position=Center");
run("Split Channels"); close(); close();
run("Bandpass Filter...", "filter_large=200 filter_small=0 suppress=None tolerance=0");
setAutoThreshold("Default");
setOption("BlackBackground", true);
run("Convert to Mask");
run("Select All");
setKeyDown("alt");
yP = getProfile();
setKeyDown("none");
yP_len = mtrxStrctr(yP, true);
yP=Array.trim(yP,yP_len);
xP = getProfile();
xP_len = mtrxStrctr(xP, false);
xP=Array.trim(xP,xP_len);
dC = floor(255/((xP_len-1)*(yP_len-1)));
for ( j=0; j<yP_len-1; j++ ) {
   for ( i=0; i<xP_len-1; i++ ) {
      k = (xP_len-1)*j+i;
      makeRectangle(xP[i], yP[j], xP[i+1]-xP[i], yP[j+1]-yP[j]);
      run("Analyze Particles...", "size=5000-Infinity show=Nothing display exclude add");
      roiManager("Select", k);
      roiManager("Rename", k+1);
      c = (k+1)*dC;
      setForegroundColor(c, c, c);
      roiManager("Fill");
   }
}
roiManager("Show All");
run("Glasbey");
close("ROI Manager");
run("Labels...", "color=black font=14 show use draw bold");
d = Table.getColumn("Major");
mi = Table.getColumn("Minor");
for ( i=0; i<d.length; i++ )  d[i] = ( d[i] + mi[i] ) * 0.5;
Table.renameColumn("Angle", "Mean Diameter");
Table.setColumn("Mean Diameter", d);
setBatchMode(false );
exit();
function mtrxStrctr( a, rws ) {
  for ( i=0; i<a.length; i++ ) if (a[i]<10) a[i]=0;
   j = 1;
   for ( i=0; i<a.length-1; i++ ) {
      if ( a[i]>0 && a[i+1]==0 ) { a[j] = i; j++; }
      if ( a[i]==0 && a[i+1]>0 && j>0 ) { a[j-1]=(i+a[j-1] )*0.5;  }
   }
   a[0]=0;
   if (rws) a[j-1]=getHeight; else a[j-1]=getWidth;
   return j;
}
//-- end imagej-macro --

The table lists the diameters for every row of specimes from left to right.
Be careful with the mean diameters of specimen that are truncated in the binarized image. Use the Major diameter for those!

2 Likes

I am sorry, but it isn’t working as I hoped it would. The colored rings and the numbers are missing in the picture.
It stays in black and white without the numbers. But I far as I can see it does the job well. It measures the zones from left to right per row.

Could you please check the macro for the last time and see why it isn’t coloring and numbering the rings? With your first macro it did it well.
I really appreciate your effort.

You can’t have everything for free.
The change that was necessary for the correct sequence was considerable because “Analyze Particles…” works from top to bottom (y-coordinate).

To get what you like to see would require an ImageJ-plugin and this is really costly. Are you willing to pay for this service?

Why don’t you do it yourself?

Hi,

I fully understand. I suppose I need to get deeper into the imageJ software to understand how exactly works. Since I will use this only for determiniming the activity of antibiotics, I though maybe there a people who have done this before with little effort.

I am willing to pay for an ImageJ plugin which will do exactly what I need.
But when you say it is “really costly” then I get scared. Is this a service outside this community or is there a specific part where we can place our requests?

Anyway… still much appreciated what you have already done for me.

Corrected.
(Invoice under way)

@notQRV
Is that you Herbie?

Herbie who?

@notQRV : a real invoice :grin:?
I am still at school doing my internship at a hospital. It sounds like I have to make my first business deal in order to impress my mentor.

Do you refer to:

It appears as if he is active on another channel.