Okay, So i'm trying to take the red channel of an image, and plot it (preferably 3d) to an image. The image is 480x640 (or thereabouts), and is taken from a webcam. I'm currently using scipy, numpy, and python to get the image, extract he red channel, and process it. That all works.
However, when i try to plot it, 2 different problems occur, depending on how I try to plot:
1) Width mismatch, it doesn't like that the image isn't square.
2) It only plots one row of the image (x val = 0, all y vals).
I've attached the relevent code. Comments are everywhere, for when i try different ways.
fig = plt.figure()
#ax = Axes3D(fig)
#ax = fig.add_subplot(111, projection='3d')
X = [range(480), range(480)]
Y = [range(480), range(480)]
#X = range(len(self.R))
#Y = range(len(self.R))
'''
surf = ax.plot_surface(X, Y, np.resize(self.R, (480, 480)) , rstride=1, cstride=10, cmap=cm.jet, linewidth=0, antialiased=False)
ax.set_zlim3d(0.0, 255.0)
ax.w_zaxis.set_major_locator(LinearLocator(100))
ax.w_zaxis.set_major_formatter(FormatStrFormatter('%.03f'))
m = cm.ScalarMappable(cmap=cm.jet)
m.set_array(self.frame_in)
fig.colorbar(m)
np.savetxt("tmp.txt", self.R)
'''
#np.savetxt("tmp.out", self.R[0])
#np.savetxt("tmp.out1", self.R[1])
#np.savetxt("tmp.txt", self.frame_in, "[ %s ]", "\t")
#plt.subplot(212)
#x, y = self.R.shape
#x = range(x)
#y = range(y)
#X, Y = np.meshgrid(x, y)
plt.scatter(X, Y, self.R)
#plt.pcolormesh(self.R)
#plt.colorbar()
#ax.scatter(x, y, self.R, c='r', marker='o')
plt.show()
I can clean up the code if needed, but i wanted everyone to see the multiple ways i've tried. Am i missing something really stupid simple? It doesn't make sense that it will work with the first row, and not all of them.
Thanks in advance!
Try using pyplot.imshow:
plt.cmap('Reds')
plt.imshow(self.R)
plt.show()
Related
I'm having trouble understanding a strange side effect of interpolating my data. I am plotting a 2D surface onto a 3D grid, this part works fine, however as soon as I tweaked it to include scipy.interpolate I get a strange glitch, (at least I think it is a glitch).
Below is an image of two plots, LHS is the original data, RHS the interpolated plot. As you can see I have rotated the RHS so that the similarities between the shapes are clear, but as a result the axis facing us is different;
(I have rotated both of these extensively and I'm confident the symmetry in this view is not a coincidence, it looks too similar and they look too different when viewed at the same rotation)
To add interpolation to my code I followed the answer to this question:
Smooth surface Plot with Pyplot
I'll also add my code before and after I added that bit, in the hope that there's something really obvious I've missed
ax = fig.add_subplot(111, projection='3d')
#y is the sin(beta-alpha) value, x is the tan(beta) value and z is the cross-section in fb
y = np.array(Y_list)
x = np.array(x_list)
X, Y = np.meshgrid(x, y)
zs = np.array(z_list)
Z = zs.reshape(Y.shape)
print(type(Z))
print(Z.shape)
ax.plot_surface(X, Y, Z)
plt.ylabel(r"$Sin(\beta - \alpha)$")
plt.xlabel(r"$Tan(\beta)$")
ax.zaxis.set_rotate_label(False) # disable automatic rotation
ax.set_zlabel('Cross-section (pb)', rotation=90)
#this is the rotation bit
for angle in range(0, 360):
ax.view_init(30, angle)
plt.draw()
plt.pause(.001)
(Obviously there is code beforehand importing everything such as numpy, scipy etc and getting the data, but this is untouched between the two versions)
y = np.array(Y_list)
x = np.array(x_list)
xstart = float(x[0])
xend = float(x[-1])
ystart = float(y[0])
yend = float(y[-1])
X, Y = np.mgrid[xstart:xend:10j, ystart:yend:22j]
zs = np.array(z_list)
#Z = zs.reshape(Y.shape)
#The following lines perform interpolation
tck = interpolate.bisplrep(X, Y, zs, s=0)
Znew = interpolate.bisplev(X[:,0], Y[0,:], tck)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(X, Y, Z)
plt.ylabel(r"$Sin(\beta - \alpha)$")
plt.xlabel(r"$Tan(\beta)$")
ax.zaxis.set_rotate_label(False) # disable automatic rotation
ax.set_zlabel('Cross-section (pb)', rotation=90)
#this is the rotation bit
for angle in range(0, 360):
ax.view_init(30, angle)
plt.draw()
plt.pause(.001)
I'm stumped and any help would be appreciated!
I am trying to plot a full cylinder, using a cylindrical mesh grid.
However I just managed to get half a cylinder. Here is my code
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
r = 1
x = np.linspace(-r, r, 50)
y = np.linspace(-r, r, 50)
X, Y = np.meshgrid(x, y)
Z = (np.pi * -Y**2)
surf = ax.plot_surface(X, Y, Z)
What I would like to obtain is something like this
Could anybody give me some insights on how to do it?
In this post the ax.plot_surface function is called twice. In your case adding a minus sign to the Z does not yet result in a cylinder, but at least you have a top and bottom part.
I'm trying to plot a heatmap with the plt.pcolormesh, and then plot the outline of my figure with the plt.scatter and I would like to crop the result according to the shape of the last plot which is the outline.
It doesn't seem that hard to do but still I haven't managed to do it or found anything. Here is my code and an image to illustrate, thank you for your help!
plt.rcParams["figure.figsize"] = (10.0, 10.0)
plt.axis("off")
plt.pcolormesh(x, y, intens)
plt.colorbar()
coord = np.genfromtxt("myfile.csv", delimiter = ' ')
x = [coord[i][0] for i in range(0, len(coord))]
y = [coord[i][1] for i in range(0, len(coord))]
plt.scatter(x, y, c = 'k', s = 1.)
Image here
You can just use plt.xlim() and plt.ylim() and give them the coordinates of the new figure. Here is a modified version of the code:
plt.rcParams['figure.figsize'] = (10.0, 10.0)
plt.axis('off')
plt.pcolormesh(x, y, intens)
plt.colorbar()
coord = np.genfromtxt('myfile.csv', delimiter=' ')
x = coord[:, 0]
y = coord[:, 1]
plt.scatter(x, y, c='k', s=1.)
plt.xlim([np.min(x), np.max(x)])
plt.ylim([np.min(y), np.max(y)])
As I present here (in 2D), I'm wondering if how I could "scale" an image input to be plotted to a range in the plot. To be more clear, this is what I need:
I have a 400 * 400 image that is generated based on a function which interval is -1..1. So, I do a translate to save this data, like this:
x = Utils.translate(pos_x, 0, self.width, -1, 1)
y = Utils.translate(pos_y, 0, self.height, -1, 1)
data = Utils.map_position_to_function(x, y)
I.e, first I map its position to my range and then I calculate de f(x, y) based on this "new position" and save the data. Also, as I save this image, I do a translate in data so it fits in a 0..255 range, generating a grayscale image.
The problem is that, later, I have to represent the image contour in the function range. So, I have an image, 400 * 400, that I have to represent in a plot which range is -1..1.
In 2D, I could do this with this code:
im = plt.array(Image.open('Mean.png').convert('L'))
plt.figure()
CS = plt.contour(im, origin='image', extent=[-1, 1, -1, 1])
plt.clabel(CS, inline=1, fontsize=10)
plt.savefig("CountorLevel2D.png")
In 3D, I tried this:
fig = plt.figure()
ax = fig.gca(projection='3d')
row = np.linspace(0, 400, 400)
X,Y = np.meshgrid(row,row)
CS = ax.contour(X, Y, im, cmap=cm.coolwarm, extent=[-1, 1, -1, 1])
plt.clabel(CS, inline=1, fontsize=10)
plt.savefig("ContourLevel3D.png")
But the X and Y are still in the 0..400 range. I don't know what is wrong, or what I have to do to have X and Y in -1..1 range. Besides, no label is shown.
Also, as im is an image, I read values which ranges between 0..255 values. How could I present this in an -1..1 range too?
Thanks in advance. (:
Try this insted:
fig = plt.figure()
ax = fig.gca(projection='3d')
row = np.linspace(-1, 1, 400)
X,Y = np.meshgrid(row,row)
CS = ax.contour(X, Y, im, cmap=cm.coolwarm)
plt.clabel(CS, inline=1, fontsize=10)
plt.savefig("ContourLevel3D.png")
I have one question about the grid lines matplotlib.
I am not sure if this is possible to do or not.
I am plotting the following graph as shown in the image.
I won't give the entire code, since it is involving reading of files.
However the important part of code is here -
X, Y = np.meshgrid(smallX, smallY)
Z = np.zeros((len(X),len(X[0])))
plt.contourf(X, Y, Z, levels, cmap=cm.gray_r, zorder = 1)
plt.colorbar()
...
# Set Border width zero
[i.set_linewidth(0) for i in ax.spines.itervalues()]
gridLineWidth=0.1
ax.set_axisbelow(False)
gridlines = ax.get_xgridlines()+ax.get_ygridlines()
#ax.set_axisbelow(True)
plt.setp(gridlines, 'zorder', 5)
ax.yaxis.grid(True, linewidth=gridLineWidth, linestyle='-', color='0.6')
ax.xaxis.grid(False)
ax.xaxis.set_ticks_position('none')
ax.yaxis.set_ticks_position('none')
Now, my questions is like this -
If I put the grid lines below the contour, they disappear since they are below it.
If I put the grid line above the contour, they looks like what they are looking now.
However, what I would like to have is the grid lines should be visible, but should be below the black portion of the contour. I am not sure if that is possible.
Thank You !
In addition to specifying the z-order of the contours and the gridlines, you could also try masking the zero values of your contoured data.
Here's a small example:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(-2*np.pi, 2*np.pi, 0.1)
y = np.arange(-2*np.pi, 2*np.pi, 0.1)
X, Y = np.meshgrid(x, y)
Z = np.sin(X) - np.cos(Y)
Z = np.ma.masked_less(Z, 0) # you use mask_equal(yourData, yourMagicValue)
fig, ax = plt.subplots()
ax.contourf(Z, zorder=5, cmap=plt.cm.coolwarm)
ax.xaxis.grid(True, zorder=0)
ax.yaxis.grid(True, zorder=0)
And the output: