【问题标题】:how to visualize a 3D matrix in MATLAB如何在 MATLAB 中可视化 3D 矩阵
【发布时间】:2012-06-15 19:10:44
【问题描述】:

我正在尝试在 MATLAB 中可视化包含 3D 数组的数据。

数组的尺寸为 20*20*40,除了一些元素为零。

我正在寻找一种方法将这些非零点绘制在散点图中,以便非零点相互连接。

这是我到目前为止所做的:

b=zeros(6,6,3);
a=[1 1 1;2 2 1;2 1 1;1 2 1;
1 1 2;1 2 2;2 1 2;2 2 2;
6 6 3;6 5 3;5 6 3;5 5 3;
6 6 2;6 5 2;5 6 2;5 5 2];
[r c]=size(a);
for i = 1:r
 b(a(i,c-2),a(i,c-1),a(i,c)) = 1;
end
[m n o]=size(b);
figure (1)
[x,y,z] = meshgrid(1:m,1:n,1:o);
scatter3(x(:),y(:),z(:),90,b(:),'filled')

所以,我所追求的是能够将八点二中的每一个连接到立方晶格。任何想法都非常感谢。

编辑: 非常感谢所有提供了很多帮助的专家。现在,我面临另一个内存问题。

我的真实案例的 b 矩阵是 1000*1000*2000 并且我有大小为 4,4700,000*3 的“a”矩阵。 “a”矩阵的所有元素都是整数值。 虽然我有高达 48GB 的​​内存可用。但是,在上面的“for循环”中,程序弹回了一个“内存不足”的错误。

非常感谢任何提高内存效率的想法。

【问题讨论】:

  • 矩阵的3维代表什么?你想用 3D 绘制它吗?您是否查看过plot3,这是显而易见的首选?

标签: matlab memory-management matrix plot visualization


【解决方案1】:

考虑以下(基于previous answer):

%# adjacency matrix
adj = false(numel(b));

%# extract first cube, and connect all its points
bb = b;
bb(:,1:3,:) = false;
idx = find(bb);
adj(idx,idx) = true;

%# extract second cube, and connect all its points
bb = b;
bb(:,4:6,:) = false;
idx = find(bb);
adj(idx,idx) = true;

%# points indices
[r c] = find(adj);
p = [r c]';

%# plot
plot3(x(p), y(p), z(p), 'LineWidth',2, 'Color',[.4 .4 1], ...
    'Marker','o', 'MarkerSize',6, ...
    'MarkerFaceColor','g', 'MarkerEdgeColor','g')
axis equal, axis vis3d, grid on, view(3)
xlabel x, ylabel y, zlabel z


编辑:

手动连接点会更容易:

%# edges: connecting points indices
p = [
    1 2; 2 8; 8 7; 7 1;
    37 38; 38 44; 44 43; 43 37;
    1 37; 2 38; 7 43; 8 44;
    65 66; 66 72; 72 71; 71 65;
    101 102; 102 108; 108 107; 107 101;
    65 101; 66 102; 71 107; 72 108
]';

%# plot
figure
plot3(x(p), y(p), z(p), 'LineWidth',2, 'Color',[.4 .4 1], ...
    'Marker','o', 'MarkerSize',6, ...
    'MarkerFaceColor','g', 'MarkerEdgeColor','g')
axis equal, axis vis3d, grid on, view(3)
xlabel x, ylabel y, zlabel z

%# label points
labels = strtrim(cellstr( num2str((1:numel(b))','%d') ));
idx = find(b);
text(x(idx(:)), y(idx(:)), z(idx(:)), labels(idx(:)), ...
    'Color','m', ...
    'VerticalAlignment','bottom', 'HorizontalAlignment','left')


EDIT#2:(感谢@tmpearce)

您可以半自动化构建边列表的过程。只需将上面代码中手动构造的matrxp替换成如下:

%# compute edges: pairs of vertex indices 
yIdx = {1:3 4:6};           %# hack to separate each cube points
p = cell(numel(yIdx),1);
for i=1:numel(yIdx)         %# for each cube
    %# find indices of vertices in this cube
    bb = b;
    bb(:,yIdx{i},:) = false;
    idx = find(bb);

    %# compute L1-distance between all pairs of vertices,
    %# and find pairs which are unit length apart
    [r,c] = find(triu(squareform(pdist([x(idx) y(idx) z(idx)],'cityblock'))==1));

    %# store the edges
    p{i} = [idx(r) idx(c)]';
end
p = cat(2,p{:});            %# merge all edges found

我们的想法是,对于每个立方体,我们计算所有顶点之间的city-block distance。 “侧”边的距离为1,而对角线的距离大于或等于2

这个过程仍然假设属于每个立方体的顶点列表提供给我们,或者像我们在上面的代码中那样轻松提取...

【讨论】:

  • 其实我也是手动连接的。只是想知道是否有更快的方法,因为有大量这样的立方体。
  • @Amro 我在补充答案中添加了一个自动查找边缘的方法。如果可能,我建议将其纳入此答案。
  • 酷,我以前没用过pdist,虽然我应该知道会有一个内置函数来做成对距离。如果原始矩阵的设置使得所有“真实”点都属于立方体,则无需遍历立方体(除非内存或计算时间对于大型矩阵来说是个问题)。
  • @tmpearce:那肯定会更“干净”(正确矢量化),但想象一下两个立方体彼此相邻,仅由一个单位隔开的情况......
  • @Amro 是的。如果您在 idx 大小的向量中有“cube members id”(可能称为mid),并使用mid(r)==mid(c) 创建逻辑索引,您可以将自己限制在多维数据集中的边缘,同时保持一切向量化。
【解决方案2】:

我想我会回答 Amro 的答案的后续内容,并展示如何自动连接沿三次矩阵的边。此答案旨在作为对 Amro 的补充,我建议将其合并到该解决方案中,以便将来的观众更容易阅读。

这从 Amro 解决方案中的 idx 开始,其中包含立方体角的线性索引。下面我只用一个立方体完成了它,所以矩阵不是很大,我们可以在这里看到它们。

>> idx' %# transposed to save space in the printed output
ans =
 1     2     7     8    37    38    43    44 '

%# now get the subindex of each point in 3D
>> [sx sy sz] = ind2sub([6 6 3],idx);
%# calculate the "edge distance" between each corner (not euclidean distance)
>> dist = abs(bsxfun(@minus,sx,sx')) +...
          abs(bsxfun(@minus,sy,sy')) +...
          abs(bsxfun(@minus,sz,sz'))
dist =

 0     1     1     2     1     2     2     3
 1     0     2     1     2     1     3     2
 1     2     0     1     2     3     1     2
 2     1     1     0     3     2     2     1
 1     2     2     3     0     1     1     2
 2     1     3     2     1     0     2     1
 2     3     1     2     1     2     0     1
 3     2     2     1     2     1     1     0 '

%# find row and column index of points one edge apart
>> [r c]=find(triu(dist==1)); %# triu means don't duplicate edges

%# create 'p' matrix like in Amro's answer
>> p = [idx(r) idx(c)]'
p =
 1     1     2     7     1     2    37     7    37     8    38    43
 2     7     8     8    37    38    38    43    43    44    44    44

为了形象化,您可以完全按照 Amro 的答案进行绘制。

【讨论】:

  • 这实际上让我想起了previous post,我们以类似的方式构造邻接矩阵...我将您的解决方案合并到我的 +1 中
【解决方案3】:

这是你需要的吗?

b=logical(b);                                  
scatter3(x(b(:)),y(b(:)),z(b(:)),90,'filled')

【讨论】:

  • 这看起来很酷。我需要的是能够连接这些立方体的 8 个角点中的每一个,以便它们形成两个立方晶格。我希望这个解释是清楚的。干杯,
  • 你能解释一下你为什么要这样做吗?也许这将有助于回答您的问题。
  • 我需要跟踪立方晶格形状的变化,因为整个结构在一些负载下。出于这个原因,我需要连接数据点。这有助于直观地了解它的形状如何变化,例如,如果它被剪断了等等......
  • @Oli: 可以用logical 代替boolean(这是一个核心的MATLAB函数,另一个需要Simulink)
猜你喜欢
  • 2013-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-20
  • 2015-02-04
  • 1970-01-01
  • 2016-03-08
相关资源
最近更新 更多