I would like to blit a 2d image (like a png) to a location in 3-space on a 3D matplotlib figure. Essentially, I want the image to always be facing the user regardless of how the plot is rotated. It would be best if the blitted image did not scale as the user zoomed in and out as well.
One would think that this would be easy to do by accessing the low level rastering functions in matplotlib, but I can't find any documentation that describes what I would like to do.
If you put in an image as an annotation, zooming in on the axes will not scale the image. For example, see this demo. (To run the demo script, replace grace_hopper.png with lena.png.)
For example, just for an easy reference on zooming I've added a line of blue squares to the plot. The top image below show the unzoomed, and I've zoomed in in the lower one.
Related
I want to create a figure that shows a background image with overlaid scatter and line plots:
As you can see, the axes ticks show image coordinates. The scatter and line plot are given in image coordinates, too - which is not desired. The scatter and line plots should still be able to work (and be meaningful) without the background image. The extent is not known because this figure is used to determine the extent (interactively) in the first place.
Instead, I'd like to specify the scatter and line plots in the coordinate system shown in the background image (units m³/h and m): the transformation from image coordinates to "axis on top" coordinates would be roughly (110,475) -> (0,10) and (530,190) -> (8,40).
In principle I can see two ways of doing it:
specify image extent after it has been added. However, I don't see this documented anywhere; This example shows how it's done when the extent is known at the call to imshow(): Plot over an image background in python
add an axes on top of the image axes with twinx and twin y, where both x,x and y,y pairs are tightly coupled. I have only seen features that allow me to specify a shared x or a shared y axis, not both.
The restriction here seems to be that "The scatter and line plots should still be able to work (and be meaningful) without the background image.". This however would not imply that you cannot use the extent keyword argument.
At the time you add the image, you'd specify the extent.
plt.scatter(...)
plt.plot(...)
plt.imshow(..., extent = [...])
You can also set the extent later, if that is desired for some reason not explained in the question, i.e.
plt.scatter(...)
plt.plot(...)
im = plt.imshow(...)
im.set_extent([...])
Finally you may also decide to remove the image, and plot it again; this time with the desired extent,
plt.scatter(...)
plt.plot(...)
im = plt.imshow(...)
im.remove()
im = plt.imshow(..., extent=[...])
I am generating contour plots (with transparent background) for pH of water on a river, and am overlaying the generated plot on the interactive map using map box. It looks like this:
I want to overlay plot in only on the water area, and not show over the ground area.
In my understanding there should be two ways possible:
1. While generating the image, making that part invisible
2. While overlaying the image, making that part invisible
I have tried finding solution for both but couldn't get a solution. Is there any way to go about it?
Dear stackoverflow community!
I need to plot a 2D-map in python using imshow. The command used is
plt.imshow(ux_map, interpolation='none', origin='lower', extent=[lonhg_all.min(), lonhg_all.max(), lathg_all.min(), lathg_all.max()])
The image is then saved as follows
plt.savefig('rdv_cr%s_cmlon%s_ux.png' % (2097, cmlon_ref))
and looks like
The problem is that when zooming into the plot one can notice that the pixels have different shapes (e.g. different width). This is illustrated in the zoomed part below (taken from the top region of the the first image):
Is there any reason for this behaviour? I input a rectangular grid for my data, but the problem does not have to do with the data itself, I suppose. Instead it is probably something related to rendering. I'd expect all pixels to be of equal shape, but as could be seen they have both different widths as well as heights. By the way, this also occurs in the interactive plot of matplotlib. However, when zooming in there, they become equally shaped all of a sudden.
I'm not sure as to whether
https://github.com/matplotlib/matplotlib/issues/3057/ and the link therein might be related, but I can try playing around with dpi values. In any case, if anybody knows why this happens, could that person provide some background on why the computer cannot display the plot as intended using the commands from above?
Thanks for your responses!
This is related to the way the image is mapped to the screen. To determine the color of a pixel in the screen, the corresponding color is sampled from the image. If the screen area and the image size do not match, either upsampling (image too small) or downsampling (image too large) occurs.
You observed a case of upsampling. For example, consider drawing a 4x4 image on a region of 6x6 pixels on the screen. Sometimes two screen pixels fall into an image pixel, and sometimes only one. Here, we observe an extreme case of differently sized pixels.
When you zoom in in the interactive view, this effect seems to disapear. That is because suddenly you map the image to a large number of pixels. If one image pixel is enlarged to, say, 10 screen pixels and another to 11, you hardly notice the difference. The effect is most apparent when the image nearly matches the screen resolution.
A solution to work around this effect is to use interpolation, which may lead to an undesirable blurred look. To reduce the blur you can...
play with different interpolation functions. Try for example 'kaiser'
or up-scale the image by a constant factor using nearest neighbor interpolation (e.g. replace each pixel in the image by a block of pixels with the same color). Then any blurring will only affect the edges of the block.
Is there a way to show the row and column axes when displaying an image with cv2.imshow()? I am using the python bindings for opencv3.0
Not that I am aware of.
However, since you are using Python you are not constrained to use the rudimentary plotting capabilities of OpenCV HighGUI.
Instead, you can use the much more competent matplotlib library (or any of the other available Python plotting libraries).
To plot an image, including a default axis you do
import matplotlib.pyplot as plt
plt.imshow(image, interpolation='none') # Plot the image, turn off interpolation
plt.show() # Show the image window
I'm not sure I fully understand the question due to lack of info.
However you can use OpenCV's draw line function to draw a line from the example points (10,10) to (10,190), and another from (10,190) to (190,190)
On an example image that is 200X200 pixels in size, this will draw a line down the left hand side of the image, and a line along the bottom. You can then plot numbers or whatever you want along this line at increments of X-pixels.
Drawing text/numbers to an image is similar to drawing a line.
Once you have drawn the image, show with the usual image.imshow().
See OpenCV's drawing documentation here:
http://docs.opencv.org/modules/core/doc/drawing_functions.html
And an example to get you going can be found here:
http://opencvexamples.blogspot.com/2013/10/basic-drawing-examples.html#.VMj-bUesXuM
Hope this helps.
I have some data made of coordinates and the count of each coordinate which I plot in a heatmap like this:
pyplot.subplot(211)
pyplot.scatter(longitudes, latitudes, c=counts)
pyplot.colorbar()
which is inspired by this great answer here in SO.
If you look closely you can see, that the dots shape the worldmap somehow. To underline this effect I'd like to put the real country boarders (simply drawn would be enough) as background to my plot. Is this possible with matplotlib? Maybe there is some (hidden) builtin in matplotlib?
You can likely achieve this if you have some image of the world map that you want as a background. You can read this into a numpy array and plot the image. Then you should be able to add your scatter plot overtop of the image. This matplotlib cookbook example shows how to insert images and such. There is also the matplotlib image tutorial that may be of use.
I've not used it, but you may also be interested in the basemap toolkit for matplotlib. In particular, the section on drawing a map background mentions specifically a drawcountries() method.