You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在指定像素位置绘制等间距竖线?Matplotlib间距异常问题

解决Matplotlib绘图区域尺寸不符导致竖线间距错误的问题

问题核心

需要在3n像素宽的绘图区域内,绘制n条1像素宽的竖线,要求线与线之间的间距严格为2像素(例如n=7时,绘图区域宽21像素,竖线应位于像素位置2、5、8、11、14、17、20)。当前实现通过设置Figure尺寸来控制像素大小,但实际竖线间距不符合预期,原因是Figure尺寸包含了默认边距等额外空间,真正的绘图区域(Axes)并非目标的3n像素宽。

解决方案

要让Axes(主绘图区域)的像素尺寸完全匹配目标值,需手动让Axes占满整个Figure,消除所有默认边距,并确保坐标系统与像素位置一一对应。

修改后的代码

from pathlib import Path
import matplotlib.pyplot as plt
from ctypes import windll
import numpy as np

plot_path = Path("./plots/testing/")
plot_path.mkdir(parents=True, exist_ok=True)
SYS_DPI = windll.user32.GetDpiForSystem()
print(f"识别到的系统DPI: {SYS_DPI}")

# 示例数据集
example_series = [(1.3, 4.2), (5.3, 8.9), (4.0, 5.5),
                  (6, 7.8), (3.2, 4.5), (5.1, 8.1), (3, 8)]
n = len(example_series)
width_pixel = n * 3
height_pixel = 10

# 计算y轴范围
min_y = min(val[0] for val in example_series)
max_y = max(val[1] for val in example_series)

# 计算竖线的x像素位置(严格对应目标像素点)
x_pos = np.arange(2, width_pixel, step=3)  # 2,5,8,11,14,17,20

# 创建画布并让Axes完全占满画布,消除所有边距
fig = plt.figure(figsize=(width_pixel/SYS_DPI, height_pixel/SYS_DPI), dpi=SYS_DPI)
ax = fig.add_axes([0, 0, 1, 1])  # [左, 底, 宽, 高] 均为0-1范围,占满整个画布

# 配置绘图样式
ax.set_facecolor("white")
ax.set_axis_off()
ax.set_xlim(0, width_pixel)  # x轴范围严格对应画布像素宽度
ax.set_ylim(min_y, max_y)

# 绘制竖线:确保线宽为1像素,端点无扩展
for idx, val in enumerate(example_series):
    ax.plot([x_pos[idx], x_pos[idx]], [val[0], val[1]],
            color="black", linewidth=1, solid_capstyle='butt')

# 保存图像:无额外边距,严格按目标像素尺寸保存
plt.savefig(plot_path/"test_fixed.png",
            bbox_inches=None,
            pad_inches=0,
            transparent=False,
            dpi=SYS_DPI,
            facecolor="white")
plt.close()

关键改动说明

  1. Axes完全占满画布:使用fig.add_axes([0,0,1,1])替代subplots(),让绘图区域完全覆盖整个Figure,彻底消除默认的边距和布局间隙,保证Axes的像素尺寸与Figure完全一致。
  2. 严格的坐标映射:x轴范围设置为(0, width_pixel),此时x坐标值直接对应图像的像素位置(例如x=2就是图像的第3个像素点,索引从0开始)。
  3. 精确的线条控制:添加solid_capstyle='butt'参数,避免Matplotlib默认的线条端点扩展(默认是圆形端点,会额外占1像素宽度),确保竖线正好是1像素宽。
  4. 简化计算:直接用np.arange(2, width_pixel, step=3)生成目标x位置,逻辑更清晰。

验证效果

修改后生成的图像宽度严格为21像素(n=7时),用图像查看工具放大后可看到竖线准确位于像素位置2、5、8等,线与线之间的间距正好是2像素,完全符合需求。

内容的提问来源于stack exchange,提问作者Lars

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:17:52