代码之家  ›  专栏  ›  技术社区  ›  petem

使用图像作为为Julia集着色的轨道陷阱

  •  0
  • petem  · 技术社区  · 2 年前

    在网上搜索时,我找不到任何关于如何使用位图(光栅图像)作为轨道陷阱为Julia集或Mandelbrot集着色的示例。 在这里 Inigo Quilez 只用两行解释了他使用的方法,并显示了生成的Julia集。而且 Malin Christersson 显示左上角的图像,在另一页上显示基于的Julia集 Mona Lisa's image ,没有任何评论或解释。 因此,我需要帮助来理解轨道陷阱方法是如何在陷阱是图像时工作的。如何将图像放置在复杂平面中以检测轨道捕获? 当我在复平面中的矩形区域上定义网格时,我只成功地绘制了Julia集,该网格具有与图像相同的分辨率,并迭代网格的点,直到abs(z)>2或者迭代次数超过阈值。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 set colored according to image pixels

    但我想了解上面提到的Julia集是如何基于图像生成的。

    0 回复  |  直到 2 年前
        1
  •  0
  •   petem    2 年前

    最后,我成功地绘制了一个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))
    

    enter image description here