当前位置: 首页 > 知识库问答 >
问题:

如何更快地渲染Mandelbrot集?

堵飞鸿
2023-03-14

我目前正在用PhotoImage和tkinter逐像素绘制Mandelbrot集。我基本上是直接使用算法,没有任何修改。有没有方法可以加快计算速度?也许快速填充大面积的颜色,或者预先计算常数?

守则的一部分:

ITERATIONS = 50
WIDTH, HEIGHT = 600, 600
CENTER = (-.5, 0)
DIAMETER = 2.5

def mandel(c):
    z = 0
    for i in range(ITERATIONS):
        z = z**2 + c
        if abs(z) > 2:
            return i     
    return ITERATIONS

root = Tk()
canvas = Canvas(root, width=WIDTH,height=HEIGHT)
canvas.pack()
img = PhotoImage(width=WIDTH, height=HEIGHT)
canvas.create_image((WIDTH/2, HEIGHT/2), image=img, state="normal")


real = CENTER[0] - 0.5 * DIAMETER
imag = CENTER[1] - 0.5 * DIAMETER

def color(i):
    colors = ("#0000AA", "#88DDFF", "#FF8800", "#000000")
    if i == ITERATIONS:
        return colors[-1]
    else:
        choice = (i//2) % len(colors)
    return colors[choice]

for x in range(WIDTH):
    for y in range(HEIGHT):
        i = mandel(complex(real, imag))

        img.put(color(i), (x, HEIGHT-y))

        imag += DIAMETER / HEIGHT
    imag = CENTER[1] - 0.5 * DIAMETER
    real += DIAMETER / WIDTH

mainloop()

共有3个答案

范鸿畅
2023-03-14

python对于数字代码来说没有那么快。最简单的加速方法是使用PyPy。如果速度不够快,请使用numpy对算法进行矢量化。如果还不够快,请使用Cython,或者考虑在C.重写。

龚振濂
2023-03-14

这是我的代码,它在8-9秒内画了一个640x480的曼德尔布罗。

它每像素最多做256次迭代,使用彩色地图列表,只放一次到PhotoImage,并且不依赖对称,所以它可以显示集合的任何缩放区域。

遗憾的是,Tkinter不允许访问PhotoImage的光栅信息作为缓冲区,并且需要笨拙的字符串。

from tkinter import Tk, Canvas, PhotoImage,NW,mainloop 
from time import clock

def mandel(kx,ky):
  """ calculates the pixel color of the point of mandelbrot plane
      passed in the arguments """

  global clr
  maxIt = 256
  c = complex(kx, ky)
  z = complex(0.0, 0.0)
  for i in range(maxIt):
      z = z * z + c
      if abs(z) >= 2.0:
         return (255-clr[i],0,0)
  return(0,0,0)

def prepare_mdb(xa,xb,ya,yb):
    """ pre-calculates coordinates of the mandelbrot plane required for each
      pixel in the screen"""

    global x,y,xm,ym
    xm.clear
    ym.clear
    xm=[xa + (xb - xa) * kx /x  for kx in range(x)]
    ym=[ya + (yb - ya) * ky /y  for ky in range(y)]


x=640
y=480
#corners of  the mandelbrot plan to display  
xa = -2.0; xb = 1.0
ya = -1.5; yb = 1.5
#precalculated color table
clr=[ int(255*((i/255)**12)) for i in range(255,-1,-1)]
xm=[]
ym=[]
prepare_mdb(xa,xb,ya,yb)

#Tk 
window = Tk()
canvas = Canvas(window, width = x, height = y, bg = "#000000")
t1=clock()
img = PhotoImage(width = x, height = y)
canvas.create_image((0, 0), image = img, state = "normal", anchor = NW)
pixels=" ".join(("{"+" ".join(('#%02x%02x%02x' % mandel(i,j) for i in xm))+"}" for j in ym))
img.put(pixels)
canvas.pack()
print(clock()-t1)
mainloop()
南门鸿振
2023-03-14

一次设置一个像素可能是减速的主要原因。计算机不是调用每个像素的放,而是调用整行像素或整个像素矩阵,然后在循环结束时调用放一次。

除其他地方外,您可以在此处找到一个示例:https://web.archive.org/web/20170512214049/http://tkinter.unpythonic.net:80/wiki/PhotoImage#Fill_Many_Pixels_at_Once

 类似资料:
  • 问题内容: 我目前正在使用PhotoImage和tkinter逐像素绘制Mandelbrot集。我基本上是直接使用没有修改的算法。有没有使计算更快的方法?也许快速填充大面积的颜色,或者预先计算常数? 部分代码: 问题答案: 一次设置一个像素可能是减速的主要来源。而不是为每个像素调用put,而是计算整个像素行或整个像素矩阵,然后在循环结束时调用一次。 您可以在其他位置找到示例:https : //w

  • 我在Javascript上制作了一个程序,创建了mandelbrot分形,并在html画布上绘制了它。我的渲染方法是每行迭代,从0到500像素,然后简单地循环创建500行500像素。 我的问题是,当我渲染它的时候,(用更多的放大率刷新页面),它需要很多时间。300倍的放大率大约在30秒内工作,但5000倍需要一个多小时。请帮忙。我想有非常高的放大率和图像加载迅速。 我通过一个下载的文件运行我的程序

  • 加载页面时 <div id="root"></div> 这样的占位空节点在 js bundle 未生效前表现为白屏。网速差 js bundle 加载慢时,白屏时间增长会造成不好的体验。 节点快照可将 HTML 容器填充为用户上一次访问时对应的内容,极速展示页面内容,提升首屏加载速度。 第一步:在工程配置 build.json 中的 build-plugin-rax-pwa 添加 snapshot

  • 我无法呈现一个selectOneMenu,但只能禁用该项目 例如,这是可行的: 而这个不是: 有什么建议吗 谢谢

  • 我有一个带有对象数组的组件,其中我正在根据字符串进行过滤。问题是当我尝试将此过滤器的返回设置为本地状态时,它会抛出错误,我不太理解原因。 所以,因为我希望这个数组处于我的状态,所以我决定这样做: 插入这一行后发生的事情是这样的: 它开始多次渲染。我假设,每次状态改变时,它都会重新渲染组件(如果我错了,请纠正我)。不过,我不知道它为什么要多次这样做。 因此,我想过使用 useEffect 来实现此处

  • 问题内容: 我想优化此代码: 事情是,我不知道如何读取bufferedReader的内容并将其复制到String中,比我上面的速度更快。我需要花费尽可能少的时间。谢谢 问题答案: 在循环中使用字符串连接是 在 经典的性能杀手(因为字符串是不可变的,整个越来越大的字符串被复制为每个连接)。改为这样做: