使用散点图可视化大型三维数据集

3
我正在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的链接。有没有办法加快渲染并使旋转更流畅?我注意到将所有数据点的大小固定为单个标量可以大大加快渲染和旋转速度。是否可能保持代码中的大小,仍然能够快速呈现和旋转图形?

编辑:我发布了一个相关问题


需要实时处理还是可以渲染成电影(.avi)以便稍后更流畅地播放? - informaton
你的代码中每次调用之间有大约0.5秒的延迟(例如,tic/toc)。你现在的进展如何? - informaton
当我运行上面链接的代码时,toc命令输出每次迭代约9.5秒的经过时间。如果我将大小数据固定为某个标量,则每次迭代会降至约0.7秒。是否可能进一步提高速度? - Vivek Subramanian
我可以将经过时间降至5.5秒,但前提是我需要更改你的代码并将 drawnow 放在 for 循环内部(这可能是你想要看到变化的地方)。 - informaton
让我们在聊天中继续这个讨论 - informaton
显示剩余2条评论
2个回答

1
似乎计时器函数是下一步尝试以了解模拟的进展情况并在满意结果后制作AVI的好地方。MATLAB有一些很棒的文档,提供了多种连续调用和它们之间的间距选项。请查看ExecutionModePeriod属性。

0

我不确定这个方法是否能解决所有问题,但作为第一步,我建议从用于绘图的循环中取出所有计算。以下是如何执行此操作的建议:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接