如何用Matplotlib叠加显示图像?含背景、曲线与热图叠加需求
Got it, let's walk through exactly how to build this plot step by step. I'll include a full, adaptable code example that covers all your requirements: using a background image, plotting your curve, and placing a rotated heatmap (saved via plt.imsave) that only covers part of the background.
Step-by-Step Breakdown & Code
First, let's import the tools we'll need:
import matplotlib.pyplot as plt import numpy as np from PIL import Image import io # For in-memory file handling (avoids temp files)
1. Prepare Your Rotated Heatmap
Since you mentioned needing to rotate the heatmap before use, we'll handle that and save it (here's a clean in-memory approach to avoid temp files):
# Replace this with your actual heatmap data (numpy array) model_prediction_i = np.random.rand(100, 100) # Example random heatmap # Rotate the heatmap (adjust k=1 for 90°, k=2 for 180°, etc.) rotated_heatmap = np.rot90(model_prediction_i, k=1) # Save rotated heatmap to memory (no temp file needed!) buf = io.BytesIO() plt.imsave(buf, rotated_heatmap, cmap='viridis', format='png') # Pick your preferred colormap buf.seek(0) heatmap_img = Image.open(buf)
2. Load Background & Set Up Canvas
We'll create a canvas that matches the background image's dimensions for perfect alignment:
# Load your background image background = Image.open("reference.jpg") # Create figure matching background size (dpi=100 ensures 1px = 0.01in) fig, ax = plt.subplots( figsize=(background.width/100, background.height/100), dpi=100 ) # Draw the background as the base layer ax.imshow(background)
3. Plot Your X_test_i Curve
Add your curve on top of the background. Replace the example data with your actual X_test_i values:
# Replace this with your actual X_test_i data (x and y arrays) x = np.linspace(0, background.width, 200) # Example x-values spanning background width y = np.random.randint(50, background.height-50, 200) # Example y-values # Plot the curve (customize color, linewidth, label as needed) ax.plot(x, y, color='#ff3333', linewidth=2.5, label='X_test_i') ax.legend(fontsize=12, loc='upper right')
4. Position & Overlay the Heatmap
Now place the rotated heatmap on a specific part of the plot. We'll convert pixel coordinates to axis coordinates for precise placement:
# Define where to place the heatmap (pixel coordinates on the background) # Adjust these values to your desired position/size heatmap_x_start = 150 # Left edge pixel position heatmap_y_start = 100 # Bottom edge pixel position heatmap_width = heatmap_img.width // 2 # Resize to 50% original width heatmap_height = heatmap_img.height // 2 # Resize to 50% original height # Convert pixel positions to normalized axis coordinates (matches the background) x0, y0 = ax.transData.inverted().transform((heatmap_x_start, heatmap_y_start)) x1, y1 = ax.transData.inverted().transform(( heatmap_x_start + heatmap_width, heatmap_y_start + heatmap_height )) # Add a new axis for the heatmap (no ticks/borders to keep it clean) heatmap_ax = fig.add_axes([x0, y0, x1 - x0, y1 - y0]) heatmap_ax.axis('off') # Draw the resized heatmap heatmap_ax.imshow(heatmap_img.resize((heatmap_width, heatmap_height)))
5. Finalize & Display/Save
Clean up the plot and show or save your final result:
# Optional: Hide the main axis ticks if they're unnecessary ax.axis('off') # Show the plot plt.show() # Or save it to a file (high DPI for crispness) # plt.savefig("final_overlay_plot.png", dpi=300, bbox_inches='tight')
Key Notes
- Why
plt.imsave? Saving the rotated heatmap (even in memory) lets us treat it as a raster image, making it easy to resize and position precisely without worrying about array alignment issues. - Precise Placement: Using
ax.transData.inverted().transform()ensures your heatmap aligns perfectly with the background image's pixel grid. - No Temp Files: The
io.BytesIOapproach keeps everything in memory, so you won't have leftover files cluttering your workspace.
内容的提问来源于stack exchange,提问作者Noltibus




