如何在Sense Hat 8x8 LED矩阵上显示Matplotlib绘制的图表
8×8像素折线图渲染方案(适配Sense Hat LED矩阵)
空白问题原因
fig, ax = plt.subplots(figsize=(8,8), dpi=1)生成空白图的核心原因有两个:
- Matplotlib对dpi<10的渲染场景存在兼容bug,默认的线宽、裁剪逻辑会失效
- 默认画布会预留占比很高的边距用于放置坐标轴、标签,dpi=1时边距会占满全部8*8像素,实际绘图区尺寸为0,自然没有内容。
实现思路
8×8像素总共只有64个显示点,完全无法容纳常规折线图的坐标轴、标签、图例元素,必须做极简适配:
- 关闭所有非必要的UI元素,让绘图区撑满整个画布
- 将两组时序数据归一化到0~7的像素坐标范围,匹配LED矩阵的索引规则
- 用1像素线宽、高对比纯色绘制折线,关闭抗锯齿避免颜色混杂
- 通过figsize和dpi的换算精确控制输出尺寸,不要直接用dpi=1的参数
可直接运行的代码
import matplotlib.pyplot as plt import numpy as np from PIL import Image # 原始采集数据 time_seq = [0, 1, 2, 3] # 对应Date a/b/c/d四个采样点 data_x = [180, 140.17, 254.71, 248.42] data_y = [16.57, 149, 200, 168] # 数据归一化到0-7的LED像素坐标区间 def normalize_to_pixel(arr): val_min, val_max = np.min(arr), np.max(arr) return np.round((np.array(arr) - val_min) / (val_max - val_min) * 7).astype(int) x_pixel = normalize_to_pixel(data_x) y_pixel = normalize_to_pixel(data_y) # 精确创建8x8像素画布 output_dpi = 100 fig = plt.figure(figsize=(8/output_dpi, 8/output_dpi), dpi=output_dpi) # 让绘图区完全占满画布,不留任何边距 ax = plt.Axes(fig, [0, 0, 1, 1]) ax.set_axis_off() # 关闭所有坐标轴、刻度元素 fig.add_axes(ax) ax.set_xlim(0, 3) ax.set_ylim(0, 7) # 用高对比色绘制两条1像素宽折线 ax.plot(time_seq, x_pixel, color=(1, 0, 0), linewidth=1, antialiased=False) # 红色代表变量x ax.plot(time_seq, y_pixel, color=(0, 1, 0), linewidth=1, antialiased=False) # 绿色代表变量y # 保存为严格8x8尺寸的无压缩PNG plt.savefig( "led_line_chart.png", dpi=output_dpi, pad_inches=0, bbox_inches=None, pil_kwargs={"compress_level": 0} ) plt.close() # 校验输出尺寸 with Image.open("led_line_chart.png") as im: assert im.size == (8, 8), "输出图片尺寸不符合要求"
生成的led_line_chart.png可以直接传给sense.load_image()接口调用,不需要额外转码。
优化提示
- 8×8分辨率极低,如果折线显示不清晰,可以把
plot换成scatter,设置s=1直接用像素点标记采样值,在LED矩阵上辨识度更高 - 选颜色时尽量用R/G/B通道值为0或255的纯色,避免抗锯齿生成的中间色在LED上显示发灰
- 不要尝试添加任何文字标注,最小的字符在8像素宽度下也无法正常识别
内容的提问来源于stack exchange,提问作者AsadMajeed
相关产品推荐
相关产品推荐

