使用坐标点生成热图

时间:2019-05-29 22:16:42

标签: python python-3.x heatmap

我是Python新手。我的问题的答案可能在StackOverflow中可用,但老实说,我尝试了StackOverflow中几乎所有可用的代码和建议。

我的问题:与here几乎相同。我有一个坐标点(xy)和相应的值(p)作为.csv文件。我正在使用pandas读取该文件。

df = pd.read_csv("example.csv")

可以从here下载example.csv文件。让图像大小为2000 x 2000

任务:

基于Excel工作表中的xy坐标点,我必须在该图像中定位该点。

可以,A是图像,A(x,y)A中的任意点。现在,我必须以这种方式生成热图,以使x中的50个像素和y中的50个像素,即A(x,y),A(x + 50,y),A (x,y + 50)和A(x + 50,y + 50)包含与该坐标点相对应的p

我发现this link非常有用,可以解决我的问题,但是问题是我的数据集还需要更多修改。

以上链接中提供的代码:

#!/usr/bin/python3
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from skimage import io
from skimage.color import rgb2gray
import matplotlib as mpl
# Read original image
img = io.imread('img.jpg')

# Get the dimensions of the original image
x_dim, y_dim, z_dim = np.shape(img)

# Create heatmap
heatmap = np.zeros((x_dim, y_dim), dtype=float)

# Read CSV with a Pandas DataFrame
df = pd.read_csv("data.csv")

# Set probabilities values to specific indexes in the heatmap
for index, row in df.iterrows():
    x = np.int(row["x"])
    y = np.int(row["y"])
    x1 = np.int(row["x1"])
    y1 = np.int(row["y1"])
    p = row["Probability value"]
    heatmap[x:x1,y:y1] = p

# Plot images
fig, axes = plt.subplots(1, 2, figsize=(8, 4))
ax = axes.ravel()

ax[0].imshow(img)
ax[0].set_title("Original")
fig.colorbar(ax[0].imshow(img), ax=ax[0])

ax[1].imshow(img, vmin=0, vmax=1)
ax[1].imshow(heatmap, alpha=.5, cmap='jet')
ax[1].set_title("Original + heatmap")

# Specific colorbar
norm = mpl.colors.Normalize(vmin=0,vmax=2)
N = 11
cmap = plt.get_cmap('jet',N)
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])
plt.colorbar(sm, ticks=np.linspace(0,1,N), 
             boundaries=np.arange(0,1.1,0.1)) 

fig.tight_layout()
plt.show()

使用此代码时遇到的问题:

  1. 此代码正在生成正方形边缘的热图,但我期望边缘平滑。我知道高斯分布可能会解决此问题。但是我是python的新手,我不知道如何在我的数据集中实现高斯分布。

  2. 不属于坐标点的区域也会生成一层颜色。结果是覆盖了图像的那些层覆盖了原始图像的背景。我希望用一句话说明热图的背景是透明的,以便覆盖在显示坐标点未覆盖的区域时不会造成任何问题。

任何潜在客户都将受到高度赞赏。

2 个答案:

答案 0 :(得分:1)

您链接的问题密谋。如果您不想使用它,而只是想简化数据的外观,我建议您仅使用使用scipy的高斯滤波器。

在顶部,导入:

import seaborn as sns
from scipy.ndimage.filters import gaussian_filter

然后像这样使用它:

df_smooth = gaussian_filter(df, sigma=1)
sns.heatmap(df_smooth, vmin=-40, vmax=150, cmap ="coolwarm" , cbar=True , cbar_kws={"ticks":[-40,150,-20,0,25,50,75,100,125]})

您可以使用以下方法更改平滑量: sigma = 3或其他任何可以给您所需平滑度的数字。

请记住,这还将“平滑”您拥有的任何最大数据峰值,因此最小和最大数据将不再与归一化中指定的数据相同。为了仍然获得美观的热图,我建议不要对vmin和vmax使用固定值,但是:

sns.heatmap(df_smooth, vmin=np.min(df_smooth), vmax=np.max(df_smooth), cmap ="coolwarm" , cbar=True , cbar_kws={"ticks":[-40,150,-20,0,25,50,75,100,125]})

如果您提到的高斯滤波器满足您的期望,您甚至可以直接对数据实施高斯规范化。

答案 1 :(得分:1)

您的代码是完美的。只需更改一行,即可解决您的两个问题。

更改前

ax[1].imshow(heatmap, alpha=.5, cmap='jet')

更改后:

ax[1].imshow(heatmap, alpha=.5, cmap='coolwarm', interpolation='gaussian')

尽管上述更改可以解决您的问题,但是如果要提高透明度,可以使用以下功能

def transparent_cmap(cmap, N=255):
    "Copy colormap and set alpha values"

    mycmap = cmap
    mycmap._init()
    mycmap._lut[:,-1] = np.linspace(0, 0.8, N+4)
    return mycmap
mycmap = transparent_cmap(plt.cm.coolwarm) 

在这种情况下,您之前的代码行将如下更改:

ax[1].imshow(heatmap, alpha=.5, cmap=mycmap, vmin=0, vmax=1)