How to convert a Julia plot (via Plots.jl) into a Matrix{RGB{N0f8}} - matrix

Matplotlib can convert a plot/figure into a RGB array as follows:
import matplotlib.pyplot as plt
import numpy as np
import io
fig, ax = plt.subplots()
n=256
I, J = np.indices((n, n))
im = ax.imshow((I | J) % 19, interpolation='none')
fig.colorbar(im, ax=ax)
#Convert fig to a RGB array
io_buf = io.BytesIO()
fig.savefig(io_buf, format='raw')
io_buf.seek(0)
fig_arr = np.reshape(np.frombuffer(io_buf.getvalue(), dtype=np.uint8),
newshape=(int(fig.bbox.bounds[3]), int(fig.bbox.bounds[2]), -1))
print(f"The shape of the rgb array: {fig_arr.shape}")
plt.show()
It displays:
The shape of the rgb array: (480, 640, 4)
Is it possible to convert similarly a Plots plot into a Matrix{RGB{N0f8}}?
The first part:
using Plots
n = 255
I = [i for i in 0:n, j in 0:n]
h = heatmap(mod.((I .| I'), 19), c= :deep, yflip=true, size=(400, 400), aspect_ratio=:equal)
I searched for Julia equivalent of numpy.frombuffer, but no result has been returned

With h holding the plot, as the code in the OP has described. The following:
using FileIO
io = IOBuffer()
show(io, MIME("image/png"), h);
strm = Stream(format"PNG", io)
img = load(strm)
leaves img with the Matrix{RGB{...}}.

Related

How to Plot YCBCR color space image with matplotlib?

This is my code it shows all color spaces except YCBCR ,,
Notation:ConvertLayer converts color space of image
fig=plt.figure(figsize=(9, 9))
for images, labels in train_ds.take(1):
for i in range(16):
plt.subplot(5, 5, i + 1)
color_space = COLOR_SPACES[i%5]
image = tf.expand_dims(images[i//5] ,axis=0)
image = augmentation(NormalLayer(color_space)(tf.cast(image,tf.float32)))
if color_space=="YCBCR":
image = tf.cast(image, tf.uint8)
image = ConvertLayer(color_space)(image)
#image = tf.cast(image * 255.0, tf.uint8)
lbl = "{}({})".format(class_names[labels[i//4].numpy().argmax()] , color_space )
plt.imshow(tf.squeeze(image))
plt.title(lbl)
plt.axis("off")
break
I need to visualize it just in matplotlib.
With the following code I was able to visualize the image in matplotlib.
import matplotlib.pyplot as plt
import numpy as np
x=plt.imread("/content/car.jpeg")
y=rgb2ycbcr(x)
fig = plt.figure(figsize=(10, 7))
rows = 1
columns = 2
fig.add_subplot(rows, columns, 1)
plt.imshow(x)
plt.axis('off')
plt.title("RGB")
fig.add_subplot(rows, columns, 2)
plt.imshow(y)
plt.axis('off')
plt.title("YCBCR")
def rgb2ycbcr(im):
xform = np.array([[.299, .587, .114], [-.1687, -.3313, .5], [.5, -.4187, -.0813]])
ycbcr = im.dot(xform.T)
ycbcr[:,:,[1,2]] += 128
return np.uint8(ycbcr)
Output:

convert hued displot of X to plot of hue vs mode(X given hue)?

I have a Seaborn displot with a hued variable:
For each hued variable, I want to extract the mode of the density estimate and then plot each hue variable versus its mode, like so:
How do I do this?
You can use scipy.stats.gaussian_kde to create the density estimation function. And then call that function on an array of x-values to calculate its maximum.
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
df = pd.DataFrame({'x': np.random.normal(0.001, 1, 1300).cumsum() + 30,
'hue': np.repeat(np.arange(0.08, 0.20001, 0.01), 100).round(2)})
g = sns.displot(df, x='x', hue='hue', palette='turbo', kind='kde', fill=True, height=6, aspect=1.5)
plt.show()
from scipy.stats import gaussian_kde
from matplotlib.cm import ScalarMappable
fig, ax = plt.subplots(figsize=(10, 6))
hues = df['hue'].unique()
num_hues = len(hues)
colors = sns.color_palette('turbo', num_hues)
xmin, xmax = df['x'].min(), df['x'].max()
xs = np.linspace(xmin, xmax, 500)
for hue, color in zip(hues, colors):
data = df[df['hue'] == hue]['x'].values
kde = gaussian_kde(data)
mode_index = np.argmax(kde(xs))
mode_x = xs[mode_index]
sns.scatterplot(x=[hue], y=[mode_x], color=color, s=50, ax=ax)
cmap = sns.color_palette('turbo', as_cmap=True)
norm = plt.Normalize(hues.min(), hues.max())
plt.colorbar(ScalarMappable(cmap=cmap, norm=norm), ax=ax, ticks=hues)
plt.show()
Here is another approach, extracting the kde curves. It uses the legend of the kde plot to get the correspondence between the curves and the hue values. sns.kdeplot is the axes-level function used by sns.displot(kind='kde'). fill=False creates lines instead of filled polygons for the curves, for which the values are easier to extract. (ax1.fill_between can fill the curves during a second pass). The x and y axes of the second plot are switched to align the x-axes of both plots.
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
df = pd.DataFrame({'x': np.random.normal(0.007, 0.1, 1300).cumsum() + 30,
'hue': np.repeat(np.arange(0.08, 0.20001, 0.01), 100).round(2)})
fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(12, 10), sharex=True)
sns.kdeplot(data=df, x='x', hue='hue', palette='turbo', fill=False, ax=ax1)
hues = [float(txt.get_text()) for txt in ax1.legend_.get_texts()]
ax2.set_yticks(hues)
ax2.set_ylabel('hue')
for hue, line in zip(hues, ax1.lines[::-1]):
color = line.get_color()
x = line.get_xdata()
y = line.get_ydata()
ax1.fill_between(x, y, color=color, alpha=0.3)
mode_ind = np.argmax(y)
mode_x = x[mode_ind]
sns.scatterplot(x=[mode_x], y=hue, color=color, s=50, ax=ax2)
sns.despine()
plt.tight_layout()
plt.show()

Trying to get a plotly graph object including both scatter and image to change xtick labels

I am creating a plotly figure, overlapping rectangles on an image and I want to change the xticks.
Example Code:
a = 255*np.random.random((28,28))
pil_img = Image.fromarray(a).convert('RGB')
fig2 = go.Figure(data = [go.Scatter(x=[0,10,10,0], y=[0,0,10,10], fill="toself"),go.Image(z=pil_img)])
fig2.show()
Instead of the ticks being the number of pixels (0-28) I want them to be let's say from 0.2 to 3 in increments of 0.1 [0.2,0.3,...3] so that the length is still 28 but the ticks aren't [0,1,2] but rather [0.2,0.3,..3]
Thanks!
Following this documentation page, one way to achieve it is:
import numpy as np
from PIL import Image
import plotly.graph_objects as go
N = 28
a = 255 * np.random.random((N, N))
pil_img = Image.fromarray(a).convert('RGB')
fig = go.Figure(data = [go.Scatter(x=[0,10,10,0], y=[0,0,10,10], fill="toself"),go.Image(z=pil_img)])
fig.update_layout(
xaxis = dict(
tickmode = 'array',
tickvals = np.arange(N),
ticktext = ["{:.1f}".format(t) for t in np.linspace(0.3, 3, N)]
),
yaxis = dict(
tickmode = 'array',
tickvals = np.arange(N),
ticktext = ["{:.1f}".format(t) for t in np.linspace(0.3, 3, N)]
)
)
fig

Animated Polar Plot

I am trying to make an animated plot of planetary motion using python. I can get the correct path to show up when not animated but once I try to animate it, it just shows up blank even though r and i are being output as the correct values when I try to print each value in the console.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig = plt.figure(figsize=(6,6))
ax = plt.subplot(111, polar=True)
ax.set_ylim(0,1)
line, = ax.plot([],[])
semi_major_axis = 1
eccentricity = 0.1
theta = np.linspace(0,2*np.pi, num = 50)
point, = ax.plot(0,1, marker="o")
def frame(i):
r=(semi_major_axis*(1-eccentricity**2)/(1-eccentricity*np.cos(i)))
line.set_xdata(i)
line.set_ydata(r)
return line,
ax.set_rmax(semi_major_axis+1)
ax.set_rticks(np.linspace(0,semi_major_axis+1, num = 5))
ax.set_rlabel_position(-22.5)
animation = FuncAnimation(fig, func=frame, frames=theta, interval=10)
plt.show()
I think the problem is you are plotting a point and not a line. The following code worked for me:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig = plt.figure(figsize=(6, 6))
ax = plt.subplot(111, polar=True)
ax.set_ylim(0, 1)
semi_major_axis = 1
eccentricity = 0.1
theta = np.linspace(0, 2 * np.pi, num=50)
def frame(i):
r = (semi_major_axis * (1 - eccentricity ** 2) / (1 - eccentricity * np.cos(i)))
ax.plot(i,r,'b', marker='o')
ax.set_rmax(semi_major_axis + 1)
ax.set_rticks(np.linspace(0, semi_major_axis + 1, num=5))
ax.set_rlabel_position(-22.5)
animation = FuncAnimation(fig, func=frame, frames=theta, interval=10)
plt.show()

matplotlib: jpg image special effect/transformation as if its on a page of an open book

I wish to appear a figure (and certain text) as if they are printed on a page of an open book. Is it possible to transform an jpg image programmatically or in matplotlib to have such an effect?
You can use a background axis along with an open source book image to do something like this,
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax2 = fig.add_axes([0.2, 0.3, 0.25, 0.3])
#Plot page from a book
im = plt.imread("./book_page.jpg")
implot = ax1.imshow(im, origin='lower')
# Plot a graph and set background to transparent
x = np.linspace(0,4.*np.pi,40)
y = np.sin(x)
ax2.plot(x,y,'-ro',alpha=0.5)
ax2.set_ylim([-1.1,1.1])
ax2.patch.set_alpha(0.0)
from matplotlib import rc
rc('text', usetex=True)
margin = im.shape[0]*0.075
ytext = im.shape[1]/2.+10
ax1.text(margin, ytext, "The following text is an example")
ax1.text(margin, 90, "Figure 1. Showing a sine function")
plt.show()
Which looks like this,
where I used the following book image.
UPDATE: Added non-affine transformation based on scikit-image warp example, but with Maxwell distribution. The solution saves the matplotlib line as an image in order to apply a pointwise transform. Mapping for vector graphics may be possible but I think this will be more complicated...
import numpy as np
import matplotlib.pyplot as plt
def maxwellian_transform_image(image):
from skimage.transform import PiecewiseAffineTransform, warp
rows, cols = image.shape[0], image.shape[1]
src_cols = np.linspace(0, cols, 20)
src_rows = np.linspace(0, rows, 10)
src_rows, src_cols = np.meshgrid(src_rows, src_cols)
src = np.dstack([src_cols.flat, src_rows.flat])[0]
# add maxwellian to row coordinates
x = np.linspace(0, 3., src.shape[0])
dst_rows = src[:, 1] + (np.sqrt(2/np.pi)*x**2 * np.exp(-x**2/2)) * 50
dst_cols = src[:, 0]
dst_rows *= 1.5
dst_rows -= 1.0 * 50
dst = np.vstack([dst_cols, dst_rows]).T
tform = PiecewiseAffineTransform()
tform.estimate(src, dst)
out_rows = image.shape[0] - 1.5 * 50
out_cols = cols
out = warp(image, tform, output_shape=(out_rows, out_cols))
return out
#Create the new figure
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
#Plot page from a book
im = plt.imread("./book_page.jpg")
implot = ax.imshow(im, origin='lower')
# Plot and save graph as image, will need some manipulation of location
temp, at = plt.subplots()
margin = im.shape[0]*0.1
x = np.linspace(margin,im.shape[0]/2.,40)
y = im.shape[1]/3. + 0.1*im.shape[1]*np.sin(12.*np.pi*x/im.shape[0])
at.plot(x,y,'-ro',alpha=0.5)
temp.savefig("lineplot.png",transparent=True)
#Read in plot as an image and apply transform
plot = plt.imread("./lineplot.png")
out = maxwellian_transform_image(plot)
ax.imshow(out, extent=[0,im.shape[1],0,im.shape[0]])
plt.show()
The figure now looks like,

Resources