Mandelbrot集Julia集分形的MATLAB实现(分形艺术)

本文首发于 matlab爱好者 微信公众号,欢迎关注。

惯例声明:本人没有相关的工程应用经验,只是纯粹对相关算法感兴趣才写此博客。所以如果有错误,欢迎在评论区指正,不胜感激。本文主要关注于算法的实现,对于实际应用等问题本人没有任何经验,所以也不再涉及。

本文为学习非线性动力学时,搜索资料时发现的一个小例子,感觉很有趣,试着自己尝试一下。相关实现案例非常多,所以这篇文章就简单水一下了。
其余两篇水文链接也一并奉上:
利用matlab进行混沌摆仿真(双摆、三摆、多摆演示)https://blog.csdn.net/weixin_42943114/article/details/121891553
利用matlab实现复数域空间牛顿迭代法的分形图案展示(newton法)https://blog.csdn.net/weixin_42943114/article/details/121905957

参考目录:
[1]GPU Code Generation: The Mandelbrot Set(https://www.mathworks.com/help/gpucoder/gs/gpu-code-generation-the-mandelbrot-set.html)
[2]神奇的分形艺术(四):Julia集和Mandelbrot集(http://www.matrix67.com/blog/archives/292)

1 简单Julia集的实现

对于复平面上某个点z,经过函数z=f(z)的不断迭代,会有两种结局:收敛或发散。

当我们取函数f(z)=z^2+C,对整个平面每个点,都经过上述多次迭代后,记录其收敛或发散的情况,并标记在图上,最终形成的图案就是Julia集。C不一定是实数,也可以是复数。

这里我用matlab简单写了一个当C=0.279的图像:
请添加图片描述
这里的颜色条我借鉴的是Matrix67博客里引用的一个图片的颜色条,自己搭配的,见神奇的分形艺术(四):Julia集和Mandelbrot集

程序算法参见matlab官方的一个介绍gpu加速的文章中GPU Code Generation: The Mandelbrot Set提到的一种算法。

程序如下:

%?res是目标分辨率,iter是循环次数,(xc,yc)是图像中心,xoom是放大倍数
%res分辨率越多,在一张图上能够计算的点越多。iter越多,细节越丰富。
clear;
clc
close all
res=2500;iter=200;xc=0;yc=0;xoom=1.7;

x0=xc-2/xoom;x1=xc+2/xoom;
y0=yc-2/xoom;y1=yc+2/xoom;
x=linspace(x0,x1,res);
y=linspace(y0,y1,res);
[xx,yy]=meshgrid(x,y);
z=xx+yy*1i;

C=0.279;
tic

%matlab官方推荐的方法
N = ones(res,res);
for k = 0:iter
    z = z.*z + C;
    inside = abs( z )<=2;
    N = N + inside;
end
toc

%这里代码参见博客:
%利用matlab构建自己的colormap(色彩搭配)
%https://blog.csdn.net/weixin_42943114/article/details/81811556
%蓝色-橘色颜色条
mycolorpoint=[
    [235 255 255];...
    [243 253 242];...
    [248 247 193];...
    [255 211 49];...
    [236 133 0];...
    [134 36 21];...
    [75 6 34];...
    [15 5 64];...
    [3 8 96];...
    [7 35 154];...
    [24 84 205];...
    [87 169 229];...
    [165 223 247];...
    [235 255 255];...
    ];
mycolorposition=[1 3 7 14 27 45 57 66 74 86 96 109 119 128];
mycolormap_r=interp1(mycolorposition,mycolorpoint(:,1),1:128,'pchip','extrap');
mycolormap_g=interp1(mycolorposition,mycolorpoint(:,2),1:128,'pchip','extrap');
mycolormap_b=interp1(mycolorposition,mycolorpoint(:,3),1:128,'pchip','extrap');
mycolor=[mycolormap_r',mycolormap_g',mycolormap_b']/255;

figure()
pcolor(x,y,log(N));
mycolor=interp1(linspace(1,256,128),mycolor,1:256);
colormap([mycolor;mycolor;mycolor])%重复颜色条
shading interp

1.1 如何实现更光滑的展示效果?

我在网上查阅资料,发现大部分资料就到此为止了。虽然输出的图片的确像回事,但是它是一个台阶一个台阶的,距离想象中的光滑过度变化有很大差别。
请添加图片描述
这个台阶产生的原因是算法本身,算法用整数去衡量该点发散的快与慢。因此只要算法不更改,整数导致的台阶问题无法消除。所以只能从其他角度去消除这个台阶。

因此我这一小节也提出了一个小改进算法,能够二次加工分形图,去除台阶。之前用过各种滤波法,但是效果不好,因为分形图具有特别多的细节,直接滤波会导致分形图的细节全部丢失。所以后来采用了提取等值线边缘提取的思路,来保持图像形状,再进行光滑插值的方法。效果如下:
请添加图片描述

可以看到基本保留了大部分分形细节,而且过渡也比较光滑。边缘部分受插值信息限制,可能过渡受边框影响,有些不自然。当然缺点也比较明显,就是我这个轮廓选择原则是逐个像素4个边来决定的,所以计算量非常大。因为之前试过M = contour()函数提取等高线,效果似乎差不多,喜欢折腾的可以在这里再研究一下,看看像Ultra Fractal 之类的分形软件是怎么实现这种效果的。

完整代码如下:

%?res是目标分辨率,iter是循环次数,(xc,yc)是图像中心,xoom是放大倍数
%res分辨率越多,在一张图上能够计算的点越多。iter越多,细节越丰富。
clear;
clc
close all
res=2500;iter=200;xc=0;yc=0;xoom=1.7;

x0=xc-2/xoom;x1=xc+2/xoom;
y0=yc-2/xoom;y1=yc+2/xoom;
x=linspace(x0,x1,res);
y=linspace(y0,y1,res);
[xx,yy]=meshgrid(x,y);
z=xx+yy*1i;
C=0.279;
tic

%matlab官方推荐
N = ones(res,res);
for k = 0:iter
    z = z.*z + C;
    inside = abs( z )<=2;
    N = N + inside;
end
toc

mycolorpoint=[[235 255 255];[243 253 242];[248 247 193];[255 211 49];...
    [236 133 0];[134 
  • 15
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值