【问题标题】:Visualizing large 3D dataset with scatter plot使用散点图可视化大型 3D 数据集
【发布时间】:2017-08-06 00:14:26
【问题描述】:

我正在 MATLAB 中运行模拟,其中我有一个大型 3D 数据集,每个时间步都会发生变化。我正在尝试使用 3D 散点图来可视化数据,其中的点随着模拟的进行而呈现不同的位置、大小、颜色和透明度级别。尺寸和颜色信息是多余的。

在 MATLAB 中渲染和旋转图形既慢又不稳定。我的电脑有一个 4 GHz i7-4790 CPU 和一个 NVIDIA GeForce GTX 750 Ti 显卡。我在 Windows 7 上使用 Matlab R2016a。我检查了我的 MATLAB OpenGL 设置,硬件支持级别已满。 (硬件 OpenGL 是透明所必需的。)此外,我正在使用 GPU-Z 监控我的 GPU 使用情况,在绘图和旋转期间,GPU 负载峰值仅为 25-30%。

这是我的代码示例:

load sample_data2
channels_matrix = cat(1, channels{:});
num_channels = length(channels);
channel_lengths = cellfun(@(x) size(x, 1), channels);

figure(1);
for i = 1:num_channels
    g = plot3(channels{i}(:, 1), channels{i}(:, 2), channels{i}(:, 3), 'k');
    set(g, 'LineWidth', 1.5)
    hold on;
    text(channels{i}(1, 1), channels{i}(1, 2), channels{i}(1, 3), num2str(i))
end
caxis([0 1])
colorbar
drawnow

numDivisions = 8;
ptsPerDivision = numel(grid_x)/numDivisions;
T = 1000;
numplotpts = 2E4;
for t = 1:T
    plot_signal = nan(size(grid_x));
    plot_signal(sort(randsample(numel(grid_x), numplotpts))) =...
        sort(rand(numplotpts, 1));
    tic
    for i = 1:numDivisions
        temp = plot_signal(dists_idx((i-1)*ptsPerDivision+1:i*ptsPerDivision));
        yplot = grid_y(dists_idx((i-1)*ptsPerDivision+1:i*ptsPerDivision));
        xplot = grid_x(dists_idx((i-1)*ptsPerDivision+1:i*ptsPerDivision));
        zplot = grid_z(dists_idx((i-1)*ptsPerDivision+1:i*ptsPerDivision));
        if t == 1
            h(i) = scatter3(yplot(~isnan(temp)), xplot(~isnan(temp)),...
                zplot(~isnan(temp)), 50*temp(~isnan(temp)), temp(~isnan(temp)), ...
                'filled', 'MarkerFaceAlpha', exp(-i)^0.25);
        else
            h(i).XData = yplot(~isnan(temp));
            h(i).YData = xplot(~isnan(temp));
            h(i).ZData = zplot(~isnan(temp));
            h(i).SizeData = 50*temp(~isnan(temp));
            h(i).CData = temp(~isnan(temp));
        end
    end
    drawnow
    toc
end

这里是data 的链接。有什么方法可以加快渲染速度并使旋转更平滑?我注意到将所有数据点的大小固定为单个标量可以大大加快渲染和旋转速度。是否可以保持代码中的大小,并且仍然可以快速渲染和旋转图形?

编辑:我发布了一个related question

【问题讨论】:

  • 是否需要实时播放,或者您可以将其渲染为电影 (.avi) 以便以后更流畅地播放?
  • 实时不是必需的,但最好。
  • 我在您的代码(例如 tic/toc)中的调用之间出现了大约 0.5 秒的延迟。你现在在做什么?
  • 当我运行上面链接的代码时,toc 命令输出每次迭代大约 9.5 秒的经过时间。如果我将大小数据固定为某个标量,则每次迭代它会下降到大约 0.7 秒。是否有可能进一步加速?
  • 我可以使经过的时间下降到 5.5 秒,但前提是我更改您的代码并将 drawnow 放入 for 循环中(这可能是您希望它看到更改的地方)。

标签: matlab 3d data-visualization matlab-figure scatter-plot


【解决方案1】:

听起来timer 函数是一个很好的下一步尝试的地方,以便了解模拟的进展情况,然后在对事物的外观感到满意后制作 AVI。

MATLAB 有一些很棒的documentation,它有多种用于连续调用的选项以及它们之间的间距。查看ExecutionModePeriod 属性。

【讨论】:

    【解决方案2】:

    我不确定这是否能解决所有问题,但作为第一步,我建议将所有计算从用于绘图的循环中取出。这里有一个建议:

    load sample_data2
    clf
    channels_matrix = cat(1, channels{:});
    num_channels = length(channels);
    channel_lengths = cellfun(@(x) size(x, 1), channels);
    
    figure(1);
    for k = 1:num_channels
        g = plot3(channels{k}(:, 1), channels{k}(:, 2), channels{k}(:, 3), 'k');
        set(g, 'LineWidth', 1.5)
        hold on;
        text(channels{k}(1, 1), channels{k}(1, 2), channels{k}(1, 3), num2str(k))
    end
    caxis([0 1])
    colorbar
    drawnow
    
    numDivisions = 8;
    ptsPerDivision = numel(grid_x)/numDivisions;
    T = 1000;
    numplotpts = 2E4;
    
    % -> chnages starts here:
    
    % first loop for creating random indices
    plot_signal = nan(size(grid_x));
    rand_numplotpts =sort(rand(numplotpts,T),1);
    rand_inds = zeros(numplotpts,T);
    for t = 1:T % one loop for creating random indices
        rand_inds(:,t) = sort(randperm(numel(grid_x),numplotpts));
    end
    plot_signal(rand_inds(:,t)) = rand_numplotpts(:,t);
    
    % second loop for drawing the first instance:
    for k = 1:numDivisions
        temp = plot_signal(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
        yplot = grid_y(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
        xplot = grid_x(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
        zplot = grid_z(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
        h(k) = scatter3(yplot(~isnan(temp)), xplot(~isnan(temp)),...
            zplot(~isnan(temp)), 50*temp(~isnan(temp)), temp(~isnan(temp)), ...
            'filled', 'MarkerFaceAlpha', exp(-k)^0.25);
    end
    
    % third loop to calculate all timesteps:
    [X,Y,Z,S,C] = deal(nan(size(temp,1),numDivisions,T));
    for t = 2:T 
        plot_signal(rand_inds(:,t)) = rand_numplotpts(:,t);
        for k = 1:numDivisions
            temp = plot_signal(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
            yplot = grid_y(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
            xplot = grid_x(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
            zplot = grid_z(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
            non_nan_inds = ~isnan(temp);
            inds = 1:sum(non_nan_inds);
            X(inds,k,t) = yplot(non_nan_inds);
            Y(inds,k,t) = xplot(non_nan_inds);
            Z(inds,k,t) = zplot(non_nan_inds);
            S(inds,k,t) = 50*temp(non_nan_inds);
            C(inds,k,t) = temp(non_nan_inds);
        end
    end
    
    % forth loop to draw all data:
    for t = 2:T
        for k = 1:numDivisions
            h(k).XData = Y(:,k,t);
            h(k).YData = X(:,k,t);
            h(k).ZData = Z(:,k,t);
            h(k).SizeData = S(:,k,t);
            h(k).CData = C(:,k,t);
            drawnow
        end
    end
    

    【讨论】:

      猜你喜欢
      • 2019-03-05
      • 1970-01-01
      • 2021-09-03
      • 2013-11-01
      • 1970-01-01
      • 2019-11-30
      • 1970-01-01
      • 2021-01-27
      • 2020-03-25
      相关资源
      最近更新 更多