给定一个N×N数组我想生成一个热图,以这种方式可视化数据:
鉴于下面的源图像,我创建了一个稀疏填充的N X N数组,其中包含下面列出的点。 1000x800阵列中的90分。
在网上研究如何生成这样的热图时,我偶然发现只使用色彩图来获得令人失望的结果。
colormap('hot'); % set colormap
imagesc(points); % draw image and scale colormap to values range
colorbar;
我得到了相当令人失望的结果。
我还有什么其他选择让我的图像与上面的图像相似?
答案 0 :(得分:3)
有几种不同的方法可以将散乱或稀疏矩阵数据转换为热图,从而提供更好的点密度可视化。我在这里展示的示例将从分散的数据开始,因此如果您已经在2D矩阵/直方图中有数据,则可以跳过初始步骤......
如果散乱数据相当密集,可能只需要一个简单的二维直方图。您可以创建一个覆盖散乱点的网格(以您选择的分辨率),并使用histcounts2
在x和y方向上分组数据:
% Normally distributed sample points:
x = randn(1, 10000);
y = randn(1, 10000);
% Bin the data:
pts = linspace(-4, 4, 101);
N = histcounts2(y(:), x(:), pts, pts);
% Plot scattered data (for comparison):
subplot(1, 2, 1);
scatter(x, y, 'r.');
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]));
% Plot heatmap:
subplot(1, 2, 2);
imagesc(pts, pts, N);
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]), 'YDir', 'normal');
这是由此产生的情节:
如果您的分散数据相当稀疏,您仍然可以像上面那样创建直方图,但是然后过滤结果以使其平滑。如果您拥有imdilate
,则可以使用Image Processing Toolbox,或创建过滤器矩阵并使用conv2
。以下是后者的一个例子:
% Normally distributed sample points:
x = randn(1, 100);
y = randn(1, 100);
% Bin the data:
pts = linspace(-3, 3, 101);
N = histcounts2(y(:), x(:), pts, pts);
% Create Gaussian filter matrix:
[xG, yG] = meshgrid(-5:5);
sigma = 2.5;
g = exp(-xG.^2./(2.*sigma.^2)-yG.^2./(2.*sigma.^2));
g = g./sum(g(:));
% Plot scattered data (for comparison):
subplot(1, 2, 1);
scatter(x, y, 'r.');
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]));
% Plot heatmap:
subplot(1, 2, 2);
imagesc(pts, pts, conv2(N, g, 'same'));
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]), 'YDir', 'normal');
这是由此产生的情节:
从上面的稀疏直方图开始,您可以使用bwdist
中的Image Processing Toolbox来创建数据的距离变换。这将根据每个像素与最近的非零像素的距离为每个像素分配一个值。
或者,您可以避免通过覆盖散乱点的creating a grid来计算2D直方图,并使用pdist2
中的Statistics Toolbox计算从每个网格点到散点之一的最小距离。这是一个例子(使用与上面相同的样本数据):
% Generate grid and compute minimum distance:
pts = linspace(-3, 3, 101);
[X, Y] = meshgrid(pts);
D = pdist2([x(:) y(:)], [X(:) Y(:)], 'euclidean', 'Smallest', 1);
% Plot scattered data:
subplot(1, 2, 1);
scatter(x, y, 'r.');
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]));
% Plot heatmap:
subplot(1, 2, 2);
imagesc(pts, pts, reshape(D, size(X)));
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]), 'YDir', 'normal');
colormap(flip(parula(), 1));
这是由此产生的情节:
答案 1 :(得分:1)
首先需要计算xy网格上的点密度。在这里,您只是在matlab中绘制任何散点图的“图像版本”。因此,在绘图之前,您需要处理数据并获取从您的点导出的密度图。 您可以使用ksdensity函数,它将估算网格基础上的点密度。如果你无法使用这个函数,那么fileexchage上有很多函数可以做同样的事情。
% get the x y coordinates of your points
[y,x] = find(points);
P = [x,y];
% estimate and plot the density
[Est,XY] = ksdensity(P);
imagesc(XY(:,1), XY(:,2),Est);
colormap('hot');
colorbar;