how to set decimal value to my matrix image index?

3 views (last 30 days)
I am trying to generate an 3D image of a cylinder with 0.3 cm thickness wall using matrix based on the following code,
===================================
% Set dimensions
ds = 1; % mm
xlim = ds*150/2;
ylim = xlim;
zlim = ds*210/2;
% Forms a 41x41x51 matrix
[X,Y,Z] = meshgrid(-xlim:ds:xlim,-ylim:ds:ylim,-zlim:ds:zlim);
% Convert to cm
X = X./10;
Y = Y./10;
Z = Z./10;
% A matrix (matrix of radii)
A = sqrt(X.^2 + Y.^2);
% Set center axis to 1
A(A == 0) = 1;
% Anything outside of cylinder radius (7.8 cm) set to 0
A(abs(A) > 7.8) = 0;
A(abs(A) > 7.5 & abs(A) < 7.8) = 0.1;
% Convert all non-zeros to 1 (all pts on and inside cylinder)
A(abs(A) > 0 & abs(A) < 7.5) = 0.5;
imshow3D(A);
==================================
However the numerical index value I set was always apprixmated to 0 or 1. How can I set the index value to decimal number or bigger than 1?
Any answer will be highly appreciated!

Accepted Answer

DGM
DGM on 27 Apr 2022
Edited: DGM on 27 Apr 2022
You have some problems with your code that's causing the result to not have the number of gray levels you expect. I think imshow3D() tries to do some auto-contrast stretch that's making the bad result look binarized. You should be able to use imshow3D() with the fix below, but I'm not going to use it here on the forum.
You shouldn't be writing directly to the array of radius values. Once you do that, your new values match the subsequent tests and get filled in again. Also, in order to get your two adjacent masks to meet without pinholes, they need to be exact complements. Note the use of <= and > at the boundary of adjacent regions instead of < and >.
% Set dimensions
ro = 7.8;
th = 0.3;
ri = ro-th;
ds = 1; % mm
xlim = ds*150/2;
ylim = xlim;
zlim = ds*210/2;
% Forms a 41x41x51 matrix
[X,Y,Z] = meshgrid(-xlim:ds:xlim,-ylim:ds:ylim,-zlim:ds:zlim);
% Convert to cm
X = X./10;
Y = Y./10;
Z = Z./10;
R = sqrt(X.^2 + Y.^2);
A = zeros(size(R));
% Set center axis to 1
A(R == 0) = 1;
% Anything outside of cylinder radius (7.8 cm) set to 0
A(R > ro) = 0;
A(R > ri & R <= ro) = 0.8; % i'm using a brighter color so it's easier to see here
% Convert all non-zeros to 1 (all pts on and inside cylinder)
A(R > 0 & R <= ri) = 0.5;
%imshow3D(A);
imshow(A(:,:,10))
If you don't need to keep the X,Y and Z arrays and all you need is A, then you can save a lot of time and memory by doing:
% Set dimensions
ro = 7.8;
th = 0.3;
ri = ro-th;
ds = 1; % mm
xlim = ds*150/2;
ylim = xlim;
zlim = ds*210/2;
nz = zlim*2/ds + 1;
x = -xlim:ds:xlim; % 1D
y = (-ylim:ds:ylim).'; % 1D
R = sqrt((x/10).^2 + (y/10).^2); % 2D
A = zeros(size(R));
% Set center axis to 1
A(R == 0) = 1;
% Anything outside of cylinder radius (7.8 cm) set to 0
A(R > ro) = 0;
A(R > ri & R <= ro) = 0.8; % i'm using a brighter color so it's easier to see here
% Convert all non-zeros to 1 (all pts on and inside cylinder)
A(R > 0 & R <= ri) = 0.5;
A = repmat(A,[1 1 nz]); % this is the only 3D array
%imshow3D(A);
imshow(A(:,:,10))
... but that might not be an option if you need those for coordinates.
  3 Comments
DGM
DGM on 28 Apr 2022
A few notes labeled in the comments:
1: If the interior of the cylinder and the centerline of the cylinder are both set to the same color, then that can be reduced to a single masking and assignment operation instead of multiple ones.
2: unless you potentially want a 1px hole in the center of the sphere, you don't need the R>0 test in that assignment.
Additionally, the order of the last two assignments needed to be swapped, otherwise you overwrite the sphere.
I don't know if it's intended, but the cylinder walls extend past the array boundaries. If that's not supposed to happen, you might want to adjust your limits.
ro = 7.8;
th = 0.3;
ri = ro-th;
rs = 0.6; % cm, the radius of the added sphere
sphloc = [-2.1 -3.64 -3.5];
ds = 1; % mm
xlim = ds*150/2; % 7.5cm
ylim = xlim; % 7.5cm
zlim = ds*210/2; % 10.5cm
% Forms a 41x41x51 matrix
[X,Y,Z] = meshgrid(-xlim:ds:xlim,-ylim:ds:ylim,-zlim:ds:zlim);
% Convert to cm
X = X./10;
Y = Y./10;
Z = Z./10;
R = sqrt(X.^2 + Y.^2);
R1 = sqrt((X + sphloc(1)).^2 ...
+ (Y + sphloc(2)).^2 ...
+ (Z + sphloc(3)).^2);
A = zeros(size(R));
% Set center axis to 1
%A(R == 0) = 1; % note 1
% Anything outside of cylinder radius (7.8 cm) set to 0
A(R > ro) = 0;
A(R > ri & R <= ro) = 0.5;
% Convert all non-zeros to 1 (all pts on and inside cylinder)
%A(R > 0 & R <= ri) = 1; % note 1
A(R <= ri) = 1; % note 1
% do this after you clear everything inside the cylinder
A(R1 <= rs) = 0; % note 2
%imshow3D(A);
imshow(A(:,:,141))
Regarding "Once you do that, your new values match the subsequent tests and get filled in again.":
When you make this assignment
A(abs(A) > 7.5 & abs(A) < 7.8) = 0.1
the area in the cylinder wall is 0.1, but since you're using the same array as your radius map, now that region also meets the following test and will be changed to 0.5 instead.
A(abs(A) > 0 & abs(A) < 7.5) = 0.5;
In other words, you were overwriting your reference array as you're trying to use it.
Xinjie Cao
Xinjie Cao on 28 Apr 2022
Regarding your comment,
"I don't know if it's intended, but the cylinder walls extend past the array boundaries. If that's not supposed to happen, you might want to adjust your limits."
Yes, I forgot to adjust that when I changed my cylinder size.
Many thanks to your comments, really learned a lot!

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!