在MATLAB中使用自定义色彩映射生成3D干图

时间:2015-03-30 14:48:33

标签: matlab plot

我有一个矩阵(200 x 4),其中前3个值是XYZ数据。我想使用第四列显示每个(X,Y,Z)三元组,以便它映射到一种颜色。

第四列包含0.0到1.0(200个值)的值。我想手动和线性地使用colormap映射这些值。最小值应为蓝色,最大值可以为红色。

我知道可以使用scatter3。但是,我想使用stem3,我可以从colormap手动指定颜色。

有没有办法在MATLAB中做到这一点?

2 个答案:

答案 0 :(得分:3)

这很简单。 kkuilla发布了一个非常有见地的链接。要开始一些事情,如果你想要一个颜色从蓝色变为红色的地图,你知道图像被分解为三种颜色:红色,绿色和蓝色。

因此,您所要做的就是改变红色和蓝色通道。从纯蓝色开始,RGB = (0,0,255)将其映射到w = 0的初始权重,并将其更改为RGB = (255,0,0)w = 1的结尾。您可以通过linspace轻松完成此操作。但是,用于在MATLAB中绘图的颜色图中的颜色是规范化,因此它们介于[0,1]之间,而不是[0,255]之间。另外,因为MATLAB中的颜色映射是N x 3的矩阵,其中N是您想要的颜色总数,您所要做的就是:

num_colours = 10;
colourmap = [linspace(0,1,num_colours).' zeros(num_colours,1) linspace(1,0,num_colours).'];
weights = linspace(0,1,num_colours);

num_colours是您要显示的颜色总数。我把它设置为10让你开始。 weights是我们以后需要的东西,所以不要担心这个问题。基本上,colormap将是您应用于数据的颜色映射。

然而,现在困难的是您正在绘制的数据与数据本身(或数据的第四列)的权重无关。这意味着您无法简单地使用(X,Y,Z)数据来确定stem中每个地块的颜色。通常对于MATLAB中的彩色图,柱的高度与显示的颜色成比例。对于数据中最大的Z值,这自然会分配给颜色映射末尾的颜色或红色。数据中最小的Z值自然会在颜色映射的开头指定,或者为蓝色。

如果是这种情况,您只需要进行一次stem调用,并将颜色映射指定为Color的属性。因为Z值的高度与您为每个数据点分配的权重之间没有相关性,所以除了循环通过每个点之外别无选择并确定具有每个权重的点的权重与最终颜色映射中的每种颜色之间的最接近值,然后将此最接近的颜色分别应用于stem中的每个点。

我们使用上面生成的weights向量确定最近的点。我们可以将每种颜色视为具有[0,1]的映射,并且每个权重对应于colourmap中的颜色。因此,权重0是颜色映射中的第一种颜色,并且是第一行中的第一种颜色。此后的下一个重量是第二种颜色,第二行中的重量等等......所以我们只需要确定矩阵第四列中每个重量的最接近的位置对于上面的weights向量。这将确定我们需要从颜色图中选择哪种颜色来绘制点。

鉴于200 x 4的矩阵存储在data中,您必须专门执行此操作:

%// Spawn a new figure
figure;
%// Determine the number of points in the dataset
num_points = size(data,1);
%// For each point in the data set
for idx = 1 : num_points
    %// Get 4th column element and determine closest colour
    w = data(idx,4);
    [~,ind] = min(abs(weights-w));
    color = colourmap(ind,:);

    %// Plot a stem at this point and change the colour of the stem
    %// as well as the marker edge colour and face colour       
    stem3(data(idx,1), data(idx,2), data(idx,3), 'Color', color, ...
         'MarkerEdgeColor', color, 'MarkerFaceColor', color);

    %// Make sure multiple calls to stem don't clear the plot
    hold on;
end

%// Display colour bar to show colours
colormap(colourmap(1:end-1,:));
colorbar('YTickLabel', colourmap);

最后两行有点乱,但我们基本上在图表的右边显示一个颜色条,告诉你每个重量如何映射到每种颜色。


让我们对一些数据进行测试。我将生成一个随机200 x 4点矩阵,我们将使用上面的代码并使用stem3绘制它:

rng(123123); %// Set seed for reproducibility
data = rand(200,4);
num_colours = 10;

我将唯一颜色的总数设置为10.一旦我有上述数据,当我运行上面的代码时,这就是我得到的情节:

enter image description here

答案 1 :(得分:2)

您也可以使用HSVZ值将与您的第四列相对应。低Z值为蓝色,高Z值为红色。

enter image description here

我使用网站http://colorizer.org/计算出蓝色为H=0.65而红色为H=1SV保持不变。

http://colorizer.org/开始,我得到的是蓝色H=236, S=100, V=100。然后蓝色的H值为H = 235/360 = 0.65H=1, S=1, V=1为红色。


num_elem = 200;
c = linspace(0,1,num_elem)'; % // Replace this with the values from your fourth column


% // The equation gives blue (H=0.65) for c=0 and red (H=1) for c = 1
H = 0.65 + ((1-0.65).* c); 
S = ones(size(c,1),1);
V = ones(size(c,1),1);

% // You have to convert it to RGB to be compatible with stem3

colourmap = hsv2rgb([H,S,V]);


% // Generate some sample data
theta = linspace(0,2*pi,num_elem)';
X = cos(theta);
Y = sin(theta);
Z = theta;

% // Plot the sample data with the colourmap
figure;
hold on;
for idx=1:num_elem
  stem3(X(idx),Y(idx),Z(idx),':*','Color',colourmap(idx,:) ...
  ,'MarkerEdgeColor',colourmap(idx,:) ...
  ,'MarkerFaceColor',colourmap(idx,:) ...
  ,'LineWidth',4 ...
  );
end

hold off;
set(gca,'FontSize',36');