树莓派Zero 2上MLX90640+PiCamera+Pygame程序卡顿优化求助
树莓派Zero 2 Ecto护目镜程序优化方案
1. 相机模块:用内存流替代磁盘IO(核心优化)
原程序每次捕获相机画面都写入本地文件再读取,磁盘IO是最大性能瓶颈。改用BytesIO在内存中直接处理图像数据,完全跳过磁盘操作:
from io import BytesIO # 初始化相机部分修改 camera = PiCamera() camera.resolution = (214, 160) camera.framerate = 30 # 可尝试提升至30帧 time.sleep(0.5) # 循环内的相机捕获代码替换为: stream = BytesIO() camera.capture(stream, format='jpeg', resize=(214,160)) stream.seek(0) image = pygame.image.load(stream).convert() screen.blit(image, (400,0)) stream.close()
2. 提升MLX90640热感传感器刷新率
原代码将刷新率设为2Hz,直接把整体帧率锁死在2帧/秒。树莓派Zero 2的I2C总线可支持更高速率,同时拉满传感器的I2C频率:
# 初始化I2C和传感器部分修改 i2c = busio.I2C(board.SCL, board.SDA, frequency=1000000) # 提升至1MHz(传感器支持最大值) mlx = adafruit_mlx90640.MLX90640(i2c) mlx.refresh_rate = adafruit_mlx90640.RefreshRate.REFRESH_8_HZ # 改为8Hz,稳定后可尝试16Hz
若设置16Hz出现数据错误,降回8Hz即可,传感器个体存在差异。
3. 优化Pygame渲染效率
原程序逐个矩形更新屏幕,频繁触发屏幕刷新开销极大。改为先在离屏Surface绘制热图,再一次性贴到主屏幕,最后统一刷新:
# 初始化时创建热图专用Surface heatmap_surface = pygame.Surface((214, 160)) # 匹配热图显示区域尺寸 # 循环内的热图绘制部分修改: heatmap_surface.fill(black) # 先清空热图Surface for row in range(24): row_pos = int((row * 10) * 0.67) for column in range(32): temp = frame[row * 32 + column] col_pos = 214 - (int((column * 10) * 0.67)) # 通过预定义映射表获取颜色(见下一个优化) color = temp_color_map.get(temp_range(temp), black) pygame.draw.rect(heatmap_surface, color, pygame.Rect(col_pos, row_pos, 7, 7)) # 一次性将热图贴到主屏幕 screen.blit(heatmap_surface, (0, 0)) # 统一刷新整个屏幕 pygame.display.flip()
4. 预创建温度-颜色映射表,减少分支判断
原程序每次循环执行8个elif判断,改用提前计算的映射表直接查表获取颜色,减少计算开销:
# 在初始化部分添加温度范围判断函数和映射表 def temp_range(temp): if temp < 27: return 0 elif temp < 29: return 1 elif temp < 31: return 2 elif temp < 33: return 3 elif temp < 35: return 4 elif temp < 37: return 5 elif temp < 39: return 6 else: return 7 temp_color_map = { 0: white, 1: light_grey, 2: very_light_blue, 3: blue, 4: purple, 5: pink, 6: red, 7: dark_red }
5. 调整Pygame初始化顺序(修复潜在问题)
原程序先创建屏幕再初始化Pygame,正确顺序应为先初始化再创建窗口:
# 初始化Pygame部分修改 pygame.init() # 先初始化Pygame size = [SCREEN_WIDTH, SCREEN_HEIGHT] screen = pygame.display.set_mode(size) # 再创建屏幕 screen.fill(black) pygame.mouse.set_visible(False)
额外:相机预览窗口的硬件加速方案
若内存流方案仍不够快,可尝试用相机预览窗口指定位置,让Pygame仅渲染热图和UI:
# 初始化相机时开启预览,指定窗口位置 camera.start_preview(fullscreen=False, window=(400, 0, 214, 160), layer=0) # 设置Pygame窗口在最上层 screen = pygame.display.set_mode(size, pygame.NOFRAME | pygame.TOPMOST)
此方式下Pygame无需处理相机画面,性能更高,需确保预览窗口与热图区域不重叠。
内容的提问来源于stack exchange,提问作者Billy O Sullivan
相关产品推荐
相关产品推荐

