如何提升插入Word表格的Matplotlib生成图像质量(适配3英寸列宽)
问题:生成数理练习题工作表时图像质量与尺寸适配矛盾
我正在编写Python程序自动生成数理练习题工作表,只需输入少量参数(如题目数量),每次运行就能生成全新题目。目前的试点程序用于生成多边形反射操作的练习题:主模块负责创建带表格的Word文档,调用子模块生成笛卡尔坐标系下的多边形图,再将图像插入表格单元格,循环生成题目。
主模块代码
import os import random from docx import Document from docx.shared import Inches from datetime import datetime from docx.oxml import OxmlElement, ns import Trapezoid_in_Cartesian_Grid_1 from PIL import Image from pathlib import Path doc = Document() tbl = doc.add_table(rows=1, cols=0) tbl.add_column(width=Inches(0.4)) tbl.add_column(width=Inches(3.0)) tbl.add_column(width=Inches(3.0)) def image_to_jpg(image_path): path = Path(image_path) if path.suffix not in {'.jpg', '.png', '.jfif', '.exif', '.gif', '.tiff', '.bmp'}: jpg_image_path = f'{path.parent / path.stem}_result.png' Image.open(image_path).convert('RGB').save(jpg_image_path, quality=95) return jpg_image_path return image_path for i in range(10): a = random.randint(-8,8) b = random.randint(-8,8) h = random.randint(-3,3) k = random.randint(-3,3) path = Trapezoid_in_Cartesian_Grid_1.ReflectTrap01OverXaxis(a,b,h,k) image_path = image_to_jpg(path) row = tbl.add_row() cell1 = tbl.cell(i,0) cell1.text = str(i+1) + "." cell2 = tbl.cell(i,1) cell2.text = "Reflect the figure over the y-axis." cell3 = tbl.cell(i,2) paragraph = tbl.rows[i].cells[2].paragraphs[0] run = paragraph.add_run() run.add_picture(image_path) # 获取当前时间作为文件名 current_datetime = datetime.now().strftime("%Y-%m-%d %H%M%S") file_name = "WS_Proj " + current_datetime header = doc.sections[0].header header.paragraphs[0].text = file_name doc.save(file_name + ".docx")
子模块(Trapezoid_in_Cartesian_Grid_1)代码
from datetime import datetime import matplotlib.pyplot as plt import numpy as np from matplotlib.path import Path import matplotlib.patches as patches from matplotlib.ticker import MultipleLocator from docx.shared import Inches import matplotlib.ticker as ticker import random current_datetime = datetime.now().strftime("%Y-%m-%d %H%M%S") def ReflectTrap01OverXaxis(a,b,h,k): # 创建多边形顶点 verts1 = [(a,b),(a+h,b),(a+h,b-k),(a,b-k+1),(a,b)] codes1 = [Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY] fig = plt.figure(figsize=(2.5,2.5)) ax = fig.add_subplot(111) path1 = Path(verts1, codes1) patch1 = patches.PathPatch(path1, edgecolor="black", facecolor="None", lw=0.8, zorder=3) ax.add_patch(patch1) # 设置坐标轴范围 ax.set_xlim(-12,12) ax.set_ylim(-12,12) plt.grid(True) plt.tick_params(labelsize=6) plt.xlabel(None, fontsize=9) # 重复设置figsize,可合并到figure创建时 plt.rcParams["figure.figsize"] = [3,3] # 绘制坐标轴 plt.axhline(color="black") plt.axvline(color="black") ax.grid(which="both", color="black", linewidth=0.5) ax.minorticks_on() # 生成唯一文件名并保存图像 current_datetime = datetime.now().strftime("%Y-%m-%d %H%M%S") file_name = "fig1 " + current_datetime plt.savefig(file_name, format="png") return file_name
当前问题
插入表格的图像质量过低,尝试过SVG、PDF等格式,调整DPI虽能提升质量,但会导致图像尺寸过大,无法适配3英寸宽的表格列。

解决方案
1. 优化Matplotlib图像导出参数
在plt.savefig()时同时指定高DPI和紧凑裁剪参数,保证高分辨率的同时控制图像尺寸:
plt.savefig(file_name, format="png", dpi=300, bbox_inches='tight', pad_inches=0.05)
dpi=300:提供足够分辨率,避免缩放后模糊bbox_inches='tight':自动裁剪图像周围空白,减少冗余尺寸pad_inches=0.05:保留少量空白防止绘图内容被裁切
同时删除子模块中重复的figsize设置,统一在创建figure时指定:
fig = plt.figure(figsize=(3,3)) # 只保留这一行,删除后面的plt.rcParams设置
2. 插入图片时强制指定适配宽度
主模块插入图片时,直接设置宽度为表格列的3英寸,这样高DPI图像会自动缩放到适配尺寸,同时保留清晰度:
run.add_picture(image_path, width=Inches(3.0))
3. 移除不必要的图像格式转换
image_to_jpg函数对PNG格式的转换完全多余,直接使用子模块返回的原图像路径即可,避免格式转换带来的质量损失。可以直接删除该函数,将循环中的image_path = image_to_jpg(path)改为image_path = path。
4. 优化绘图细节增强清晰度
- 适当调大线条宽度,确保缩放后仍清晰:
patch1 = patches.PathPatch(path1, edgecolor="black", facecolor="None", lw=1, zorder=3) ax.grid(which="both", color="black", linewidth=0.8) - 关闭坐标轴边距,让绘图区域更紧凑:
ax.margins(0) # 在设置xlim/ylim后添加
内容的提问来源于stack exchange,提问作者Mark Barry
相关产品推荐
相关产品推荐

