1

I am new in Python. The answer to my question might be available in the StackOverflow, but honestly speaking, I tried almost all the codes and suggestions available in the StackOverflow.

My problem: Almost the same as it is described here. I have coordinate points (x and y) and the corresponding value (p) as a .csv file. I am reading that file using pandas.

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

The example.csv file can be download from here. Let an image of size 2000 x 2000.

Task:

Based on the x and y coordinate points in the excel sheet, I have to locate the point in that image.

Lets, A is an image and A(x,y) is any point within A. Now I have to generate a heat map in such a way so that 50 pixels from x and 50 pixels fromy i.e., A(x,y), A(x+50, y), A(x, y+50) and A(x+50, y+50) contains p corresponding to that coordinate points.

I found this link which is very helpful and serves my issue, but the problem is some more modifications are necessary for my datasets.

The code which is available in the above 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()

Issues which I am facing when using this code:

  1. This code is generating a heat map of square edges, but I am expecting a smooth edge. I know Gaussian distribution might solve this problem. But I am new in python and I don't know how to implement the Gaussian Distribution in my dataset.

  2. The regions which don't belong to the coordinate points also generating a layer of color. As a result in an overlayed image those layer covering the background of original images. In one sentence I want the background of the heat map will be transparent so that overlays will not create any problem in showing the regions which are not covered by the coordinate points.

Any leads will be highly appreciated.

Js541
  • 100
  • 1
  • 13

2 Answers2

1

The question you linked uses plotly. If you don't want to use that and want to simply smooth the way your data looks, I suggest just using a gaussian filter using scipy.

At the top, import:

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

Then use it like this:

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]})

You can change the amount of smoothing, using e.g. sigma=3, or any other number that gives you the amount of smoothing you want.

Keep in mind that that will also "smooth out" any maximum data peaks you have, so your minimum and maximum data will not be the same that you specified in your normalization anymore. To still get good looking heatmaps I would suggest not using fixed values for your vmin and vmax, but:

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]})

In case that you Gaussian filter fulfill your expectations you mentioned you can even implement Gaussian normalization on your data directly.

Mario
  • 1,631
  • 2
  • 21
  • 51
1

Your code is perfect. Just change only one line, then your both issues will be solved.

Before changes:

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

After changes:

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

Though above changes will solve your issue, but if you want then for additional transparency, you can use below function

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) 

In that case, your previous code line will change like below:

ax[1].imshow(heatmap, alpha=.5, cmap=mycmap, vmin=0, vmax=1)
user1410665
  • 719
  • 7
  • 23