Segmentation of DG granule cells using trainable Weka and Watershed

Hello again! I was wondering if anyone could think of ways to improve my current segmentation method. I am using a trainable weka segmentation classifer to separate soma from dendrites and background. Currently I am mainly interested in measuring the soma, and merely need to separate out the dendrites.

I trained the Weka classifier on a stack of 3 images of different samples, but the same settings. The parameters used were median, difference of gaussian, membrane projections (membrane thickness 2) and otherwise default settings. I use the watershed irregular features plugin to separate neighboring cells in the mask created from the weka segmentation, with default settings except erosion, which is set to 20 (it seems not to change much after I increase it from 10-15).

Classifier and Lif file

This is the current segmentation after watershed.

I would also love if someone could suggest code to automate the multi measure and saving of the results? And if possible, how to exclude objects under (and over) a certain size from the results list. (Should I make a different thread about this?)

And the code:

def virtualstack():

	# Source, output and transformations directories
	source_dir = "D:\\Image_Processing\\Virtualstacks\\Lif_Stack_Split\\"
	target_dir = "D:\\Image_Processing\\Virtualstacks\\Lif_Stack_Split\\Lif_Stack_Split_aligned\\"
	transf_dir = "D:\\Image_Processing\\Virtualstacks\\Transformations\\"
	
	# Reference image (must be within source directory)
	reference_name = "Slice0MAX_sgerre.lif - Control 1 time 0 min LP 9 - C=0.tif"
	
	# Shrinkage option (False = 0)
	use_shrinking_constraint = 0
	 
	p = Register_Virtual_Stack_MT.Param()
	
	# The "maximum image size":
	p.sift.maxOctaveSize = 1024
	
	# The "inlier ratio":
	p.minInlierRatio = 0.05
	
	# Opens a dialog to set transformation options, comment out to run in default mode
	p.showDialog()

	Register_Virtual_Stack_MT.exec(source_dir, target_dir, transf_dir, 
	reference_name, p, use_shrinking_constraint)

	# Define reference image for segmentation -> ROI definition
	
	w_train = IJ.getFilePath("Select image for WEKA segmentation")
	trainer = IJ.openImage(w_train)
	weka = WekaSegmentation()
	weka.setTrainingImage(trainer)

	# Select classifier model
	weka.loadClassifier("D:\\Image_Processing\\classifier_best.model")
	weka.applyClassifier(False)
	result = weka.getClassifiedImage()

	# Convert image to 8bit
	ImageConverter(result).convertToRGB()
	ImageConverter(result).convertToGray8()

	# Threshold to show soma only
	hist = result.getProcessor().getHistogram()
	lowth = Auto_Threshold.IJDefault(hist)
	result.getProcessor().threshold(lowth)
	result.getProcessor().setThreshold(0, 0, ImageProcessor.NO_LUT_UPDATE)
	result.getProcessor().invert()
	result.show()

	# Run Watershed Irregular Features plugin, with parameters
	IJ.run(result, "Watershed Irregular Features", "erosion=20 convexity_treshold=0 separator_size=0-Infinity")

  	# Make selection and add to RoiManager	
  	RoiManager()
   	rm = RoiManager.getInstance()
   	ip = result.getProcessor()
   	rm.runCommand("reset")
	roi = ThresholdToSelection.run(result)
	result.setRoi(roi)
	rm.addRoi(roi)
	rm.runCommand("Split")
	rm.runCommand("Select All")

	IJ.selectWindow("Registered Lif_Stack_Split")
	rm.runCommand("Multi Measure")

Thank you for any advice you can offer!

Sverre

1 Like

Are you satisfied with this result? If not, what would you like to improve?

You are almost there, no? You just need to apply the same procedure for each slice and save the result table.

Either you add the area in the measurements you show per segmented object and then you post-process your tables by cleaning the objects of specific size, or you use the regular Analyze Particles that allows you to filter by size directly.

I would like to improve the separation of neighbouring cells. In this image there is only one case where two soma are registered as one, but in others there are more. This may simply be a matter of additional training?

Actually, at the moment the multi measure command will open a dialog box, but it does measure all the slices. My question put more simply, can I do this without the dialog box? I also select the image stack by name, in stead of using the separate image files saved to the Lif_stack_aligned directory. This seems a bit quirky to me, but I guess it works.

I’m sorry I don’t quite understand. Currently my output is a results window where I click save as and get an xls file (pictured below). From this file I want to remove the measurements that are based on area, clearly not soma. But as my script works now, the result is not a defined variable. So how do I edit it?

You would need to teach the classifier how to separate touching somas by providing some training samples. Another option is to find a way of separating them later as you did with watershed, but that approach is not always successful.

Yes:

resultsTable = rm.multiMeasure( result )

Yeah, you should get the file names from the LIF file or extract the whole LIF to some folder and read all files in the folder.

Either you manipulate the result table variable that I created above (resultsTable) or you save the XLS files and process them later somewhere else.

I hope this helps!

1 Like