Processing Images with Blob Analysis

Hi All,

I would like to come up with a Macro that reports blob area, height, and width at various thresholds for images in a collection, where the values reported are for the blob with the largest area at each threshold. I have done this previously in a different software, and I would like to do this in ImageJ. So basically, I would apply different thresholds from say 0 to 200 in increments of 10 for 10 different images, and I would like to report the area of the largest blob that is detected in those images in the resultstable. I understand that to set up the results table I can use updateResults(), and I would just like to create a table that has measurements such as Area, darkest pixel, mean pixel, height, and width for the largest blob at each threshold.

Note that a blob in this case would represent a region where all the pixels are touching together. I have attached a screenshot for a better idea for blobs at both a threshold of 120 and at 80.
80
120
I have attached an example screenshot that has an example of the output format (I would do it in a resultstable). A200 represents the area of the blob at 200, BDP200 is the darkestpixel at 200, BDP is the meanpixel at 200, H200 is the height of the blob and W200 is the width of the blob at a threshold of 200.

I have played around a little bit with ImageJ and used some Macros with regards to Edge Detection, but I would love some help with summarizing these result parameters in the resultsTable and doing the blob detection in ImageJ.
I would like to run this script for a collection of images, so any help with this problem would be greatly appreciated!

Update: I have found a macro that does the table to csv conversion here:
https://imagej.nih.gov/ij/macros/CustomTabStatFromResults.txt

The code for it is

function saveTab (path) {

	if (isOpen(windowTabName)) {
		if (path == "") {
			selectWindow (windowTabName);
			run("Input/Output...", "jpeg=75 gif=-1 file=.xls");
			saveAs("Text");
		}
		if (path != "") {
			selectWindow(windowTabName);
			saveAs("Text", path+windowTabName+".xls");
		}
	}
}

function openTab (path,name) {

	undoErease="";windowTabName=name;
	lines=split(File.openAsString(path), "\n");
	if (lines.length < 2) { exit ("This file doesn't seam to contain data");}
  	headings = lines[0];
	titlesOfColumns = split(headings, ",\t");
	nameOfStatTab="["+windowTabName+"]";
	if (isOpen(windowTabName)) {selectWindow(windowTabName) ;run("Close");}	
	firstLine="";
	for (i=0; i < (titlesOfColumns.length ); i++) {
		firstLine=firstLine+ titlesOfColumns [i];
		if ( i < (titlesOfColumns.length )-1) {firstLine=firstLine+ "\t";}
	}
	toPrint="";
	for (i=1; i < (lines.length ); i++) {
		toPrint=toPrint+lines[i]+"\n";
	}
	run("New... ", "name="+nameOfStatTab+" type=Table");
	print(nameOfStatTab, "\\Headings:"+firstLine+"");
	print(nameOfStatTab,toPrint);
}

I would just appreciate any help with finding the measurements for blobs. Thanks!

@firewater334

First - check Set Measurements to see what measures will be best suited to what you need to report.

Second - I made a little example code that incrementally changes the threshold in an image:


count = 200;
do {
	run("Dot Blot (7K)");
	setThreshold(0, count);
	run("Create Mask");
	rename("Mask_"+count);
	run("Create Selection");
	run("Measure");
	count = count - 10;
	print(count);
	run("Close All");
} while (count > 100)

It’s just an example… but at least gives you an idea of want you can do.

Third - You’ll need to search that Results table (in another loop) for whichever is the largest value you want and save/write it into another Results table - perhaps?

If you can provide us with a general workflow that you want to use in ImageJ or some example code - along with a corresponding image file - that can better help us help you.

You can definitely do this in ImageJ… but for sure - you’ll need to script it.

Here are some helpful links on segmentation and scripting:

3 Likes

Hi,

Thank you so much for your response!

The general workflow that I would want to use in ImageJ is:

  1. Create a group or collection or series (batch processing I think?) the user would select all the images they want to analyze
  2. Run each image against a for loop of thresholds and record all of the defect attributes (e.g. area, width, height, etc.). The objective would be to see what threshold allows the user to see the defect without seeing too much background noise.
  3. Display all of the results in some sort of table

The code that you provided above is actually what I would like to do just on multiple images and with more result values such as darkestpixel, mean pixel, etc. (in the screenshot of the table).

In the Set Measurements link you provided, I am assuming that darkestpixel (the measurement
I am looking for) would equate with max gray level and mean pixel would equate with mean gray value? I was just wondering how to compute those values.

I played around a bit with your code and got the threshold areas to match from my previous software, so thank you so much for that!

The format of the table that I am looking for is similar to what I have above.

Some sample images are: 632055513.bmp (1.3 KB)
632055514.bmp (1.7 KB)
632055515.bmp (1.3 KB)

Thanks again!

@firewater334

You should go through that scripting workshop I linked above. There is an example in there that is very much applicable to what you want to do here. It uses this example script to batch process images:

/*
 * Macro template to process multiple images in a folder
 */

#@ File (label = "Input directory", style = "directory") input
#@ File (label = "Output directory", style = "directory") output
#@ String (label = "File suffix", value = ".tif") suffix

processFolder(input);

// function to scan folders/subfolders/files to find files with correct suffix
function processFolder(input) {
	list = getFileList(input);
	list = Array.sort(list);
	for (i = 0; i < list.length; i++) {
		if(File.isDirectory(input + File.separator + list[i]))
			processFolder(input + File.separator + list[i]);
		if(endsWith(list[i], suffix))
			processFile(input, output, list[i]);
	}
}

function processFile(input, output, file) {
	// Do the processing here by adding YOUR OWN CODE
	// Leave the print statements until things work, then remove them.
	print("Processing: " + input + File.separator + file);
	print("Saving to: " + output);
}

So you can use this as a starting point… inserting the processing you want to do for each image in the processFile() function call. That should get you started!

1 Like