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

Python中迭代像素动态绘制的高效新手方案咨询

问题描述

我正在开发一款Python简易程序,供学生探索形如 $x(n+1) = (1+b)F(x_n) – b x(n-1)$ 的递推关系,其结果为基于Gumowski和Mira研究的“尘埃型”分形,函数每次迭代生成一个(x,y)点。

迭代生成代码相对简单,但作为Python新手,我寻求最高效的方法,让学生能逐次、逐像素地在屏幕上观察迭代(轨道)的演化过程。

我已尝试Pillow和matplotlib,但二者均无法满足动态展示需求。以下是使用matplotlib实现静态结果的代码示例(不含额外UI细节):

#mira exmple using matplotlib to visualise static result
import matplotlib.pyplot as plt

#initialise base parameters
a = 0.5
b = 0.998

#set starting point
x = 0
y = 12.1

#set level of iterations
p = 10000

#initialise arrays for holding x , y results
x_plot = [0]
y_plot = [12.1]

#define f(x) and generate initial value
f = (a*x + ((2-2*a)*x**2))/(1+x**2)

for n in range(1000,p):
    z = x
    x = b*y + f
    f = (a*x + ((2-2*a)*x**2))/(1+x**2)
    y = f - z

    x_plot.append(x)
    y_plot.append(y)

plt.style.use('classic')
fig, ax = plt.subplots()
ax.scatter(x_plot, y_plot, s = 1)
plt.show()

朋友建议使用Pygame,但提到其大量像素更新时速度较慢。在我研究Pygame gfx之前,是否有更适合新手的优质方案?


推荐方案

1. Matplotlib动态更新(极简改造)

如果你已经熟悉Matplotlib,完全可以用它实现动态逐点绘制,不需要学习新库,代码改动极小:

import matplotlib.pyplot as plt

# 初始化参数
a = 0.5
b = 0.998
x = 0
y = 12.1
p = 10000

# 开启交互模式
plt.ion()
fig, ax = plt.subplots(figsize=(8,8))
ax.set_xlim(-15, 15)  # 根据分形范围固定坐标轴
ax.set_ylim(-15, 15)
ax.set_title("Gumowski-Mira 分形演化")

f = (a*x + ((2-2*a)*x**2))/(1+x**2)

# 跳过前1000次迭代(避免初始点干扰)
for _ in range(1000):
    z = x
    x = b*y + f
    f = (a*x + ((2-2*a)*x**2))/(1+x**2)
    y = f - z

# 开始动态绘制
for _ in range(p - 1000):
    z = x
    x = b*y + f
    f = (a*x + ((2-2*a)*x**2))/(1+x**2)
    y = f - z
    # 绘制单个点
    ax.scatter(x, y, s=1, color='black')
    # 每次迭代更新画布
    plt.draw()
    plt.pause(0.001)  # 控制绘制速度,可调整

plt.ioff()
plt.show()

这个方案足够满足学生演示需求,缺点是超大量迭代时速度会略慢,但日常使用完全没问题。

2. PyQtGraph(高效易上手)

PyQtGraph是专门针对科学计算的快速绘图库,动态更新速度远快于Matplotlib,API也很直观:
先安装库:pip install pyqtgraph

import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui

# 初始化参数
a = 0.5
b = 0.998
x = 0
y = 12.1
p = 10000

# 创建窗口和绘图区域
app = QtGui.QApplication([])
win = pg.GraphicsLayoutWidget(show=True, title="Gumowski-Mira 分形")
plot = win.addPlot(title="迭代轨道演化")
plot.setXRange(-15, 15)
plot.setYRange(-15, 15)
plot.setAspectLocked(True)  # 保持坐标轴比例

# 创建点集合对象
points = pg.ScatterPlotItem(size=1, pen=None, brush='k')
plot.addItem(points)

f = (a*x + ((2-2*a)*x**2))/(1+x**2)

# 跳过前1000次迭代
for _ in range(1000):
    z = x
    x = b*y + f
    f = (a*x + ((2-2*a)*x**2))/(1+x**2)
    y = f - z

# 动态更新函数
def update():
    global x, y, f
    z = x
    x = b*y + f
    f = (a*x + ((2-2*a)*x**2))/(1+x**2)
    y = f - z
    # 添加新点到集合
    points.addPoints([x], [y])

# 设置定时器,每隔1ms更新一次
timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(1)

# 启动事件循环
if __name__ == '__main__':
    QtGui.QApplication.instance().exec_()

它支持实时缩放、平移,适合学生探索分形细节,速度表现也更优。

3. Pygame优化方案(极致速度)

如果想用Pygame,只需通过批量更新屏幕就能解决速度问题,不用纠结gfx模块:
先安装库:pip install pygame

import pygame
import sys

# 初始化Pygame
pygame.init()
WIDTH, HEIGHT = 800, 800
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Gumowski-Mira 分形")
# 创建离线Surface存储像素,减少屏幕更新次数
pixel_surface = pygame.Surface((WIDTH, HEIGHT))
pixel_surface.fill((255,255,255))

# 参数初始化
a = 0.5
b = 0.998
x = 0
y = 12.1
p = 10000
# 坐标映射:分形数值转屏幕像素
scale = 25
offset_x = WIDTH // 2
offset_y = HEIGHT // 2

f = (a*x + ((2-2*a)*x**2))/(1+x**2)

# 跳过前1000次迭代
for _ in range(1000):
    z = x
    x = b*y + f
    f = (a*x + ((2-2*a)*x**2))/(1+x**2)
    y = f - z

running = True
count = 0
while running and count < p - 1000:
    # 处理退出事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    
    # 迭代计算
    z = x
    x = b*y + f
    f = (a*x + ((2-2*a)*x**2))/(1+x**2)
    y = f - z
    
    # 转换为屏幕坐标
    px = int(x * scale + offset_x)
    py = int(-y * scale + offset_y)  # 反转y轴匹配数学坐标系
    if 0 <= px < WIDTH and 0 <= py < HEIGHT:
        pixel_surface.set_at((px, py), (0,0,0))
    
    # 每100次迭代更新一次屏幕,提升速度
    if count % 100 == 0:
        screen.blit(pixel_surface, (0,0))
        pygame.display.flip()
    
    count += 1

# 最后更新完整画面
screen.blit(pixel_surface, (0,0))
pygame.display.flip()
pygame.quit()
sys.exit()

通过批量刷新屏幕,Pygame的速度完全能满足实时演示需求,还能直观展示像素级的演化过程。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 17:17:53