Я новичок в Python. Ответ на мой вопрос может быть доступен в StackOverflow, но, честно говоря, я перепробовал почти все коды и предложения, доступные в StackOverflow.
Моя проблема: Почти так же, как описано здесь. У меня есть точки координат (x
и y
) и соответствующее значение (p
) в виде файла .csv
. Я читаю этот файл, используя pandas
.
df = pd.read_csv("example.csv")
Файл example.csv
можно скачать с сайта здесь. Пусть изображение размером 2000 x 2000
.
Задача:
Основываясь на точках координат x
и y
на листе Excel, я должен найти точку на этом изображении.
Допустим, A
— изображение, а A(x,y)
— любая точка внутри A
. Теперь мне нужно сгенерировать тепловую карту таким образом, чтобы 50 пикселей из x
и 50 пикселей из y
, то есть A(x,y), A(x+50, y), A(x, y+50) и A (x + 50, y + 50) содержит p
, соответствующий этим точкам координат.
Я нашел эта ссылка, который очень полезен и решает мою проблему, но проблема в том, что для моих наборов данных необходимы дополнительные модификации.
Код, который доступен по ссылке выше:
#!/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()
Проблемы, с которыми я сталкиваюсь при использовании этого кода:
Этот код генерирует тепловую карту квадратных краев, но я ожидаю, что край будет гладким. Я знаю, что распределение Гаусса может решить эту проблему. Но я новичок в python и не знаю, как реализовать распределение Гаусса в моем наборе данных.
Области, которые не принадлежат координатным точкам, также создают слой цвета. В результате на изображение накладывается тот слой, который перекрывает фон исходного изображения. Одним предложением я хочу, чтобы фон тепловой карты был прозрачным, чтобы наложения не создавали проблем с отображением областей, которые не покрыты координатными точками.
Любые выводы будут высоко оценены.
Вопрос, который вы связали, использует сюжет. Если вы не хотите использовать это и хотите просто сгладить внешний вид ваших данных, я предлагаю просто использовать фильтр Гаусса с помощью 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]})
В случае, если ваш фильтр Гаусса соответствует вашим ожиданиям, о которых вы упомянули, вы даже можете напрямую реализовать нормализацию Гаусса для своих данных.
вызовите библиотеку seaborn на import seaborn as sns
и замените правую на df
Ваш код идеален. Просто измените только одну строку, и обе проблемы будут решены.
До изменений:
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)
Не могли бы вы сказать мне в приведенном выше коде, как я могу использовать вашу концепцию?