Enhancing grain boundaries

Hey guys,

I am working with aragonite biominerals in the SEM and trying to analyze individual grains. I want to measure size and shape through thresholding and particle analysis.

I have worked quite a lot on sample preparation to uniformally outline individual crystals. My samples hae an anisotropic arrangement and therefore grain boundaries are better defined in x-direction than in y-direction. Here you see an unprocessed example image:

You see that some of the crystas are outlined nicely, making thresholding and particle analysis easy. However some of them are still “fused together” with only minor contrast differences seperating them. I have outlined some of the cases here:

I can’t do much more regarding sampole preparation - stronger etching will cause the other crystals to lose their form, and not help much with seperating the fused crystals. I am thinking of enhancing there fused crystals with directional filtering but I am not sure where to start.

I already preprocess the images with a median / lowpass filter to remove noise. I experimented with MorphoLibJ, using a laplacian filter and substracting the result from the original image to improve contours. While it improves the contours it is still insufficient. This is why I currently use distance transform watershed to seperate these crystals, but this involves fiddling with dynamic values which I would rather avoid to ensure reproducibility.

So I am currently at my wits end regarding improvements to the image that would allow for easy thresholding - particle analysis.

Other analysis approaches I considered are Fractal Surface Measurement - whch I don’t think is suited here; Or mean line interception - of which I can’t find an automated implementation for imagej.

So any tipps you guys might have that improve the separation of individual crystals on my example image would help me tremendously.

Best regards,


Hello Cripcate,
If you just want increased separability you can accomplish that but first let me say that you should always try to work with an image without the data heading showing as it interferes with just about any of the data you wish to get based on the a histogram. Copy just the image area and create 2 new images. Invert 1 then use process > Image calculator > differences. I will be much easier than before because the dynamic range is increased.

As to your other inquiry here is an example of what can be done with your images an some of the results. All based on the average of the cited items of interest.

%232A_1Particles Results !!.csv (697 Bytes)
RoiSet.zip (85.9 KB)
Also a note on using TEM or SEM images do not dispose of the ‘noise’ because it many times will contain useful information.
I’ll write up the process if you wish and also set up analysis on this image. Remember the results attached were based on averages as to histograms, size etc. so the procedure can always be tweaked or adapted for changes.

you should always try to work with an image without the data heading

Yes, yes, I know, I sent you the absolute raw image.

My process at the moment gives me results that are more or less reproducible, and say more or less significant trends of what I would expect. It is as follows:

1. Set Scale
2. Crop the image to remove header (I do this by rectangle select 2048x2048, Crtl+Shift+X)
3. Median filter r=2 to remove the noise; I am also experimenting with a Bandpass Filter
4. Laplacian filter r=2 for an edge-enhanced version
5. Image Calculator: Original - Laplacian; Darker Version, but more pronounced contours
6. Automatic Threshold Mean White
7. Distance Transform Watershed from the MorphoLibJ Plugin. Here I tweak the Kernel and Dynamic values until it fits what I am trying to segment in the original image. I make sure the biggest Crystals are not over- or undersaturated, because I am trying to measure differences in crystal size between multiple images.

Step 7 is what I am most unhappy with because it needs tweaking of individual values and is not fully automatic. Hence the question on how to improve the vertical contours before thresholding to make this step unnecessary.
Once I determined values that work I apply it automatically to n images (10-80 per series). I create a stack of the final, segmented binary images and run analyze particles.

Im courious on hat method you used? To you have any other tipps for the process?

Thank you so much for investing the time and helping me :slight_smile:

Hello once again,
As you work with these ‘Biominerals’ I’m sure you have noticed how they change in size, shape and even intensity as you go through the layers depending on which layer and even the climate and food sources that were available to them. So you know that to be very adaptable to this will be difficult. But it can be fun and interesting.I have attached some info to see.

You will want the plug in ‘FeatureJ’. Available on the plug in site. It seems you have a good handle on it already so here we go.
After you have obtained the Histogram (and saved it) go to the peak in the graph and determine the ‘chock’ point. Where the closest gathering of pixels determine where the intensity of the pixels starts to drop. Everything above this is typically considered the outer surface, and those below are where the intersections, pores etc…start decreasing in intensity.
*Histogram-remove below ‘chock point’ (192 from the example image).I always leave the Histogram in ‘live’ mode to watch the changes as they happen.
Take the image goto Process > math > subtract,(192)
This should leave your image with a lower and shorter graph, you might then,
*Divide by max (63 in the example image), it will make the image appear black but it isn’t.
*Multiply by 250, this will give you the best dynamic range without saturating the image.
*Process > Make binary
*Featurej–Panel—Structure—select all eigenvalues options. Select the one you want but go ahead and keep all. In Statistics set Minimum, Maximum, and Element to get stats on all three sets.
Again *Process > make binary and again do all three.
*Analyze > Set Measurements > Area, Area Fraction, Shape descriptors, Ferets diameter and what ever else you want.
*Threshold—analyze particles with settings–set size obtained by all the other statistics.------Done.
Results 1st half To Send.csv (2.4 KB)

RoiSet 1st half.zip (56.1 KB)
Good luck and have fun.

Hey Bob,

thanks again for helping out! So I figured out what you’re doing until the FeatureJ part - it’s straight forward. Now what exactly does the plugin do then? I realize its calculating the eigenvalues of each pixel, to see where the biggest changes occur. And it outputs pixels with the biggest and smallest change around them, right?

If I then get the statistics on these images it outputs to the results the number of elements (pixels) and the min and max eigenvalue of those? My questions regarding this are:

  1. Do you do the eigenvalue decomposition (is it called that) a second time for the min and max eigenvalue images? So you end up with 4 images in total (max-max, max-min, min-max, min-min)?

  2. How do I use the statistics on the eigenvalues for thresholding / particle analysis, and what Image did you perform this on?

Best regards,


Good day Nils,

if you are referring to this result

onto which I’ve drawn the red circles of your original post, I wonder if you see any improvement regarding your original question.

Maybe I don’t understand what you are looking for or the above result is off the point.



Top of the day to ya Nils,
Actually I used FeatureJ to make exact copies of the interested areas. Once you get a little used to it you can decide whice size you want to use small, medium, or large. You will encounter many sizes/shapes and other changes in your research so you will know how to adapt to those changes. And actually you do not need to threshold the eigenvalue images to analyze the particles which with the Feret data and other settings will give you the angles of the particles and some others which you may or maynot need. You can also obtain other data with other settings if you wish.
No you do not need to do the eigenvalues a separate 2nd time again, you only have to make them binary a second time. The reason you only obtained 2 values is because this particular image only contained 2 values, but your previous image generated all three. You just have to keep in mind that you will sometimes have to adapt.
Just a tip that when you obtain the eigen images stop, take a breath and then decide what data you really need. Don’t try to overthink the goal you are trying to obtain. And I used the 2 original raw images you supplied, which I want to thank you for.
Play with the procedure and have fun with it, you cannot hurt anything.