给定一个N x N数组,我想生成一个热图,以这种方式可视化数据:
给定下面的源图像,我创建了一个人口稀少的NXN数组,其中包含下面列出的点。1000x800阵列中的90点。
在线研究如何生成这样的热图时,我偶然发现仅使用色图来获得令人失望的结果。
colormap('hot'); % set colormap
imagesc(points); % draw image and scale colormap to values range
colorbar;
Run Code Online (Sandbox Code Playgroud)
我的结果令人失望。
我还需要哪些其他选择才能使自己的形象与上一幅形象相似?
您可以通过几种不同的方法将分散的或稀疏的矩阵数据转换为热图,以更好地显示点密度。我将在此处显示的示例将从分散的数据开始,因此,如果您已经拥有2D矩阵/直方图中的数据,则可以跳过初始步骤...
如果您分散的数据非常密集,则可能只需要一个简单的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');
Run Code Online (Sandbox Code Playgroud)
这是结果图:
如果您分散的数据比较稀疏,您仍然可以如上所述创建直方图,然后过滤结果以使其平滑。imdilate如果您拥有图像处理工具箱,则可以使用它,也可以创建一个滤镜矩阵并使用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');
Run Code Online (Sandbox Code Playgroud)
这是结果图:
从上方的稀疏直方图开始,您可以bwdist从“ 图像处理工具箱”中使用它来创建数据的距离变换。这将根据每个像素与最近的非零像素的距离为其分配一个值。
或者,你可以避开计算2D直方图创建网格覆盖的散点和计算使用您的散点之一,从每个网格点的最小距离pdist2从统计工具箱。这是一个示例(使用与上述相同的示例数据):
% 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));
Run Code Online (Sandbox Code Playgroud)
这是结果图:
您首先需要计算 xy 网格上点的密度。在这里,您只是在 matlab 中绘制任何散点图的“图像版本”。因此,在绘图之前,您需要处理数据并获取从您的点导出的密度图。例如,您可以使用ksdenth函数,它将估计网格基础上点的密度。如果您无法使用此功能,则 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;
Run Code Online (Sandbox Code Playgroud)