简体   繁体   English

在MATLAB中使用自定义颜色图生成3D干图

[英]Produce a 3D stem plot with a custom colormap in MATLAB

I have a matrix (200 x 4) where first 3 values are X , Y and Z data. 我有一个矩阵(200 x 4),其中前三个值是XYZ数据。 I want use the fourth column to display each (X,Y,Z) triplet so that it maps to a color. 我想使用第四列来显示每个(X,Y,Z)三元组,以便它映射到一种颜色。

The fourth column contains values from 0.0 to 1.0 (200 values). 第四列包含从0.0到1.0的值(200个值)。 I want to map these values with colormap manually and linearly. 我想手动和线性地使用colormap映射这些值。 The smallest value should have blue color and the largest value may have red color. 最小值应为蓝色,最大值应为红色。

I know that it is possible with scatter3 . 我知道scatter3是可能的。 However, I want to do using stem3 where I can specify the color manually from colormap. 但是,我想使用stem3 ,在这里我可以从colormap中手动指定颜色。

Is there a way to do this in MATLAB? 在MATLAB中有没有办法做到这一点?

That's pretty simple to do. 这很简单。 kkuilla posted a very insightful link. kkuilla发布了一个非常有见地的链接。 To get something started, if you want to have a colour map that varies from blue to red, you know that an image is decomposed into three colours: Red, green and blue. 首先,如果要创建一个从蓝色到红色的颜色映射表,则需要将图像分解为三种颜色:红色,绿色和蓝色。

Therefore, all you would have to do is vary the red and blue channels. 因此,您要做的就是改变红色和蓝色通道。 Start with a pure blue colour, which is RGB = (0,0,255) where this is mapped to the initial weight of w = 0 and vary this to the end where RGB = (255,0,0) with w = 1 . 从纯蓝色开始,即RGB = (0,0,255) ,将其映射到w = 0的初始权重,然后将其更改为RGB = (255,0,0)且在w = 1的末尾。 You can very easily do that by linspace . 您可以通过linspace轻松地做到这一点。 However, colours in a colour map for plotting in MATLAB are normalized so that they're between [0,1] , not [0,255] . 但是,对要在MATLAB中绘制的颜色图中的颜色进行了归一化处理,以使它们介于[0,1]而非[0,255] Also, because a colour map in MATLAB is a matrix of N x 3 , where N is the total number of colours you want, all you have to do is: 另外,由于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 is the total number of colours you would like displayed. num_colours是您想要显示的颜色总数。 I set it to 10 to get you started. 我将其设置为10以使您入门。 weights is something we will need for later, so don't worry about that righ tnow. weights是我们以后需要的东西,因此请不要担心这种精确性。 Essentially, colormap would be the colour map you apply to your data. 本质上, colormap将是您应用于数据的颜色图。

However, what is going to be difficult now is that the data that you're plotting has no correlation to the weight of the data itself (or the fourth column of your data). 但是,现在要困难的是,您正在绘制的数据与数据本身(或数据的第四列)的权重没有关联。 This means that you can't simply use the (X,Y,Z) data to determine what the colour of each plot in your stem is going to look like. 这意味着您不能简单地使用(X,Y,Z)数据来确定stem中每个图的颜色。 Usually for colour maps in MATLAB, the height of the stem is proportional to the colour that is displayed. 通常对于MATLAB中的颜色图,茎的高度与显示的颜色成比例。 For the largest Z value in your data, this would naturally be assigned to the colour at the end of your colour map, or red. 对于数据中最大的Z值,自然会将其分配给颜色图末尾的颜色,即红色。 The smallest Z value in your data would naturally get assigned at the beginning of your colour map, or blue. 数据中最小的Z值自然会在颜色图的开头或蓝色处分配。

If this was the case, you would only need to make one stem call and specify the colour map as the attribute for Color . 如果是这种情况,则只需要进行一次stem调用并将颜色图指定为Color的属性即可。 Because there is no correlation between the height of the Z value and the weight that you're assigning for each data point, you have no choice but to loop through each of your points and determine the closest value between the weight for a point with every weight and ultimately every colour in your colour map, then apply this closest colour to each point in your stem respectively. 因为在高度之间没有相关性Z价值,你的每一个数据点分配权重,你必须通过每个点无奈地循环 ,并确定每一个点的权重之间的最接近的值权重并最终将颜色映射到每种颜色,然后将此最接近的颜色分别应用于stem每个点。

We determine the closest point by using the weights vector that was generated above. 我们使用上面生成的weights向量确定最接近的点。 We can consider each colour as having a mapping from [0,1] , and each weight corresponds to the colour in colourmap . 我们可以认为每种颜色都有[0,1]的映射,每种权重都对应于colourmap的颜色。 Therefore, a weight of 0 is the first colour in the colour map, and that's in the first row. 因此,权重0是颜色图中的第一个颜色,即在第一行中。 The next weight after this is the second colour, and that's in the second row and so on.... so we simply need to determine where each weight that's in the fourth column of your matrix is closest to for the above weights vector. 此后的下一个权重是第二种颜色,该权重在第二行中,依此类推....所以我们只需要确定矩阵第四列中每个权重最接近上述weights向量的位置。 This will determine which colour we need to select from the colour map to plot the point. 这将确定我们需要从颜色图中选择哪种颜色来绘制点。

Given that your matrix of 200 x 4 is stored in data , you must specifically do this: 假设您的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);

The last two lines are a bit hackish, but we basically show a colour bar to the right of the plot that tells you how each weight maps to each colour. 最后两行有些黑,但是我们基本上在图的右侧显示了一个色条,告诉您每种重量如何映射到每种颜色。


Let's test this on some data. 让我们对一些数据进行测试。 I'm going to generate a random 200 x 4 matrix of points and we will use the above code and plot it using stem3 : 我将生成一个随机的200 x 4点矩阵,我们将使用上面的代码并使用stem3进行stem3

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

I set the total number of unique colours to 10. Once I have this above data, when I run through the code above, this is the plot I get: 我将唯一颜色的总数设置为10。一旦获得了上述数据,当我运行上述代码时,这就是我得到的图:

在此处输入图片说明

You can use HSV as well. 您也可以使用HSV The Z values would correspond to your fourth column. Z值将对应于您的第四列。 Low Z values are blue and high Z values are red. Z值低为蓝色, Z值高为红色。

在此处输入图片说明

I used the site http://colorizer.org/ to work out that blue is H=0.65 and red is H=1 . 我使用http://colorizer.org/网站计算出,蓝色为H=0.65 ,红色为H=1 S and V stay the same. SV保持不变。

From http://colorizer.org/ , I got that a blue colour is H=236, S=100, V=100 . http://colorizer.org/ ,我得到蓝色是H=236, S=100, V=100 Then the H value for blue is H = 235/360 = 0.65 and H=1, S=1, V=1 for red. 那么蓝色的H值为H = 235/360 = 0.65 ,红色的H=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');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM