Detection and length measurement of 2-channels fiber signals

measure
fiji
imagej
macro
segmentation
roi
thresholding
line-roi
Tags: #<Tag:0x00007fd543f7bf50> #<Tag:0x00007fd543f7bdc0> #<Tag:0x00007fd543f7bc58> #<Tag:0x00007fd543f7baf0> #<Tag:0x00007fd543f7b9b0> #<Tag:0x00007fd543f7b848> #<Tag:0x00007fd543f7b708> #<Tag:0x00007fd543f7b528>

#1

Dear all,

I’m trying to find a good way to analyze the following signals:

As you may see from this example there are a few problems with this data:

  1. a substantial amount of background (and this is even the best sample so far…)
  2. differences in signal intensities (faint fiber signals are not of interest, ROIs in 2nd image show some signals of interest)
  3. signal quality of the signals-of-interest (signals are not continuous in most cases…)
  4. two different (sometimes overlapping) signals. Actually, not all green + red signals will be important and be analyzed. This depends on the combination of signals…

This is only one field of view of a much larger dataset (stitched images), so I’m trying to figure out a good way to pre-process and then analyze the data. But I’m currently struggling a bit to define which would be the best possibility to analyze these signals.

My idea would be to

  1. pre-process the data (i.e. remove speckled background signals), auto-threshold the remaining signals in the overlay image, make a binary mask from this image

  2. automatically detect all signals of interest (or at least all the signals that fulfill certain criteria like strong signal intensity (see ROIs in 2nd image again). You can find an example of my processing chain so far in the GIF below

  3. (automatically) measure the length of the signals. I would imagine that something like the Ridge Detection plugin can be useful here. But if I want to discriminate the two different signals (and only measure some of them depending on the combination), there might be a limit to it…

Here’s an overview of my workflow to make it easier to follow (sorry that the GIF is a bit fast):

  1. Original Image containing both signals as RGB
  2. Blurring
  3. Remove Outliers
  4. Auto Color-Threshold
  5. Make Binary
  6. Binary > Close (8 Iterations)
  7. Binary > Dilate (2 Iterations)
  8. Analyze Particles based on circularity
  9. Overlay with original signal

I don’t know if it is possible (in a relatively easy way) to do an automatic measurement, but I doubt it.

So, for now, I end up segmenting the combined signals more or less automatically (still have to wrap it up in a macro…). From that step on I will have to review all the potential signals manually and measure the ones of interest by hand, which is very time consuming. But I don’t see another possibility given that I’m now an image analysis specialist…

Does anybody have some comments for improvements or to make the workflow easier and/or more efficient? I’ve been struggling for some time now to get along but I was unable to improve it beyond that level. Although I’m proud that I’ve gotten that far :stuck_out_tongue:

Thanks and best wishes,

Patrick


Line Tool to ROI Manager with different colors
#2

Good day Patrick,

very seldom deficits in image acquisition (that are most often responsible for bad image quality) can be fully compensated for by post hoc image processing. That said, it appears that you have reached an approach that can only be slightly be improved with reasonable effort.

Please re-think image acquisition!

BTW, what about your earlier post and did my suggestion help?

Regards

Herbie


#3

Hey @Herbie,

thanks for all your answers :slight_smile:

Indeed I just replied to you in the other topic!

In this case, I guess, I can not avoid the background I get during the imaging process itself. With the data I get, I’m now trying to find a good way to analyze it in a meaningful way to avoid spending weeks/months for the manual measurements…

But there will certainly be a limit to what is possible in terms of automatic measurement.

If there are other suggestions, anyway, I’m thankful for any help :slight_smile:

Best,
Patrick


#4

Why not spend weeks or months if the task is worth it?

Seriously

Herbie (who did so for solving many scientific tasks)


#5

Haha, you are right (in principle)

But this measurement is only one experiment of my PhD project and I can not afford to spend all of the time on only this as it would not answer enough questions to get my degree :stuck_out_tongue:

It is, however, not that I don’t want to spend the time on it :wink: But I would rather spend week(s) finding ways to make the processing/analysis more straightforward!

Hope you agree :slight_smile:

Regards,
Patrick


#6

But I would rather spend week(s) finding ways to make the processing/analysis more straightforward!

As I’ve mentioned before: Improve the image quality by improving image acquisition. There is little hope for much better post hoc image analyses with reasonable effort.

An important part of a doctorate concerns planning …

Good luck

Herbie


#7

Hi Patrick - in ImageJ1 you should be able to use the Measure->Analyze particles tool, to get measurements.

You could also look into some of the ImageJ2 scripts. In the script editor under Templates->Turorials there is a script called “Ops Threshold Measure”. This goes over some of the steps you would take to measure structure in an image. It is only a template, so it won’t work perfectly on your data, you would have to learn a bit about ops and optimize the steps for your images.

If you have time constraints, you may want to just concentrate on learning about the IJ1 options for measurement (https://imagej.nih.gov/ij/docs/guide/146-30.html). If you have the time I’d highly recommend trying to write a script using ImageJ2/ops.

As a side note the “Ops Threshold Measure” script currently measures objects, but does not generate an output table. I think I noticed some people working on tables lately, is there an easy way to modify the script so the final object measurements appear in an output table??

Thanks

Brian

# @OpService ops
# @ImgPlus inputData
# @Double sigma
# @OUTPUT ImgPlus logFiltered
# @OUTPUT ImgPlus thresholded
# @OUTPUT ImgPlus labelingIndex

# Run this tutorial using the C0Z12 image generated in the 'Crop Confocal Series' tutorial.

# To generate the C0Z12 image, do the following:
# Go to 'file>Open Samples>Confocal Series' and make sure confocal-series.tif is the active image and 
# run the Crop Confocal Series tutorial.

from net.imglib2.algorithm.labeling.ConnectedComponents import StructuringElement
from net.imglib2.roi import Regions;
from net.imglib2.roi.labeling import LabelRegions;

# create a log kernel
logKernel=ops.create().kernelLog(inputData.numDimensions(), sigma);

logFiltered=ops.filter().convolve(inputData, logKernel)

# otsu threshold and display
thresholded = ops.threshold().otsu(logFiltered)

# call connected components to label each connected region
labeling=ops.labeling().cca(thresholded, StructuringElement.FOUR_CONNECTED)

# get the index image (each object will have a unique gray level)
labelingIndex=labeling.getIndexImg()

# get the collection of regions and loop through them
regions=LabelRegions(labeling)

regions_big=[]

for region in regions:
	if region.size()>20:
		regions_big.append(region)
	
for region in regions_big:
	# get the size of the region
	size=region.size()

	# get the intensity by "sampling" the intensity of the input image at the region pixels
	intensity=ops.stats().mean(Regions.sample(region, inputData)).getRealDouble()

	print "size",size,"intensity",intensity

#8

Patrick,

here is a macro that may help with your task:

// macro for length estimation in red and green channel
// begin macro
if ( bitDepth() != 24 ) exit( "RGB-image required!" );
run( "Set Measurements...", "bounding feret's display redirect=None decimal=2" );
setBatchMode( true );
run( "Duplicate...", "title=" );
w = getWidth();
h = getHeight();
if ( h < w ) sz = h; else sz = w;
sz = nextPowerOfTwo( sz );
run( "Canvas Size...", "width=" + sz + " height=" + sz + " position=Center zero" );
run( "Split Channels" );
close( " (blue)" );
newImage( "FilterFct", "32-bit", sz, sz, 1 );
fltFnct = getImageID();
run( "Specify...", "width=33 height=" + sz + " x=" + (0.5*sz) + " y=" + (0.5*sz) + " centered" );
run( "Set...", "value=1" );
run( "Select None" );
run( "Gaussian Blur...", "sigma=8" );
for ( i = 0; i < 2; i++ ) {
	if ( i < 1 ) c = " (red)"; else c = " (green)";
	selectImage( c );
	run( "Custom Filter...", "filter=FilterFct" );
	run( "Canvas Size...", "width=" + w + " height=" + h + " position=Center" );
	setAutoThreshold( "Yen dark" );
	run( "Analyze Particles...", "size=25-Infinity  add" );
	roiManager( "multi-measure append" );
	run( "From ROI Manager" );
	roiManager( "Delete" );
}
selectImage( fltFnct );
close();
setBatchMode("exit and display");
exit();
///////
function nextPowerOfTwo( size ) {
	size--;
	for ( i = 1; i <= 32; i *= 2 ) { size = size | (size >> i); }
	size++;
	return size;
}
// macro end

Paste the above macro code to an empty macro window (Plugins >> New >> Macro) and run it.

Here are the results


(red channel)


(green channel)

from the sample image:

The results table gives the widths of the selections. More meaningful for length measurements is the Feret. For the sample image they don’t differ much.
Furthermore, please realiize that these values are length estimates!

There are a number of parameters involved that allow one, within limits, to fine tune the processing.

Regards

Herbie


#9

Dear all,

although it took me some time to respond to your recent posts, and I apologize for this, I wanted to say thank you for your effort and help. I really appreciated it! This forum is a great resource and has helped me a lot.

Best,
Patrick