最后,我成功地绘制了一个Julia集,其中有一个图像
orbit trap
。
用于检测轨道的捕获点的算法工作如下:
Julia分形被包括在矩形区域中,
[A, B] x [C,D]
,从复杂的平面来看。
在这个矩形上定义了一个分辨率为的网格
Nrow x Ncol
。陷阱集是
另一个矩形,
[a,b] x [c,d]
,包含在第一个中,由用户通过实验选择。在后一个矩形上,定义了与图像分辨率相同分辨率的网格。因此确保了最后一个网格的点与图像像素之间的一一对应。
该算法的工作原理与已知算法类似,用于绘制Julia集。但这里要测试轨道上的每个点是否进入陷阱(矩形
[a,b]x[c,d]
)。如果是这种情况,并且(i,j)是在该矩形上的网格中离捕获点最近的点的索引,则轨道起点的位置(k,l)处的分形图像用该像素颜色着色。
该代码是以非朱利安的方式编写的,以便所有对这种类型的轨道陷阱感兴趣的人都可以访问,即使他们不使用Julia lang。
此代码适用于去除背景的图像(即带有背景像素的png图像
彩色RGBA(0,0,0,0))以及具有其原始背景的jpg图像。
如果背景被移除,那么当轨道实际上被捕获时,但轨道的点在陷阱中
[a,b] x[c,d]
对应于透明像素(即,它不是图像所表示形状上的像素),它被视为未映射(请参见函数
istrapped
)。
以下是一个透明背景图像的示例,通过
fotor
。
using Images, Interpolations
function get_index(z::Complex, nrow, ncol; imgrectangle=(a=-0.25, b=0.7, c=-0.25, d=0.7))
a, b, c, d = imgrectangle
idxrow = floor(Int, 1.5+ (nrow-1)*(d-imag(z))/(d-c)) #1.5 =1.0+0.5; 1
idxcol = floor(Int, 1.5+ (ncol-1)*(real(z)-a)/(b-a))
return idxrow, idxcol
end
function istrapped(img::Matrix{T}, i::Int, j::Int) where T
1 <= i <=size(img, 1) && 1 <= j <= size(img, 2) && (img[i, j] != RGBA(0,0,0,0))
end
f(z::Complex; c=-0.8+0.156im)=z^2+c
function iteratef(z::Complex, img::Matrix{T}; maxiter=512) where T
n=0
i, j = get_index(z, size(img)...;)
while (n < maxiter && abs(z) < 2) && (n < 2 || !istrapped(img, i, j ))
z = f(z)
n += 1
i, j = get_index(z, size(img)...;)
if istrapped(img, i, j)
return img[i, j]
end
end
end
function Juliafractal(img::Matrix{T};
fractrectangle=(xmin=-1.55, xmax=1.55, ymin=-1.4, ymax=1.4),
Nrow=1000, Ncol=1000, maxiter=1024,
bgcolor=RGB{N0f8}(1.0,1.0, 1.0)) where T
A, B, C, D = fractrectangle
frimg = fill(bgcolor, 1:Nrow, 1:Ncol)
for l in axes(frimg, 2)
for k in axes(frimg, 1)
z = Complex(A+(B-A)*(l-1)/(Ncol-1), D-(D-C)*(k-1)/(Nrow-1))
vr = iteratef(z, img; maxiter=maxiter)
if vr != nothing
frimg[k, l] = vr
end
end
end
return interpolate(frimg, BSpline(Linear()), OnGrid())
end
img = load("imgs/ai-younglady.png")
fritp = Juliafractal(img; bgcolor=RGB{N0f8}(1,0.953,0.91))