我有需要可视化的 3D 图像数据。我已经能够使用 imshow3D
通过 2D 切片对其进行可视化,但我希望在 3D 空间中查看图像数据。
我使用的代码如下(礼貌: How do i create a rectangular mask at known angles? ),但我不知道为什么它不显示:
% create input image
imageSizeX = 120;
imageSizeY = 200;
imageSizeZ = 50
% generate 3D grid
[columnsInImage, rowsInImage, pagesInImage] = meshgrid(1:imageSizeX, 1:imageSizeY, 1:imageSizeZ);
% create the sphere in the image.
centerY = imageSizeY/2;
centerX = imageSizeX/2;
centerZ = imageSizeZ/2;
diameter = 56;
radius = diameter/2;
sphereVoxels = (rowsInImage - centerY).^2 ...
+ (columnsInImage - centerX).^2 + (pagesInImage - centerZ).^2 <= radius.^2;
% change image from logical to numeric labels.
Img = double(sphereVoxels);
for ii = 1:numel(Img)
if Img(ii) == 0
Img(ii) = 2; % intermediate phase voxels
end
end
% specify the desired angle
angle = 60;
% specify desired pixel height and width of solid
width = imageSizeX;
height = imageSizeY;
page = imageSizeZ;
% Find the row point at which theta will be created
y = centerY - ( radius*cos(angle * pi/180) )
% determine top of the solid bar
y0 = max(1, y-height);
% label everything from y0 to y to be = 3 (solid)
Img(y0:y, 1:width, 1:page)=3;
% figure, imshow3D(Img);
% axis on;
% grid on;
% display it using an isosurface
fv = isosurface(Img, 0);
patch(fv,'FaceColor',[0 0 .7],'EdgeColor',[0 0 1]); title('Binary volume of a sphere');
view(45,45);
axis tight;
grid on;
xlabel('x-axis [pixels]'); ylabel('y-axis [pixels]'); zlabel('z-axis [pixels]')
尽管实心条不是如下图所示的对角线,但我希望图像与此类似:
我不知道我到底做错了什么。
最佳答案
关于代码中的问题,看来您将球体内的点设置为 1,然后将球体外部的所有剩余点设置为 2,然后将 y 平面的截面设置为 3。没有值在本例中,卷中的值为 0,因此尝试获取 isosurface
值为 0 时不会找到任何内容。
但是,如果您想创建一个类似 Minecraft 的“体素化”表面,就像在示例图像中显示体素的各个方面一样,那么我为您提供了另一个选择...
首先,我按照您在示例中所做的那样创建了一组体积数据,但我省略了将值设置为 2 的 for 循环,而是将实心条的值设置为 2。
接下来,我使用了一个在我的一些 3D 项目中使用过的函数 build_voxels
:
function [X, Y, Z, C] = build_voxels(roiMask)
maskSize = size(roiMask);
% Create the ROI surface patches pointing toward -x:
index = find(diff(padarray(roiMask, [1 0 0], 'pre'), 1, 1) > 0);
[X1, Y1, Z1, C1] = make_patches([-1 -1 -1 -1], [1 1 -1 -1], [-1 1 1 -1]);
% Create the ROI surface patches pointing toward +x:
index = find(diff(padarray(roiMask, [1 0 0], 'post'), 1, 1) < 0);
[X2, Y2, Z2, C2] = make_patches([1 1 1 1], [-1 -1 1 1], [-1 1 1 -1]);
% Create the ROI surface patches pointing toward -y:
index = find(diff(padarray(roiMask, [0 1 0], 'pre'), 1, 2) > 0);
[X3, Y3, Z3, C3] = make_patches([-1 -1 1 1], [-1 -1 -1 -1], [-1 1 1 -1]);
% Create the ROI surface patches pointing toward +y:
index = find(diff(padarray(roiMask, [0 1 0], 'post'), 1, 2) < 0);
[X4, Y4, Z4, C4] = make_patches([1 1 -1 -1], [1 1 1 1], [-1 1 1 -1]);
% Create the ROI surface patches pointing toward -z:
index = find(diff(padarray(roiMask, [0 0 1], 'pre'), 1, 3) > 0);
[X5, Y5, Z5, C5] = make_patches([1 1 -1 -1], [-1 1 1 -1], [-1 -1 -1 -1]);
% Create the ROI surface patches pointing toward +z:
index = find(diff(padarray(roiMask, [0 0 1], 'post'), 1, 3) < 0);
[X6, Y6, Z6, C6] = make_patches([-1 -1 1 1], [-1 1 1 -1], [1 1 1 1]);
% Collect patch data:
X = [X1 X2 X3 X4 X5 X6];
Y = [Y1 Y2 Y3 Y4 Y5 Y6];
Z = [Z1 Z2 Z3 Z4 Z5 Z6];
C = [C1 C2 C3 C4 C5 C6];
function [Xp, Yp, Zp, Cp] = make_patches(Xo, Yo, Zo)
[Xp, Yp, Zp] = ind2sub(maskSize, index);
Xp = bsxfun(@plus, Xp, Xo./2).';
Yp = bsxfun(@plus, Yp, Yo./2).';
Zp = bsxfun(@plus, Zp, Zo./2).';
Cp = index(:).';
end
end
此函数接受 3D 矩阵,最好是要为其创建表面的体积区域的逻辑掩码,并返回 4 个 4×N 矩阵:X/Y/Z
矩阵用于体素面片和索引矩阵C
,可用于从体数据矩阵获取值以用于为每个表面着色。
这是渲染表面的代码:
[X, Y, Z, C] = build_voxels(Img > 0);
rgbData = reshape([1 0 0; 1 1 0], [2 1 3]);
hSurface = patch(X, Y, Z, rgbData(Img(C), :, :), ...
'AmbientStrength', 0.5, ...
'BackFaceLighting', 'unlit', ...
'EdgeColor', 'none', ...
'FaceLighting', 'flat');
axis equal;
axis tight;
view(45, 45);
grid on;
xlabel('x-axis (voxels)');
ylabel('y-axis (voxels)');
zlabel('z-axis (voxels)');
light('Position', get(gca, 'CameraPosition'), 'Style', 'local');
情节如下:
请注意,球体和条形表面的颜色不同,因为它们在体积数据 Img
中分别标记为值 1 和 2。这些值是使用 C
从 Img
中提取的,然后用作 rgbData
的索引,其中包含红色(第一行)和黄色(第二行) ) RGB 三元组。这将创建一个 N×1×3 矩阵 polygon face colors .
关于matlab - 如何通过 3D 图像可视化解决此问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43948680/