如何实现PNG图像像素完美绘图、展示并保留原分辨率保存?
问题与解决方案
问题概述
需求:
- 读取本地PNG格式图像
- 在图像上绘制矩形等形状
- 在Jupyter Notebook中展示处理后的图像并保存回文件
使用matplotlib时遇到分辨率丢失问题:输入图像为1200x800像素,保存后的输出图像仅为496x330像素。本质原因是matplotlib基于物理单位(英寸)绘图,依赖屏幕dpi等参数,无法直接实现像素完美的绘制与原分辨率保存。
当前使用的代码:
import matplotlib.pyplot as plt import matplotlib.image as mpimg import matplotlib.patches as patches # Read the image. image_path = 'input_image.png' output_image_path = 'output_image.png' image = mpimg.imread(image_path) # Create a figure. fig, ax = plt.subplots(1) ax.axis('off') # Create a rectangle patch and add it. rect = patches.Rectangle((100, 100), 20, 20, linewidth=1, edgecolor='r', facecolor='none') ax.add_patch(rect) ax.imshow(image) # Save result. plt.savefig(output_image_path, bbox_inches='tight', pad_inches=0) # Input image: (1200x800) # Output image: (496x330)
解决方案
方案1:调整matplotlib参数实现原分辨率保存
通过手动匹配图像像素尺寸与matplotlib的figure尺寸、dpi参数,强制输出与原图一致的分辨率:
import matplotlib.pyplot as plt import matplotlib.image as mpimg import matplotlib.patches as patches image_path = 'input_image.png' output_image_path = 'output_image.png' image = mpimg.imread(image_path) # 获取图像的像素高度与宽度 h, w = image.shape[:2] # 设定dpi值,前后保持一致即可 dpi = 100 # 计算figure尺寸:像素数 / dpi,得到英寸单位的尺寸 fig, ax = plt.subplots(figsize=(w/dpi, h/dpi), dpi=dpi) ax.axis('off') # 绘制矩形,坐标为像素级,与原图完全对应 rect = patches.Rectangle((100, 100), 20, 20, linewidth=1, edgecolor='r', facecolor='none') ax.add_patch(rect) ax.imshow(image) # 保存时指定相同dpi,同时消除边距 plt.savefig(output_image_path, bbox_inches='tight', pad_inches=0, dpi=dpi) plt.show() # 在Jupyter Notebook中展示图像
方案2:使用Pillow(推荐,更适合像素级操作)
Pillow是专门的图像处理库,完全基于像素逻辑操作,无需考虑物理单位,直接实现像素完美绘制与原分辨率保存:
from PIL import Image, ImageDraw from IPython.display import display # 读取本地PNG图像 image_path = 'input_image.png' output_image_path = 'output_image.png' img = Image.open(image_path) # 创建绘图对象 draw = ImageDraw.Draw(img) # 绘制矩形:参数为左上角坐标与右下角坐标,outline指定边框颜色,width指定边框宽度 draw.rectangle([(100, 100), (120, 120)], outline='red', width=1) # 在Jupyter Notebook中展示处理后的图像 display(img) # 保存回原分辨率的PNG文件 img.save(output_image_path)
内容的提问来源于stack exchange,提问作者user2623674
相关产品推荐
相关产品推荐

