在网上搜索时,我找不到任何有关如何使用位图(光栅图像)作为轨道陷阱来为 Julia 集或 Mandelbrot 集着色的示例。 这里 Inigo Quilez 仅用两行解释了他使用的方法,并显示了生成的 Julia 集。此外,Malin Christersson 显示了左上角的图像,而在另一页上则显示了基于 Mona Lisa's image 的 Julia 设置,没有任何评论或解释。 因此,我需要帮助来理解当陷阱是图像时轨道陷阱方法如何工作。如何将图像放置在复平面上来检测轨道捕获? 当我在复平面中的矩形区域上定义网格网格(与图像具有相同的分辨率)并迭代网格网格的点直到abs(z)> 2或迭代次数超过时,我仅成功绘制了Julia集一个门槛。 Julia 集在起始点位置获取图像像素的颜色,对应于计算轨道的最后一个点。这是我使用 Julia lang 得到的结果:
using Images, Interpolations
f(z::Complex; c= 0.56666-0.5im, n=4) = z^n + c
function iteratef(z, iter)
k=0
while abs(z) <2.0 && k < iter
z=f(z;)
k+=1
end
return z
end
function JuliasetImage(img::Union{Matrix{RGB{T}}, Matrix{Gray{T}}};
rectangle=(remin=-1.5, remax=1.5, immin=-1.5, immax=1.5), iter=255) where T
#define a constant image for fractal, inialized on white
frimg = fill(RGB{N0f8}(1, 1, 1), size(img)...)
nrow, ncol = size(img)
a, b, c, d = rectangle
@assert a<b && c<d || error("wrong boundaries for the rectangle {$a, $b}x[$c, $d]")
for j in axes(img, 2)
for i in axes(img, 1)
z = Complex(a+(b-a)*(j-1)/(ncol-1), d-(d-c)*(i-1)/(nrow-1))
z = iteratef(z, iter)
#get indices in the image of the last z
idxr = floor(Int, 1.5+(nrow-1)*(d-imag(z))/(d-c))
idxc = floor(Int, 1.5+(ncol-1)*(real(z)-a)/(b-a))
if idxr < 1 || idxr > nrow
idxr = mod(idxr, nrow) + 1
end
if idxc < 1 || idxc > ncol
idxc = mod(idxc, ncol) + 1
end
frimg[i,j] = img[idxr, idxc]
end
end
return frimg
end
img =load("ai-boy.jpg")
frimg = JuliasetImage(img;)
fritp = interpolate(frimg, BSpline(Linear()), OnGrid())
但我想了解上面提到的 Julia 集是如何基于图像生成的。
最后,我成功地绘制了一个 Julia 集,其中包含图像作为 轨道陷阱。 检测轨道捕获点的算法工作原理如下:
朱莉娅分形包含在复平面上的矩形区域
[A, B] x [C,D]
中。
在这个矩形上定义了一个分辨率为 Nrow x Ncol
的网格。捕获集是
另一个矩形,[a,b] x [c,d]
,包含在第一个矩形中,由用户通过实验选择。在后一个矩形上定义了与图像分辨率相同分辨率的网格。这样就保证了最后一个网格的点与图像像素之间的一一对应。
该算法的工作原理与已知的算法类似,用于绘制 Julia 集。但这里测试轨道的每个点是否进入陷阱(矩形
[a,b]x[c,d]
)。如果是这种情况,并且 (i,j) 是该矩形上的网格中距捕获点最近的点的索引,则轨道起点位置 (k,l) 处的分形图像,用该像素颜色着色。
该代码以非 Julian 方式编写,以便所有对此类轨道陷阱感兴趣的人都可以访问,即使他们不使用 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))