如何基于给定密度图绘制与二维正态分布示例效果一致的热力图
实现方案
要基于密度图生成和你提供的二维正态分布示例视觉效果完全一致的热力图,核心是对齐示例代码的数值处理逻辑和绘图参数,整体流程如下:
参考基线说明
你当前实现的正态分布热力图、对应密度图、待转换的目标密度图分别如下:
- 二维正态分布热力图效果:

- 上述正态分布对应的密度图效果:

- 待转换的样本密度图:

你当前绘制正态分布热力图的代码是逻辑基线,所有转换规则都要和这套逻辑对齐:
output_width = 40 output_height = 40 p_x = 20 p_y = 20 sigma = 1 X1 = np.linspace(0, output_width, output_width) Y1 = np.linspace(0, output_height, output_height) [X, Y] = np.meshgrid(X1, Y1) X = X - np.floor(p_x) Y = Y - np.floor(p_y) D2 = X * X + Y * Y E2 = 2.0 * sigma ** 2 Exponent = D2 / E2 heatmap = np.exp(-Exponent) heatmap = (heatmap - heatmap.min()) / (heatmap.max() - heatmap.min()) plt.imshow(heatmap)
具体实现步骤
1. 提取密度值二维矩阵
首先要把你手里的密度图转换成和上述代码中heatmap维度一致的二维数值数组,分两种情况处理:
- 如果你手里有密度分布的原始采样/计算数据:直接把数据整理为
(output_height, output_width)形状的二维数组即可,不需要额外处理图像。 - 如果你手里只有渲染完成的密度图图片:按下面逻辑做逆提取:
- 读入图片后先裁剪,去掉坐标轴、图例、留白等非密度绘图区域,只保留核心的密度可视化部分
- 将裁剪后的图像缩放到你需要的热力图尺寸(和示例对齐的话就是40*40),转成灰度值矩阵(彩色图的颜色和密度值是单调映射关系,灰度值可以直接对应密度相对大小)
- 对矩阵做上下翻转:
plt.imshow默认坐标原点在左上角,而常规密度图原点在左下角,不翻转会导致出图上下颠倒 - 做背景掩码:如果图中有纯白/纯黑的无密度背景,把对应位置的矩阵值设为0,避免后续归一化被极值干扰。
2. 对齐归一化逻辑
完全复用你现有代码的线性归一化逻辑,把所有密度值缩放到[0,1]区间,不要改缩放规则:
# density_raw为上一步得到的原始密度二维矩阵 heatmap = (density_raw - density_raw.min()) / (density_raw.max() - density_raw.min())
3. 对齐绘图参数
调用plt.imshow时保持默认参数即可,不要额外修改配置:
- 不要修改colormap,保持默认的
viridis(就是示例里从深蓝过渡到亮黄的配色) - 不要添加插值参数,保持默认的最近邻插值,才能和示例一样呈现方块状的像素效果
- 不要额外添加colorbar、网格、坐标轴标注、标题等元素,避免视觉差异。
完整可运行参考代码
import numpy as np import matplotlib.pyplot as plt from PIL import Image # 基础配置 和示例参数完全对齐 output_width = 40 output_height = 40 # -------------------------- # 替换成你自己的密度读取逻辑 # -------------------------- # --- 场景1:有原始密度数据,直接赋值给density_raw即可 --- # --- 场景2:从现成密度图片提取,取消注释下面代码 --- # img = Image.open("your_density_image.png").convert("L") # # 按你自己的图片实际坐标裁剪掉非密度区域 # img = img.crop((plot_left, plot_top, plot_right, plot_bottom)) # img = img.resize((output_width, output_height)) # density_raw = np.array(img) # density_raw = np.flipud(density_raw) # 翻转y轴匹配imshow坐标 # density_raw[density_raw > 250] = 0 # 纯白背景置为0密度 # 这里用原有正态分布数据做测试 p_x = 20 p_y = 20 sigma = 1 X1 = np.linspace(0, output_width, output_width) Y1 = np.linspace(0, output_height, output_height) [X, Y] = np.meshgrid(X1, Y1) X = X - np.floor(p_x) Y = Y - np.floor(p_y) D2 = X * X + Y * Y E2 = 2.0 * sigma ** 2 Exponent = D2 / E2 density_raw = np.exp(-Exponent) # 归一化 和基线逻辑一致 heatmap = (density_raw - density_raw.min()) / (density_raw.max() - density_raw.min()) # 绘图 plt.imshow(heatmap) plt.show()
常见坑点
- 出图上下颠倒:大概率是没做y轴翻转,检查密度矩阵的原点方向是否和imshow对齐
- 出图模糊没有方块感:检查是否给imshow传入了
interpolation参数,删掉该参数保持默认最近邻插值即可 - 出图对比度和示例差异大:检查密度矩阵是否混入了背景的极值点,归一化前先把无密度的背景区域做掩码处理。
内容的提问来源于stack exchange,提问作者KhanhNguyen
相关产品推荐
相关产品推荐

