【问题标题】:How to make a gif of mandelbrot fractal zoom (Python)?如何制作曼德布罗分形缩放 (Python) 的 gif 图像?
【发布时间】:2016-11-28 21:35:15
【问题描述】:

我在 Python 中使用 PIL 模块制作了 Mandelbrot 分形。 现在,我想做一个放大一点的 GIF。我在网上看过其他代码,但不用说,我不明白,因为我使用的模式有点不同(我正在使用类)。

我知道要放大我需要更改比例...但我显然不知道如何实现它。

from PIL import Image
import random


class Fractal:
    """Fractal class."""

    def __init__(self, size, scale, computation):
        """Constructor.

        Arguments:
        size -- the size of the image as a tuple (x, y)
        scale -- the scale of x and y as a list of 2-tuple
                 [(minimum_x, minimum_y), (maximum_x, maximum_y)]
        computation -- the function used for computing pixel values as a function
        """
        self.size = size
        self.scale = scale
        self.computation = computation
        self.img = Image.new("RGB", (size[0], size[1]))

    def compute(self):
        """
        Create the fractal by computing every pixel value.
        """
        for y in range(self.size[1]):
            for x in range(self.size[0]):
                i = self.pixel_value((x, y))
                r = i % 8 * 32
                g = i % 16 * 16
                b = i % 32 * 8
                self.img.putpixel((x, y), (r, g, b))

    def pixel_value(self, pixel):
        """
        Return the number of iterations it took for the pixel to go out of bounds.

        Arguments:
        pixel -- the pixel coordinate (x, y)

        Returns:
        the number of iterations of computation it took to go out of bounds as integer.
        """
        # x = pixel[0] * (self.scale[1][0] - self.scale[0][0]) / self.size[0] + self.scale[0][0]
        # y = pixel[1] * (self.scale[1][1] - self.scale[0][1]) / self.size[1] + self.scale[0][1]
        x = (pixel[0] / self.size[0]) * (self.scale[1][0] - self.scale[0][0]) + self.scale[0][0]
        y = (pixel[1] / self.size[1]) * (self.scale[1][1] - self.scale[0][1]) + self.scale[0][1]

        return self.computation((x, y))

    def save_image(self, filename):
        """
        Save the image to hard drive.

        Arguments:
        filename -- the file name to save the file to as a string.
        """
        self.img.save(filename, "PNG")

if __name__ == "__main__":
    def mandelbrot_computation(pixel):
        """Return integer -> how many iterations it takes for the pixel to escape the mandelbrot set."""
        c = complex(pixel[0], pixel[1])  # Complex number: A + Bi  (A is real number, B is imaginary number).
        z = 0  # We are assuming the starting z value for each square is 0.
        iterations = 0  # Will count how many iterations it takes for a pixel to escape the mandelbrot set.

        for i in range(255):  # The more iterations, the more detailed the mandelbrot set will be.
            if abs(z) >= 2.0:  # Checks, if pixel escapes the mandelbrot set. Same as square root of pix[0] and pix[1].
                break
            z = z**2 + c
            iterations += 1

        return iterations

    mandelbrot = Fractal((1000, 1000), [(-2, -2), (2, 2)], mandelbrot_computation())
    mandelbrot.compute()
    mandelbrot.save_image("mandelbrot.png")

【问题讨论】:

  • 欢迎来到 StackOverflow。请阅读并遵循帮助文档中的发布指南。 How to askMinimal, complete, verifiable example 在这里申请。
  • 您好,谢谢。抱歉,这个问题困扰我很久了,我急于回答这个问题。感谢您的详细解答!
  • 我们随时为您提供帮助。如果您遵守发布指南,您将获得更好的答案,让速读者更容易理解问题。
  • 当你得到一个解决方案时,请记得给有用的东西投票并接受你最喜欢的答案(即使你必须自己写),这样 Stack Overflow 才能正确存档问题。跨度>

标签: python python-imaging-library fractals mandelbrot


【解决方案1】:

正如您在线性代数中所学的那样,这是一个“简单”的线性变换,包括缩放(缩放)和平移(移位)。你还记得一个类似的公式

s(y-k) = r(x-h) + c

翻译是(h,k);每个方向的尺度为(r, s)。

要实现这一点,您需要更改循环增量。要在每个方向上放大 k 倍,您需要缩小坐标范围,同样减少像素位置之间的增量。

这里最重要的是将显示坐标与数学值部分分离:您不再在标记为 (0.2, -0.5) 的位置显示 0.2 - 0.5i 的值;新位置根据您的新帧边界计算。

你的旧代码不太适合这个:

    for y in range(self.size[1]):
        for x in range(self.size[0]):
            i = self.pixel_value((x, y))
            ...
            self.img.putpixel((x, y), (r, g, b))

相反,您需要以下内容:

    # Assume that the limits x_min, x_max, y_min, y_max
    #   are assigned by the zoom operation.
    x_inc = (x_max - x_min) / self.size[0]
    y_inc = (y_max - y_min) / self.size[1]
    for y in range(self.size[1]):
        for x in range(self.size[0]):
            a = x*x_inc + x_min
            b = y*y_inc + y_min
            i = self.pixel_value((a, b))
            ...
            self.img.putpixel((x, y), (r, g, b))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-10
    相关资源
    最近更新 更多