Commit fea52317 authored by Karel Štěpka's avatar Karel Štěpka
Browse files

Added contrast enhancement to the empty region detection. Applied "keep only...

Added contrast enhancement to the empty region detection. Applied "keep only the largest component" to the empty regions of the first image. Fixed a minor bug when selecting a starting image that was not included in the analysis.
parent ae25fa73
Loading
Loading
Loading
Loading
+42 −7
Original line number Original line Diff line number Diff line
@@ -18,6 +18,16 @@ open("d:/Scratch Assay/Images/2025-03-05 KER/25_1_t24.JPG");






*/

/*

TODO: (General TODO notes.)

In the first image of a series, try to pick only the one largest component (assume the gap is unbroken in the first image).

In each subsequent image, try intersection of empty regions from that image with a dilated version of the empty regions from the previous image (dilation radius as a parameter linked to cell size).

*/
*/




@@ -243,9 +253,13 @@ function readSettingsFromSetupDialog() {
	firstImageTitle = Dialog.getChoice();
	firstImageTitle = Dialog.getChoice();
	
	
	// Determine which images should be analyzed based on the individual checkboxes.
	// Determine which images should be analyzed based on the individual checkboxes.
	firstImageTitleFound = false;
	for (i = 0; i < imageList.length; i++) {
	for (i = 0; i < imageList.length; i++) {
		if (Dialog.getCheckbox()) {
		if (Dialog.getCheckbox()) {
			imagesToAnalyze = Array.concat(imagesToAnalyze, imageList[i]);
			imagesToAnalyze = Array.concat(imagesToAnalyze, imageList[i]);
			if (imageList[i] == firstImageTitle) {
				firstImageTitleFound = true;
			}
		}
		}
	}
	}
		
		
@@ -262,11 +276,13 @@ function readSettingsFromSetupDialog() {
		}
		}
	}
	}


	// Make sure the starting image is the first element of imagesToAnalyze.
	// If firstImageTitle was found among the images to process, make sure it is the first element of imagesToAnalyze.
	if (firstImageTitleFound) {
		imagesToAnalyze = Array.concat(firstImageTitle, Array.deleteValue(imagesToAnalyze, firstImageTitle));
		imagesToAnalyze = Array.concat(firstImageTitle, Array.deleteValue(imagesToAnalyze, firstImageTitle));
	}
	
	
	// Print out which images will be analyzed.
	// Print out which images will be analyzed.
	print("These images were selected for analysis:" );
	print("The images will be analyzed in this order:" );
	for (i = 0; i < imagesToAnalyze.length; i++) {
	for (i = 0; i < imagesToAnalyze.length; i++) {
		print(imagesToAnalyze[i]);
		print(imagesToAnalyze[i]);
	}
	}
@@ -764,6 +780,15 @@ function processImage(imageIndex, imageToAnalyzeTitle) {
	run("Duplicate...", "title=[" + greyscaleImageToAnalyzeTitle + "]");
	run("Duplicate...", "title=[" + greyscaleImageToAnalyzeTitle + "]");
	run("8-bit");
	run("8-bit");


// Try to enhance the contrast of the cells while also smoothing the
//run("Enhance Contrast...", "saturated=0 normalize");
//run("Enhance Contrast...", "saturated=5 normalize");
//run("Enhance Contrast...", "saturated=10 normalize");
run("Enhance Contrast...", "saturated=20 normalize");  // High values of "saturated" (up to 20 was tested) seem to help with low-contrast images.
run("Median...", "radius=5");  // TODO: Median radius should be smaller than the cell size. (About one third of the SE size used for morphological gradient/opening seems to work.)
//waitForUser("");


	// Find the fiducials and the area between them.
	// Find the fiducials and the area between them.
	findFiducials(imageIndex, imageToAnalyzeTitle, greyscaleImageToAnalyzeTitle);
	findFiducials(imageIndex, imageToAnalyzeTitle, greyscaleImageToAnalyzeTitle);
	
	
@@ -826,7 +851,7 @@ function processImage(imageIndex, imageToAnalyzeTitle) {
	
	
	
	
	// Calculate the image gradient.
	// Calculate the image gradient.
	run("Morphological Filters", "operation=Gradient element=Disk radius=15");  // TODO: Radius should be related to the actual cell diameter in the image. (Version B: morphological gradient)
	run("Morphological Filters", "operation=Gradient element=Disk radius=15");  // TODO: Radius should be related to the actual cell diameter in the image.
	gapImageToAnalyzeTitle = intermediateDebugImagePrefix + "Gap" + "_" + imageToAnalyzeTitle;
	gapImageToAnalyzeTitle = intermediateDebugImagePrefix + "Gap" + "_" + imageToAnalyzeTitle;
	rename(gapImageToAnalyzeTitle);
	rename(gapImageToAnalyzeTitle);
	
	
@@ -844,6 +869,16 @@ function processImage(imageIndex, imageToAnalyzeTitle) {
	run("Convert to Mask");
	run("Convert to Mask");
	// Refine the gap mask.
	// Refine the gap mask.
	run("Fill Holes (Binary/Gray)");
	run("Fill Holes (Binary/Gray)");


	// Morphological opening.
	run("Morphological Filters", "operation=Opening element=Disk radius=15");  // TODO: Radius should be related to the actual cell diameter in the image. Possibly the same value as used for the gradient computation.
	// TODO: Treat the gap mask in the first image of a series differently -- keep only the largest component.
	if (imageIndex == 0) {
		run("Keep Largest Region");
	}	


	run("Area Opening", "pixel=15000");  // TODO: The area parameter of this area opening should be related to the actual cell diameter in the image.
	run("Area Opening", "pixel=15000");  // TODO: The area parameter of this area opening should be related to the actual cell diameter in the image.
	// Convert the mask into a selection and store it.
	// Convert the mask into a selection and store it.
	run("Create Selection");
	run("Create Selection");