Matplotlib中imshow与quiver的坐标约定差异技术咨询
imshow and quiver in Matplotlib Let’s break down exactly why your code isn’t behaving as expected, and how to fix this common confusion when overlaying vector fields on images.
The Root Cause: Opposite Dimension-to-Axis Mappings
The key issue here is that imshow and quiver interpret array dimensions and coordinate axes in reverse ways:
1. How imshow handles coordinates
When you pass a 2D array like img = np.random.randn(20, 40) to imshow:
- The first dimension (20, rows of the array) maps to the y-axis of the plot (vertical direction)
- The second dimension (40, columns of the array) maps to the x-axis of the plot (horizontal direction)
Even withorigin='lower', this dimension-to-axis mapping stays the same—originonly flips whether the first row of the array is drawn at the top or bottom of the plot, not which axis it’s assigned to. So your image spansx: 0→39andy: 0→19.
2. How quiver handles coordinates
quiver uses standard Cartesian coordinates:
- The first value you pass (
xs=15) is the x-axis position (horizontal) - The second value (
ys=30) is the y-axis position (vertical)
In your code,ys=30is way outside the image’s y-axis range (max 19), which is why the arrow doesn’t appear within the image bounds. Your calculation15+4<20mixes up axes—15 is an x-coordinate (which goes up to 39, so 15+4=19 is fine), but 30 is a y-coordinate (which only goes up to 19, so 30 is already out of bounds).
Fixing the Problem
You have two straightforward solutions, depending on whether you want to adjust the image or the vector field:
Option 1: Transpose the image
By transposing img with img.T, you swap its rows and columns. Now the array becomes (40,20), so:
- The new first dimension (40) maps to y-axis (range 0→39)
- The new second dimension (20) maps to x-axis (range 0→19)
This aligns with your originalxs=15(x-axis, within 0→19) andys=30(y-axis, within 0→39), so the arrow appears where you expect.
Option 2: Swap coordinates in quiver
Instead of transposing the image, swap the x/y parameters in quiver to match imshow’s dimension mapping:
plt.quiver(ys, xs, vs, us, scale_units='xy', angles='xy', scale=1)
Here, we’re passing the original y-position (30) as the x-coordinate for quiver (since it corresponds to the image’s columns), and the original x-position (15) as the y-coordinate (corresponding to the image’s rows). We also swap us and vs to keep the arrow direction correct.
Handling RGB Images
For RGB images (shape (H, W, 3) where H=height, W=width), the same rule applies:
- H (rows) maps to y-axis
- W (columns) maps to x-axis
When overlaying vector fields, make sure your vector coordinates follow this: if your vector’s horizontal component corresponds to image width (W), it should be the x-value inquiver; vertical components (H) should be the y-value. If you find yourself transposing the image to make things line up, double-check that yourquivercoordinates are mapped to the correct axes.
内容的提问来源于stack exchange,提问作者Jatentaki

