很多人问我明明已经有现成的程序,为什么还要教大家自己写代码制作分形呢?
那好,既然已经有那么多人成功了,你们可以不用追求成功,就这样颓废下去,可以吗?
(这个例子是不是很怪?其实我认为是一回事)
import numpy as np
import cv2
from tqdm import tqdm
# 我只是想加个进度条
def f(z, c):
# 原始的M集迭代公式(Python支持复数数据类型,可以直接计算)
return z**2 + c
def dwell(z0, c, bailout, step):
# 一般的迭代数公式
z = z0
i = 0
while abs(z) <= bailout and i <= step:
z = f(z, c)
i += 1
return i
def dwell_to_bgr(s):
# 配色方案
# 这里用的函数是用伯恩斯坦基构造的,效果不错
red = lambda s: (1-s)**4
green = lambda s: (1-s)**2*(1+2*s+3*s**2)
blue = lambda s: 2*s**2*(1-s)*(3-s)
color = np.array([blue(s), green(s), red(s)])
color = np.floor(225 * color)
return color
def main():
# 基本参数:迭代步数,初值,逃离界
step = 1024
z0 = 0
bailout = 2
# 构造网格(在原定大小基础上进行9倍超采样)
x_ir = 640
y_ir = 360
g = np.zeros((3*y_ir+1, 3*x_ir+1))
# 作画区域确定
x_range = 2
y_range = x_range * y_ir / x_ir
# 计算各格子的颜色(配色方案另行说明)
for i in tqdm(range(g.shape[0])):
for j in range(g.shape[1]):
# 坐标这么写是保证生成的图符合传统上的直角坐标系
x = x_range * (2 * j / (g.shape[1]-1) - 1)
y = -y_range * (2 * i / (g.shape[0]-1) - 1)
c = x + y * 1j
g[i][j] = dwell(z0, c, bailout, step)
# 对矩阵进行0-1归一化
g = (g - np.min(g)) / (np.max(g) - np.min(g))
# 填入BGR三通道,适应OPENCV的格式
img = np.zeros((g.shape[0], g.shape[1], 3))
for i in tqdm(range(g.shape[0])):
for j in range(g.shape[1]):
for k in range(3):
img[i][j][k] = int(dwell_to_bgr(g[i][j])[k])
# 放缩恢复原定的图像大小(插值算法是我自己选的,有疑问可以问我)
img2 = cv2.resize(img, (x_ir, y_ir), interpolation=cv2.INTER_AREA)
cv2.imwrite("test.png", img2)
main()