I have plotted some data that are defined by specific coordinates and a value.
I have plotted this with a scatterplot, and would now like to plot this on top of an image, to reflect where the data points are located.
I have tried to use matplotlib.image and import img to be able to show the image. Unfortunately, the image of my location does not match up with the data completely (due to stretching, I believe).
When I edit the extent Python either edits out some of the image, instead of moving my data. I would like to be able to move the image/crop it to fit with the data or use some sort of package to load in a map (as I have the coordinates). This needs to show a local stream in Denmark.
x and y are our coordinates (lat, lon) and z is the value each coordinate have.
plt.figure(figsize=(20,10))
plt.scatter(x,y, cmap = 'gist_heat' ,s=100,c=z)
plt.colorbar()
plt.ylim(np.min(y),np.max(y))
plt.xlim(np.min(x),np.max(x))
img = plt.imread("grindsted4_sattelit.png")
ext = [np.min(x),np.max(x), np.min(y), np.max(y)]
plt.imshow(img, zorder=0, extent=ext)
aspect=img.shape[0]/float(img.shape[1])*((ext[1]-ext[0])/(ext[3]-ext[2]))
plt.gca().set_aspect(aspect)
plt.show()
The plot are the colored dots, and the black and white dots are my coordinates in Google Earth.
Thank you!
Related
I have an image in python. It's a map of california, and I need to place some point on this map.
The coordonate of each point are retrieve from a csv. But the value of each coordinate are in latitude/longitude. So, i need to convert it to the dimension of my picture.
So, here's is the description of my situation:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
# dpi for the saved figure: https://stackoverflow.com/a/34769840/3129414
dpi = 120
img = mpimg.imread("california_map_blank.png")
height, width, bands = img.shape
# Update figure size based on image size
figsize = width / float(dpi), height / float(dpi)
# Create a figure of the right size with one axes that takes up the full figure
figure = plt.figure(figsize=figsize)
axes = figure.add_axes([0, 0, 1, 1])
# Draw the image
axes.imshow(img, interpolation='nearest')
Here's the result:
First i need to modify the y-axis. I need to inverse it so the 0 start at the bottom. Then I need to modify the value of the axis, [31,42] for y-axis and [-123,-114] for x-axis. Because the point I want to place in this map are all in this range. One example of coordinate: 41.76440000093729, -124.1998.
Now here's my question. Is it possible to achieve this ? How ?
PS: I use python 3.6, and I already know how to place point on the image. I don't need to save the image just showing.
PPS: My final goal in fact is to convert lat/lon data into coordinate in a picture so if you know any other way to do it(in Python of course) please tell me.
EDIT: If I apply this: axes.set_xlim(-124.5,-114) it give me this:
I want to have the axis with this range but with the whole image.
In fact, at the end I will not display the axis I will just put the map with the points, but I need to place the point on the map so I think I need to go through this step.
EDIT2: I tried this: axes.imshow(img[::-1], origin='lower', interpolation='nearest') it works fine to reverse the axis but when I draw a point python draw it in the same place when I the axis was normal.
You need to set the limits of the image via the extent= parameter of imshow. These should be quite precise values for the longitudes left and right, and for the latitudes of bottom and top.
Depending on how deformed the map is, the result can be good enough or not. Try to find the exact longitudes and latitudes of the corners of your map, e.g. via Google Maps.
Depending on how you're running your Python program, matplotlib will show an interactive plot. You can zoom to every region, and the axes will adapt. In the bar at the bottom the x and y-positions will be shown. If they are not the desired ones, you can try to change the extents until they match.
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
img = mpimg.imread("california_map_blank.png")
dpi = 120
height, width, bands = img.shape
# Update figure size based on image size
figsize = width / float(dpi), height / float(dpi)
# Create a figure of the right size with one axes that takes up the full figure
fig, ax = plt.subplots(figsize=figsize)
# find the extent
longitude_top_left = -124.5
longitude_top_right = -113
latitude_bottom_left = 32
latitude_top_left = 42
extent = [longitude_top_left, longitude_top_right, latitude_bottom_left, latitude_top_left]
# Draw the image
ax.imshow(img, interpolation='nearest', extent=extent)
plt.show()
I have a set of pixel values that I wanted to map on an image as a heatmap. My pixel values look something like this: they are x,y coordinates of image pixels of an arbitrary resolution.
pixel values = [[1,1],[2,1],[3,1],[4,1],[2,1]]
I have tried using OpenCV but I fail to understand how to get it to work. I assume a probability/density distribution needs to be generated, or perhaps the plotting function can do this automatically ? Since the image is loaded using OpenCV, I was looking for an OpenCV function, if Matplotlib works, please do comment.
heatmap_array = np.array(heatmap)
cv_colormap = cv2.applyColorMap(heatmap_array[0:], cv2.COLORMAP_HOT)
cv2.imwrite("colormap_gen.jpg", cv_colormap)
There needs to be an slightly opaque overlay of the heatmap on top of the original image.
You can try with Matplotlib:
# sample data
# xy can be np.array(pixel_values)
np.random.seed(1)
xy = np.random.multivariate_normal([300,300], [[2000,400],[400,1000]], 2000000)
# compute the hist
# bins here are the size of the image
hist,_,_ = np.histogram2d(xy[:,0], xy[:,1], bins=(600,800))
# show heatmap by plt
# you can use plt to save the figure
fig = plt.figure(figsize=(12,8))
plt.imshow(hist,cmap='hot')
plt.axis('off')
plt.show()
Output:
I have a calculated data (x,y) which I would like to put on top of an image from a paper to compare with some of its boundaries. If this image was a 2D x,y plot, I would have extracted easily the points and then plot together with mine. However this image is a 3D color plot, therefore if I want just to read the image, define my coordinates according to it and plot my data on top, so at the end would seem like 2 layers.
I can plot scatter points by following:
import matplotlib.pyplot as plt
im = plt.imread('fig_exp.png')
implot = plt.imshow(im)
# put a blue dot at (10, 20)
plt.scatter([10], [20], c='r', s=2000, marker=u'*')
plt.show()
But how can I define image coordinates so I can plot e.g
x=[-100,-80,-60,-40]
y=[10,15,20,25]
plt.plot(x,y,'-ro')
The problem here is that I dont know how to define the coordinates as in the figure. Beside I dont know how to plot not as scatter but a line.
I appreciate any helpful solution!
You are looking for the extent= keyword argument to imshow() as detailed in the documentation
As for your second question, if you want a line plot, you use the plot() function instead of scatter().
I've taken an image and extracted some features from it using OpenCv. I'd like to replot those points and their respective areas (which are real pixel values) into a scatter window and then save it. Unfortunately, when I plot the points, they resize to stay more visible. If I zoom in they resize. I'd like to save the whole figure retaining the actual ratio of pixel (x,y) coordinates to size of points plotted.
For instance:
import matplotlib.pyplot as plt
x=[5000,10000,20000]
y=[20000,10000,5000]
area_in_pixels=[100,200,100]
scatter(x,y,s=area_in_pixels)
I would like this to produce tiny dots on the image. They should span like 10 xy units. However, the dots it produces are large, and appear to span 1000 xy units.
I've tried resizing the image with:
plt.figure(figsize=(10,10))
Which seems to resize the points relative to their position a little. But I'm not sure what scale I would select to make this accurate. DPI settings on plt.figsave seem to make the saved image larger but don't appear to alter relative spot sizes.
Asked another way, is there another way to relate the s which is in points^2 to a real number or to the units of the x-y axis?
You can use patches to create markers sized relative to the data coordinates.
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
xData=[5000,10000,20000, 15000]
yData=[20000,10000,5000, 15000]
radius_in_pixels=[100,200,100, 1000] # Circle takes radius as an argument. You could convert from area.
fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
for x, y, r in zip(xData, yData, radius_in_pixels):
ax.add_artist(Circle(xy=(x, y), radius = r))
plt.xlim(0, max(xData) + 200)
plt.ylim(0, max(yData) + 200)
plt.show()
I am working on identifying tumors in CT images, using SciPy. Once I've identified the slice containing the tumor, I retrieve the slice using:
slice_x, slice_y = ndimage.find_objects(label_im==label)[0]
I then plot the full image as follows:
plt.imshow(image, cmap='gray')
I want to overlay the contour of the extracted slice (containing the tumor) on top of the original image in the appropriate location. However, I can't get the contour plot to lie on top of the proper region. Instead, the contour plot always lies in the top-left corner of the image. Here's what I'm using:
plt.contour(mask[slice_x, slice_y], position=(slice_x.start, \
slice_y.start), linewidths=2, colors='r')
Here is the result:
How can I set the position of the contour plot inside the main plot? Thanks!
You need to use the extent keyword argument instead of position. However, you'll need to specify a maximum as well as a start (i.e. it needs to be extent=[xmin, xmax, ymin, ymax])
In your case, it would look something like:
extent=[xslice.start, xslice.stop+1, yslice.start, yslice.stop+1]
plt.contour(mask[xslice, yslice], extent=extent)
Note that you may need to use the origin keyword argument (or flip ymin and ymax) to control the way the input data is interpreted.
Alternately, you could do something like the following:
x, y = np.mgrid[xslice, yslice]
plt.contour(x, y, mask[xslcie, yslice])
It will be a bit inefficient if you're working with a large region, but it's much cleaner.
As a full example of the latter approach:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
data = np.random.random((100,100))
xslice, yslice = slice(20, 30), slice(45, 65)
plt.imshow(data, cmap=cm.gray)
x, y = np.mgrid[xslice, yslice]
plt.contour(x, y, data[xslice, yslice])
plt.show()