Image processing: Determine fiber diameter

14 views (last 30 days)
Bjorn
Bjorn on 25 Apr 2018
Edited: Image Analyst on 22 May 2021

Dear reader,

A fabricated fiber structure is made visible using a SEM. The fibers in these images needs to be analyzed: I’m especially interested in the fiber thickness. It would be nice to write a Matlab-script that could do the image analysis and provides a histogram of the determined fiber thicknesses. An example of such a SEM-image is found below.

Using image thresholding and morphological opening- and closing, a binarized figure is obtained. This image is used for edge detection and skeletonization. The figure below shows the image that is obtained

The upper figure is obtained using the following code

clear all; close all; clc
I = imread('ZnAcetate.tif');
se1 = strel('disk',4);
se2 = strel('disk',1);
BI = imbinarize(I,0.4);
filter1 = imclose(BI,se1);
filter2 = imopen(filter1,se2);
inverse = imcomplement(filter2);
ED = edge(filter2,'Sobel');
skel = bwmorph(filter2,'skel',Inf);
BP = bwmorph(skel, 'branchpoints');
EP = bwmorph(skel, 'endpoints');
[y,x] = find(EP);
BP_L = find(BP);
Dmask = false(size(skel));
for k = 1:length(x)
    D = bwdistgeodesic(skel,x(k),y(k));
    distanceToBranchPt = min(D(BP_L));
    Dmask(D < distanceToBranchPt) = true;
end
skel = skel - Dmask;
figure(1)
muxing = ED | inverse;
imshowpair(muxing,skel,'blend')

At this stage, the normal distance between two parallel lines needs to be determined. The center line of each fiber should be used to determine the thickness between two real edge lines.

I have been searching the net, but I could not find a real useful example that could be implemented in this particular case. I guess a distance transformation needs to be used to determine the fiber thicknesses.

Does somebody have any suggestion how to tackle this problem?

Thank you in advance!

Kind regards,

Bjorn

Answers (8)

Felix Ruhnow
Felix Ruhnow on 17 Oct 2018
Try looking at fibermetric() in the image processing toolbox!

JBM
JBM on 15 Aug 2018
Try the DiameterJ plugin for ImageJ.

Bjorn
Bjorn on 25 Aug 2018
Dear JBM,
yes, I tried DiameterJ. However, this plugin does not allow us to do statistical analysis of any kind of the diameter of the fibers. For this reason, it is tried to write/develop the code ourselves.
Kind regards,
Bjorn

Image Analyst
Image Analyst on 25 Aug 2018
Edited: Image Analyst on 22 May 2021
To get a width distribution, use bwdist() and bwmorph().
  1. Compute the Euclidean distance transform with bwdist()
  2. Compute the skeleton with bwmorph()
  3. Multiply them together.
  4. Take the histogram of that product image to get the radius distribution.
  5. Multiply the radius values by 2 to get diameter values.
See attached demos.

Yanan Wang
Yanan Wang on 24 Apr 2019
Have you figure it out? Thanks a lot.

JBM
JBM on 24 Apr 2019
Hi all,
I've developed a script that will help you measure fibre diameters manually. If you supply the script with a 1024 x 768 pixel SEM image of a fibrous filter, the script will present you with 100 x 100 pixel sub-images containing a crosshair. You then use the MATLAB distance measure tool to meaure the diameter of the fibre whose centreline passes closest to the crosshair, and save this as a variable. Measuring about 100 fibres takes 20 minutes or so, and produces a reasonable distribution.

Bjorn
Bjorn on 24 Apr 2019
Dear JBM,
Matlab is giving me this error when I try to run the script:
d_f = [d_f distance1]
Error using eval
Undefined function or variable 'distance1'.
Error in test (line 108)
eval(['d_f = [d_f distance', int2str(i), '];']);
Perhaps it my image does not have the required contrast? I uploaded a SEM image having the required 1024 x 768 pixel size.
Kind regards,
Bjorn

JBM
JBM on 25 Apr 2019
Hi Bjorn,
Before running the section of code "Read in diameters in pixels", you need to run the section "Generate random points" at least twice.
You need to run the section "Generate random points" at least twice because when you first export the measured distance to the MATLAB workspace, the auto-generated variable name is "distance", not "distance1".
When you measure your second sub-image and export the measured distance, the auto-generated variable name is "distance1", and for the third, "distance2", and so on.
I normally try and measure ~100 fibres, and then run the "Read in diameters in pixels" section that puts the values from each auto-generated "distanceN" variable into a single variable. Adjust the value of N in the loop for however many fibres you have measured.
The use of "eval", as Image Analyst rightly points out, should in general be avoided. However in this instance it is a workaround to allow the auto-generated distance values to be read in to a single variable.
  1 Comment
Image Analyst
Image Analyst on 26 Apr 2019
One possible approach might be a modified version of what I did my Ph.D. dissertation on (vessel tracking using A*). You could drop down random boxes and then start on each of two sides of the box. Then use dynamic programming to find the path to the opposite side that has a low enough intensity standard deviation (meaning you're running along a fiber and it's not interrupted/crossed at all). If you can find such a smooth path running across the box, assume it's a fiber and then start taking perpendicular cross sections to the path and compute the widths, mean width, and width distribution. Sorry, I don't have code for it, and it will take longer than 5 minutes to code up so you're on your own.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!