How to accurately measure the height of a 3D structure?

I have a 3D data array consisting of a scan of a semi-circular sample on a flat surface. The purpose of this is to image and afterwards detect the height and width of each sample.
To do so, I wrote the following:
data_raw = load('sample.asc'); %3 columns with hundreds of rows
data_filt = imgaussfilt3(data_raw);
x = data_filt(:,1);
y = data_filt(:,2);
z = data_filt(:,3);
dotsize = 6;
scatter3(x, y, z, dotsize, z, 'filled'); %colobar linked to height (z-axis)
xlim([-6 14])
ylim([-20 -6]) %limits where the sample is
I wrote the limits above, as the original image goes from [(-60, 60), (-40, 40) ,(-10, 15)], and this included a lot of noise and unnecessary image space (especially when using the function plot3 instead of scatter3).
To try and measure the height of the sample and its width I thought of doing a simple max/min subtraction within a certain space array, but unfortunately there is enough noise that would make this not work. Is there another way of doing this?
The images below demonstrate the noise and the image before the array limits.
The image above shows all the noise around of the surface on which the sample laid on and why I applied the above limits.
The image below shows the noise still around the area of interest. How do I get the height and width (accurately) of the sample in this case?
Update:
I have attempted using imdistline and drawline the first one can only be used in a single dimension and I don't know how to obtain the lengthof the latter.

5 Comments

We would probably need data_raw in a .mat file attachment to analyze the problem in any meaningful way.
I don't have it as a .mat file but I have it as an .asc file which should work the same.
I will upload it straight away. Thanks for the help.
I have tried compressing it into a zip file but unfortuantely the file is still too big (over 5KB).
you could share it via internet (like Googledrive or alike) and share the link
I have uploaded it up in the problem desciption. Thanks for the suggestion.

Sign in to comment.

 Accepted Answer

hello
this is my rough first trial
NB that I didn't use here any surface smoothing (needs still to be implemented) but I assume you can bring that bak in the code
(I cannot use imgaussfilt3 because I don't have the corresponding toolbox)
one last detail, I draw the lower boundary line once I could remove the "noise" islands from the main shape . I don't know if you prefer to take the mean or the min of the z points belonging to that line , please choose the best option for you
hope this helps !
data_raw = readmatrix('drying_1.asc','FileType','text'); %3 columns with hundreds of rows
x = data_raw(:,1);
y = data_raw(:,2);
z = data_raw(:,3);
% "zoom" into sample area
idx = (x>-6 & x<14) & (y>-20 & y<-6);
x = x(idx);
y = y(idx);
z = z(idx);
dotsize = 6;
figure
scatter3(x, y, z, dotsize, z, 'filled'); %colobar linked to height (z-axis)
% attempt to remove outliers once x,y coordinates are transformed in polar
% coordinates
x_center = mean(x);
y_center = mean(y);
[th,r,z] = cart2pol(x-x_center,y-y_center,z);
% remove "outliers" points => find the best radius for circle fit
M = 100;
[N,EDGES] = histcounts(r,M); % uses M bins.
idx = find(N<2); % find first bin of data with very small amount of samples => "gap" between valid data and noise islands
idx = idx(1);
r_threshold = EDGES(idx); % this should be the radius of the circle that contains the valid data (outside this radius is noise)
% remove points above r_threshold
idx = (r<= r_threshold);
% convert back to cartesian coordinates
[x,y,z] = pol2cart(th(idx),r(idx),z(idx));
figure
scatter3(x, y, z, dotsize, z, 'filled'); %colobar linked to height (z-axis)
% boundary ?
k = boundary(x,y,0.5);
hold on
plot3(x(k), y(k), z(k), 'r'); %colobar linked to height (z-axis)
% height distance
% z_low = mean(z(k));
z_low = min(z(k));
z_high = max(z);
distZ = z_high - z_low

7 Comments

I don't fully understand how the use of bins or boundaries work, the code works beautifully. I will try to understand these things better.
Thank you so much for your help.
I just presume that on the second to last line it should be instead:
z_high = max(z(k));
If not, why is it not?
hello again
z_high = max(z(k)); corresponds to the max Z of the boundary (red) line , not the peak of your shape (which is max(z))
if I'm right you wanted to measure the height of that curved surface not the red line height
Uhmmm, I was trying to get the height in reference to plane it was measured in. I presumed that the red line indicated said contact with the plane, and hence could be subtracted.
I don't know what is the "reference" plane - you know better than I
just looked in the "sidewalks" , if they would represent something like this , but again, not sure
The reference plane, is just a plane on which the sample being analyzed was place, so yeah it would be that line that you drew. Perfect!
there are several "steps" so I am not quite sure which one is the true reference plane
you see my red line does not truly coincide with both sides too , I think the whole "basement" is not truly parallel to the XY plane (more noticeable seen from the side)

Sign in to comment.

More Answers (0)

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!