注册

Python 3 使用Pillow生成漂亮的分形树图片

Python 3 使用Pillow生成漂亮的分形树图片

分形树是一种美丽而复杂的几何图形,常用于数学、计算机图形和平面设计等领域。在本文中,我们将介绍如何使用Python 3和Pillow库来生成漂亮的分形树图片。

步骤1:安装Pillow库

Pillow是Python开发人员常用的图像处理库之一。可以使用pip命令轻松安装Pillow库:

pip install pillow

步骤2:编写代码创建分形树图像

在开始我们的Python代码编写之前,让我们先来看一下分形树的基本原理:

  1. 从单个点开始,在固定的角度内绘制分支线;
  2. 对于分支线的末端点,递归地重复步骤1,生成更小的分支线,直到满足终止条件。

根据该原理,我们可以编写以下代码来生成分形树图像:

from PIL import Image, ImageDraw
import math

# 定义一个函数来绘制分支线
def draw_branch(draw, start, length, angle, width, color):
    end_x = start[0] + length * math.sin(math.radians(angle))  # 计算结束点的x坐标
    end_y = start[1] - length * math.cos(math.radians(angle))  # 计算结束点的y坐标
    end = (end_x, end_y)
    draw.line([start, end], fill=color, width=width)  # 绘制分支线
    return end  # 返回结束点

# 定义一个函数来绘制分形树
def draw_tree(size, depth, branch_length, angle, width, color):
    image = Image.new('RGB', size, (255, 255, 255))  # 创建图像
    draw = ImageDraw.Draw(image)  # 创建绘制对象
    start = (size[0] // 2, size[1] - 1)  # 定义起点
    end = draw_branch(draw, start, branch_length, -90, width, color)  # 生成分支线
    draw_tree_recursive(draw, end, branch_length, angle, depth-1, width, color)  # 递归绘制分支线
    return image

# 递归绘制分支线
def draw_tree_recursive(draw, start, length, angle, depth, width, color):
    if depth == 0:
        return
    for i in range(2):
        sub_angle = angle + (i * 2 - 1) * 45  # 计算分支线的角度
        sub_length = length * 0.75  # 计算分支线的长度
        sub_width = max(1, width - 2)  # 计算分支线的宽度
        sub_color = tuple(max(0, min(255, int(c * 0.8))) for c in color)  # 计算分支线的颜色
        end = draw_branch(draw, start, sub_length, sub_angle, sub_width, sub_color)  # 生成分支线
        draw_tree_recursive(draw, end, sub_length, angle, depth-1, sub_width, sub_color)  # 递归绘制分支线

上述代码中,我们通过draw_branch函数来绘制分支线,并通过draw_tree_recursive函数递归地绘制分支线。然后在draw_tree函数中创建图像对象,绘制起始分支线,并递归地调用draw_tree_recursive函数来生成更多的分支线。

步骤3:运行代码生成分形树图像

调用draw_tree函数来绘制一个漂亮的分形树图像:

size = (800, 800)  # 定义图像尺寸
depth = 10  # 定义递归深度
branch_length = 250  # 定义分支线长度
angle = 0  # 定义分支线角度
width = 20  # 定义分支线宽度
color = (0, 128, 0)  # 定义分支线颜色
image = draw_tree(size, depth, branch_length, angle, width, color)  # 生成分形树图像
image.save('fractal_tree.png')  # 保存图像

运行上述代码后,我们将在代码所在的目录中生成一个名为“fractal_tree.png”的文件,其中包含了我们所创建的分形树图像。

示例1:生成多种分形树图像

如果我们想要生成不同风格的分形树图像,可以通过调整参数来实现。例如以下代码将生成三种分形树图像:

size = (400, 400)
depth = 7
branch_length = 150
angle = 0
width = 20
color = (70, 40, 20)
image1 = draw_tree(size, depth, branch_length, angle, width, color)
color = (0, 0, 255)
image2 = draw_tree(size, depth, branch_length, angle, width, color)
angle = 30
color = (255, 0, 0)
image3 = draw_tree(size, depth, branch_length, angle, width, color)

image1.save('fractal_tree1.png')
image2.save('fractal_tree2.png')
image3.save('fractal_tree3.png')

示例2:优化分形树生成效率

在处理大型分形树图像时,代码可能会变得非常缓慢。我们可以通过将函数的参数设置为全局变量,以及使用L-System算法来优化代码。以下是优化后的示例代码:

from PIL import Image, ImageDraw
import math

# 全局变量
depth = 10
branch_length = 100
branch_angle = 30
width = 20
color_start = (255, 255, 255)
color_end = (0, 0, 0)
background_color = (255, 255, 255)

# 生成L-System序列
def generate_string(axiom, rules, iterations):
    sequence = axiom
    for i in range(iterations):
        new_sequence = ''
        for c in sequence:
            if c in rules:
                new_sequence += rules[c]
            else:
                new_sequence += c
        sequence = new_sequence
    return sequence

# 根据L-System序列生成分形树图像
def draw_fractal_tree(size, sequence):
    image = Image.new('RGB', size, background_color)
    draw = ImageDraw.Draw(image)
    stack = []
    position = (size[0] // 2, size[1] - 1)
    angle = 90
    for c in sequence:
        if c == '[':
            stack.append((position, angle))
        elif c == ']':
            position, angle = stack.pop()
        elif c == 'F':
            color = tuple([int(color_start[i] * (1 - t) + color_end[i] * t) for i in range(3)])
            draw.line([position, (position[0] + int(branch_length * math.cos(math.radians(angle))), position[1] - int(branch_length * math.sin(math.radians(angle))))], width=width, fill=color)
            position = (position[0] + int(branch_length * math.cos(math.radians(angle))), position[1] - int(branch_length * math.sin(math.radians(angle))))
        elif c == '+':
            angle += branch_angle
        elif c == '-':
            angle -= branch_angle
    return image

axiom = 'F'
rules = {'F': 'F[+F][-F]'}
iterations = 5
sequence = generate_string(axiom, rules, iterations)
image = draw_fractal_tree((800, 800), sequence)
image.save('fractal_tree.png')

上述代码中,我们使用了L-System算法来生成分形树图像。该算法可以快速生成复杂的分形树,使代码的运行速度更快。我们还可以通过调整分形树的参数来生成不同风格的图像。