Python 3 使用Pillow生成漂亮的分形树图片
分形树是一种美丽而复杂的几何图形,常用于数学、计算机图形和平面设计等领域。在本文中,我们将介绍如何使用Python 3和Pillow库来生成漂亮的分形树图片。
步骤1:安装Pillow库
Pillow是Python开发人员常用的图像处理库之一。可以使用pip命令轻松安装Pillow库:
pip install pillow
步骤2:编写代码创建分形树图像
在开始我们的Python代码编写之前,让我们先来看一下分形树的基本原理:
- 从单个点开始,在固定的角度内绘制分支线;
- 对于分支线的末端点,递归地重复步骤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算法来生成分形树图像。该算法可以快速生成复杂的分形树,使代码的运行速度更快。我们还可以通过调整分形树的参数来生成不同风格的图像。