Store the Spectrogram as Image in Python - python-3.x

I want to store the STFT spectrogram of the audio as image. The code below shows a spectrogram to me as output, but when saved as image I get a different image.
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
audio_name = '---.au'
hop_length = 512
window_size = 1024
import librosa
y, sr = librosa.load(audio_name)
window = np.hanning(window_size)
out = librosa.core.spectrum.stft(y, n_fft = window_size, hop_length = hop_length,
window=window)
out = 2 * np.abs(out) / np.sum(window)
import librosa.display
librosa.display.specshow(librosa.amplitude_to_db(out,ref=np.max),
y_axis='log', x_axis='time')
from PIL import Image
img = Image.fromarray(out)
if img.mode != 'RGBA':
img = img.convert('RGBA')
img.save('output.png')
But when I save it the output file is a black image.
I want to save the exact image of the spectogrm.

If you want exactly what librosa.display.spectrogram() will show, then use matplotlib to save the plot to a file:
import matplotlib.pyplot as plt
import librosa.display
import numpy as np
import pandas as pd
import librosa
filename = librosa.util.example_audio_file()
y, sr = librosa.load(filename)
y = y[:100000] # shorten audio a bit for speed
window_size = 1024
window = np.hanning(window_size)
stft = librosa.core.spectrum.stft(y, n_fft=window_size, hop_length=512, window=window)
out = 2 * np.abs(stft) / np.sum(window)
# For plotting headlessly
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
fig = plt.Figure()
canvas = FigureCanvas(fig)
ax = fig.add_subplot(111)
p = librosa.display.specshow(librosa.amplitude_to_db(out, ref=np.max), ax=ax, y_axis='log', x_axis='time')
fig.savefig('spec.png')
spec.png:

If the desired is to get just the data in the spectrogram, stored as an image, then see this answer.

Related

Multiple plot single colorbar in python matplotlib basemap system crash problem

Why I am getting a runtime error while running this code?? I wanted to show two SST data in a single plot using for loop. while I am running the code it shows your system has crashed. I am sharing the screenshot of the system log.
Screenshot of the error
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from netCDF4 import Dataset
from mpl_toolkits.axes_grid1 import ImageGrid
def read_sst (x):
ncfile=x
fh=Dataset(ncfile,mode='r')
sst=fh.variables['sst'][:]
sst_anom=sst[0,:,:]
return sst_anom
sst_anom_drought=read_sst("Drought_SST_Mean_Anomaly_Composite_1901-2014.nc")
sst_anom_flood=read_sst("Flood_SST_Mean_Anomaly_Composite_1901-2014.nc")
SST_ncfile='Flood_SST_Mean_Anomaly_Composite_1901-2014.nc'
fh1=Dataset(SST_ncfile,mode='r')
lons = fh1.variables['longitude'][:]
lats = fh1.variables['latitude'][:]
sst_data=[sst_anom_drought,sst_anom_flood]
fig = plt.figure(1,(15.,5.))
grid_top = ImageGrid(fig, 111, nrows_ncols = (2, 1),axes_pad=0.5)
cbar_ax = fig.add_axes([0.25,0.15, 0.55, 0.015])
for g, s in zip(grid_top,sst_data):
plt.sca(g)
m = Basemap(resolution='l',projection='merc',llcrnrlon=30, llcrnrlat=-31,
urcrnrlon=360, urcrnrlat=65)
clevs = np.linspace(-0.8, 0.8, 15)
lons, lats = np.meshgrid(lons, lats)
xi, yi = m(lons, lats)
color_map = plt.cm.RdBu_r
#reversed_color_map = color_map.reversed()
cs = m.contourf(xi,yi,s,clevs,cmap=color_map,extend='both')
cb=fig.colorbar(cs,orientation="horizontal",cax=cbar_ax)
m.drawparallels(np.arange(-30., 65., 15.), labels=[1,0,0,0], fontsize=12,linewidth=0.1)
m.drawmeridians(np.arange(-180., 180., 40.), labels=[0,0,0,1], fontsize=12,linewidth=0.1)
m.fillcontinents(color='whitesmoke',lake_color='whitesmoke')
m.drawcoastlines()

How to plot 3d rgb histogram of a colored image in python

I want to plot a 3d histogram of a colored image but I can only plot R and G value. what am I doing wrong here? or is there an easier way to do so
import numpy as np
import matplotlib.image as mpimg
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
img = mpimg.imread('model/obj4__0.png')
pixels = img.shape[0]*img.shape[1]
channels = 3
data = np.reshape(img[:, :, :channels], (pixels, channels))
histo_rgb, _ = np.histogramdd(data, bins=256)
histo_rg = np.sum(histo_rgb, 2)
levels = np.arange(256)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for g in levels:
ax.bar(levels, histo_rg[:, g], zs=g, zdir='y', color='r')
ax.set_xlabel('Red')
ax.set_ylabel('Green')
ax.set_zlabel('Number of pixels')
plt.show()
If I understand your question well, I have the same issue, and found this: https://www.bogotobogo.com/python/OpenCV_Python/python_opencv3_image_histogram_calcHist.php
Here is the code for your question:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('images/GoldenGateSunset.png', -1)
cv2.imshow('GoldenGate',img)
color = ('b','g','r')
for channel,col in enumerate(color):
histr = cv2.calcHist([img],[channel],None,[256],[0,256])
plt.plot(histr,color = col)
plt.xlim([0,256])
plt.title('Histogram for color scale picture')
plt.show()
while True:
k = cv2.waitKey(0) & 0xFF
if k == 27: break # ESC key to exit
cv2.destroyAllWindows()
Note that this use cv2 functions but you can convert it to works with Numpy.
I will try to figure out with numpy and give you an update.

Sending matplotlib image to pymsteams (cannot create new tag pymsteams)

I am using matplotlib to plot my image.
import pandas as pd
from matplotlib import pyplot as plt
x = ['09:30', '09:33', '09:40', '09:43', '09:50', '09:53', '10:00', '10:03', '10:10', '10:13']
y = ['3010.910000', '3011.650000', '3009.130000', '3011.500000', '3010.460000', '3010.950000', '3012.830000', '3013.120000', '3011.730000', '3010.130000']
matrix = pd.DataFrame({'Time': x, 'Quote': y})
matrix['Quote'] = matrix['Quote'].astype(float)
plt.plot('Time', 'Quote', data=matrix, color='mediumvioletred')
Here is the challenge now:
import pymsteams
web_hook = 'My Microsoft Teams URL https://outlook.office.com/webhook/blahblah'
teams_message = pymsteams.connectorcard(web_hook)
msg_section = pymsteams.cardsection()
msg_section.title('Title')
msg_section.addImage(image) #I want to add that plt image here
teams_message.addSection(msg_section)
teams_message.text("Some Message")
self.teams_message.send()
I have tried this (and I want this approach, using cache):
buf = io.BytesIO()
plt.savefig(buf, format='png')
buf.seek(0)
msg_section.addImage(buf.read())
I did try saving the image to local drive 'c:/temp/'. The code did not give any error msg, but the image on Teams was a blank image, even though the image is correct in c:/temp
In summary. A PNG image has to be converted to base64 string.
Please see the example below.
Note that I'm using Python 3.6.
Additionally image width seems to be limited in a Connector Card.
import numpy as np
import matplotlib.pyplot as plt
import base64
from io import BytesIO
import pymsteams
# generate fig
fig, ax = plt.subplots(1,1,figsize=(20,6))
ax.hist(np.random.normal(0, 1, 1000), bins=51, edgecolor='k', alpha=0.5);
buf = BytesIO()
fig.savefig(buf, format="png")
# get base64 string
data = base64.b64encode(buf.getbuffer()).decode("ascii")
encoded_fig = f"data:image/png;base64,{data}"
# send encoded_fig via webhook
web_hook = 'YOUR_WEBHOOK'
teams_message = pymsteams.connectorcard(web_hook)
msg_section = pymsteams.cardsection()
msg_section.title('Title')
msg_section.addImage(encoded_fig) #I want to add that plt image here
teams_message.addSection(msg_section)
teams_message.text("Some Message")
teams_message.send()
image_file = open('img/icon.png'), "rb").read()
ICON = "data:image/png;base64,{data}".format(data=b64encode(image_file).decode("ascii"))
#And in your Teams alert creation, you call:
section.activityImage(ICON)

How can I make a transparent background?

I have a .csv file which contains some data where x, y, x1, y1 are the coordinate points, and p is the value. My below code is working very well for plotting, but when I am plotting the data, I am getting a background color like the purple color. I don't want any color in the background. I want the background will be Transparent. My ultimate goal is overlying this result over an image. I am new in Python. Any help will be highly appreciated.
Download link of the .csv file here or link-2 or link-3
I am getting below result
My Code
import matplotlib.pyplot as plt
from scipy import ndimage
import numpy as np
import pandas as pd
from skimage import transform
from PIL import Image
import cv2
x_dim=1200
y_dim=1200
# Read CSV
df = pd.read_csv("flower_feature.csv")
# Create numpy array of zeros os same size
array = np.zeros((x_dim, y_dim), dtype=np.uint8)
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["p"]
array[x:x1,y:y1] = p
map = ndimage.filters.gaussian_filter(array, sigma=16)
plt.imshow(map)
plt.show()
As per Ghassen's suggestion I am getting below results. I am still not getting the transparent background.
When Alpha =0
When alpha =0.5
When alpha =1
try with this code :
import matplotlib.pyplot as plt
from scipy import ndimage
import numpy as np
import pandas as pd
x_dim=1200
y_dim=1200
# Read CSV
df = pd.read_csv("/home/rosafi/Downloads/flower_feature.csv")
# Create numpy array of zeros os same size
array = np.ones((x_dim, y_dim), dtype=np.uint8)
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["p"]
array[x:x1,y:y1] = p
map = ndimage.filters.gaussian_filter(array, sigma=16)
map = np.ma.masked_where(map == 0, map)
plt.imshow(map)
plt.show()
output:
I solved this issue by masking out the values where values ==0. The code will be
from mpl_toolkits.axes_grid1 import make_axes_locatable
masked_data = np.ma.masked_where(map == 0, map)

how to map netcdf data ob base map

file contains values of echos w.r.t to lat/long, I have to plot complete range of echos over base map.
from netCDF4 import Dataset
import numpy as np
import pandas as pd
from google.colab import files
upload = files.upload()
my_example_nc_file = 'a.nc'
fh = Dataset(my_example_nc_file, mode='r')
lons = fh.variables['longitude'][:]
lats = fh.variables['latitude'][:]
ech= fh.variables['echos'][:]
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
%matplotlib inline
m = Basemap(width=5000000,height=3500000,
resolution='l',projection='stere',\
lat_ts=40,lat_0=lat_0,lon_0=lon_0)
xi, yi = m(lons, lats)
#simple plot
#m.plot(xi, yi, 'co')
m.scatter(rge,yi, marker = 'o', color='r', zorder=5)
Current code execute below results.
enter image description here
I want to plot total echos with variation represented by colors as presented in below screen short
enter image description here

Resources