How to draw a volxe size?
Show older comments
Hi, i am looking for script to calculate the crown volume of tree point cloud by the voxel size. The file input is .txt type.
I thank you in advance.
Accepted Answer
More Answers (2)
stefano chiappini
on 6 Sep 2021
0 votes
20 Comments
Walter Roberson
on 8 Sep 2021
I do not know what the third column of input represents. If it represents a z coordinate like what I plotted, then how do you want to calculate the values that are represented by color in your output ?
Are you wanting to calculate data density? https://www.mathworks.com/matlabcentral/fileexchange/31726-data-density-plot Are you wanting to calculate 2D histogram for a particular height (in order to do that, we need to know a thickness of the slice.)
stefano chiappini
on 8 Sep 2021
vox = 0.3;
cmap = colormap(parula);
T = readmatrix('https://www.mathworks.com/matlabcentral/answers/uploaded_files/730384/test%20chioma.txt');
x = T(:,1); y = T(:,2); z = T(:,3);
xidx = floor(x/vox); xbin = xidx - min(xidx) + 1;
yidx = floor(y/vox); ybin = yidx - min(yidx) + 1;
zidx = floor(z/vox); zbin = zidx - min(zidx) + 1;
xq = xidx * vox; yq = yidx * vox; zq = zidx * vox;
scatter3(xq, yq, zq)
counts = accumarray([ybin(:), xbin(:), zbin(:)], 1);
xv = (min(xidx):max(xidx)) * vox;
yv = (min(yidx):max(yidx)) * vox;
zv = (min(zidx):max(zidx)) * vox;
LV = floor(min(zv)):max(zv);
for K = 1 : length(LV)
L = LV(K);
[~, zidx] = min(abs(zv - L));
Z = counts(:,:,zidx);
Z(Z == 0) = nan;
figure();
imagesc(xv, yv, Z); colormap(cmap);
xlabel('x'); ylabel('y'); zlabel('z');
title("Z = " + LV(K));
end
stefano chiappini
on 8 Sep 2021
Edited: stefano chiappini
on 8 Sep 2021
Walter Roberson
on 8 Sep 2021
Which should be green and which should be red?
stefano chiappini
on 8 Sep 2021
Walter Roberson
on 8 Sep 2021
No, I have no ideas on how to produce those diagrams. I could make guesses, but I do not know what they represent. I especially have no idea what the red one represents.
If a, b, c are intended to represent the same tree from https://www.mathworks.com/matlabcentral/answers/1447449-how-to-draw-a-volxe-size#answer_781809 then that tree has a span of about 3 metres in height. If you count the number of vertical bands in c, there are 9, suggesting a voxelization of 0.3. But then when we look at b, with its greater subdivisions, the natural inference would be that b is intended to show voxelization with 0.3 and c is intended to show voxelization with 1.0 .
stefano chiappini
on 8 Sep 2021
Walter Roberson
on 9 Sep 2021
counts = accumarray([ybin(:), xbin(:), zbin(:)], 1);
nnz(counts) is the number of voxels that have something in them. counts at any location tells you how many hits there were, but if you are looking at "volume" from the point of view of whether a box sized vox * vox * vox could be put into the space without hitting any branch, then nnz(counts) will tell you the number of obstructed areas without telling you anything about how much obstruction is present there. You would then multiply nnz() by vox^3 to get a volume estimate.
But I am not sure that is the meaning of "volume" for this purpose. Another plausible meaning of "volume" would be to ask, if you were to "shrink-wrap" a surface over the points, then what would be the enclosed space? For that, the volume output of boundary() times vox^3 would give you the volume estimate.
It is not at all clear in diagram c what the differences in color mean. It looks sort of like it is depth cued with lighting coming from the right hand side casting shadows. So the below diagrams are effectively depth maps to the closest surface. "Front occupancy" is brightest where the closest surface is nearer to you; "Back" occupancy is darkest where the furthest surface is furthest from you. So when you look at the front, it is brightnest near the centre, reflecting the fact that it is closest to you near the centre; when you look at the back, it is darkest near the centre, reflecting the fact that it is furthest from you near the centre.
T = readmatrix('https://www.mathworks.com/matlabcentral/answers/uploaded_files/730384/test%20chioma.txt');
x = T(:,1); y = T(:,2); z = T(:,3);
voxlist = [1, 0.3];
for voxidx = 1 : length(voxlist)
vox = voxlist(voxidx);
xidx = floor(x/vox); xbin = xidx - min(xidx) + 1;
yidx = floor(y/vox); ybin = yidx - min(yidx) + 1;
zidx = floor(z/vox); zbin = zidx - min(zidx) + 1;
xb = [min(xidx), max(xidx)] * vox;
yb = [min(yidx), max(yidx)] * vox;
zb = [min(zidx), max(zidx)] * vox;
counts = accumarray([ybin(:), xbin(:), zbin(:)], 1);
occupied = counts > 0;
oidx = occupied .* (1:size(occupied,2));
oidx(oidx == 0) = nan;
froidx = permute(max(oidx,[],2), [1 3 2]);
fralpha = double(~isnan(froidx));
baoidx = permute(min(oidx,[],2), [1 3 2]);
baalpha = double(~isnan(baoidx));
maxidx = max(baoidx(:));
c = linspace(0, 1, maxidx).';
cmap = zeros(maxidx,3);
cmap(:,voxidx) = c;
figure
imagesc(xb, zb, froidx./maxidx, 'alphadata', fralpha); colormap(cmap);
xlabel('x'); ylabel('height'); title("front occupancy vox = " + vox);
figure
imagesc(xb, zb, baoidx./maxidx, 'alphadata', baalpha); colormap(cmap)
xlabel('x'); ylabel('height'); title("back occupancy vox = " + vox)
end
stefano chiappini
on 9 Sep 2021
stefano chiappini
on 9 Sep 2021
T = readmatrix('https://www.mathworks.com/matlabcentral/answers/uploaded_files/730384/test%20chioma.txt');
x = T(:,1); y = T(:,2); z = T(:,3);
voxlist = [1, 0.3];
for voxidx = 1 : length(voxlist)
vox = voxlist(voxidx);
xidx = floor(x/vox); xbin = xidx - min(xidx) + 1;
yidx = floor(y/vox); ybin = yidx - min(yidx) + 1;
zidx = floor(z/vox); zbin = zidx - min(zidx) + 1;
xb = [min(xidx), max(xidx)] * vox;
yb = [min(yidx), max(yidx)] * vox;
zb = [min(zidx), max(zidx)] * vox;
counts = accumarray([ybin(:), xbin(:), zbin(:)], 1);
voxcount = nnz(counts)
volestimate = voxcount * vox^3
occupied = counts > 0;
oidx = occupied .* (1:size(occupied,2));
oidx(oidx == 0) = nan;
froidx = permute(max(oidx,[],2), [1 3 2]);
fralpha = double(~isnan(froidx));
baoidx = permute(min(oidx,[],2), [1 3 2]);
baalpha = double(~isnan(baoidx));
maxidx = max(baoidx(:));
c = linspace(0, 1, maxidx).';
cmap = zeros(maxidx,3);
cmap(:,voxidx) = c;
figure
imagesc(xb, zb, froidx./maxidx, 'alphadata', fralpha); colormap(cmap);
xlabel('x'); ylabel('height'); title("front occupancy vox = " + vox);
figure
imagesc(xb, zb, baoidx./maxidx, 'alphadata', baalpha); colormap(cmap)
xlabel('x'); ylabel('height'); title("back occupancy vox = " + vox)
end
Walter Roberson
on 9 Sep 2021
You would get a slightly different estimate if you were to start your voxels at different places, such as min(x) or max(x) and use relative positions. The estimate I do works with absolute positions -- notice the Heights are absolute units, not relative to the bottom-most location in the point-cloud.
Walter Roberson
on 9 Sep 2021
Edited: Walter Roberson
on 10 Sep 2021
format long g
T = readmatrix('https://www.mathworks.com/matlabcentral/answers/uploaded_files/730384/test%20chioma.txt');
x = T(:,1); y = T(:,2); z = T(:,3);
voxlist = [1, 0.3];
for voxidx = 1 : length(voxlist)
vox = voxlist(voxidx)
xidx = floor(x/vox); xbin = xidx - min(xidx) + 1;
yidx = floor(y/vox); ybin = yidx - min(yidx) + 1;
zidx = floor(z/vox); zbin = zidx - min(zidx) + 1;
xq = xidx * vox; yq = yidx * vox; zq = zidx * vox;
counts = accumarray([ybin(:), xbin(:), zbin(:)], 1);
occupied = counts > 0;
oind = find(occupied);
vol_estimate = length(oind) * vox.^3
[ox, oy, oz] = ind2sub(size(occupied), oind);
oxq = (ox + min(xidx) - 1) * vox;
oyq = (oy + min(yidx) - 1) * vox;
ozq = (oz + min(zidx) - 1) * vox;
noq = length(oxq);
rF = [1 2 3 4 1; 8 7 6 5 8; 1 4 6 7 1; 2 8 5 3 2; 1 7 8 2 1; 3 5 6 4 3];
rV = [0 0 0; 1 0 0; 1 0 1; 0 0 1; 1 1 1; 0 1 1; 0 1 0; 1 1 0] * vox;
%noq = 2;
poxq = oxq(1:noq); poyq = oyq(1:noq); pozq = ozq(1:noq);
allF = repmat(rF, noq, 1) + 8*repelem((0:noq-1).', size(rF,1), 1);
allV = repelem([poxq, poyq, pozq], size(rV,1), 1) + repmat(rV, noq, 1);
cmap = zeros(1,3);
cmap(:,voxidx) = 1;
figure
patch('Faces', allF, 'Vertices', allV, 'FaceColor', cmap, 'LineWidth', 0.1)
title("vox = " + vox)
view(3)
end
stefano chiappini
on 9 Sep 2021
Walter Roberson
on 10 Sep 2021
I updated to output the volume estimate.
By the way, the reason that vox 1 is done before vox 0.3, is that it made it easier to figure out which color to use for the drawing. The first vox processed writes 1.0 into column 1 of the colormap, producing red. The second vox processed writes 1.0 into the column 2 of the colormap, producing green. If you had another vox then it would write into column 3, producing blue; if you went to more colors than that, you would need a minor revision to be able to specify the colors.
stefano chiappini
on 10 Sep 2021
Walter Roberson
on 10 Sep 2021
I have had a lot of practice answering questions ;-)
stefano chiappini
on 10 Sep 2021
stefano chiappini
on 9 Sep 2021
Edited: Walter Roberson
on 9 Sep 2021
0 votes
3 Comments
Walter Roberson
on 9 Sep 2021
No. There is no way to make your data look like that diagram.
stefano chiappini
on 9 Sep 2021
Edited: stefano chiappini
on 9 Sep 2021
Walter Roberson
on 9 Sep 2021
The result of fopen() is a file identifier, which is a scalar integer. You then try to take the first three columns of that scalar integer.
Categories
Find more on Labeling, Segmentation, and Detection in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!




















