【问题标题】:Coloring the Barnsley Fern fractal着色巴恩斯利蕨分形
【发布时间】:2014-08-01 02:51:17
【问题描述】:

在渲染巴恩斯利蕨类分形时,我想出了单色图像或最多四色图像,即左下角、右下角、底部茎和叶子的其余部分。例如,这是我得到的图像:

然而我想要的是给叶子带来阴影,让茎更粗,颜色不同,比如:

我对可以使用的算法进行了一些挖掘,然后我在Draves's paper about fractal flames 中读到,在迭代函数系统的迭代过程中,如果我们使用单一颜色,可能会多次渲染单个点这会导致信息丢失,因此我们需要创建一个点被渲染多少次的直方图,然后使用带有颜色阴影对数密度着色的直方图执行渲染通道。

我已经达到了我有直方图但不知道如何使用它来渲染阴影或使用对数密度渲染技术的地步。 有人可以帮助我进行此类渲染,或者至少将我引导到可以通过实际示例阅读更多相关信息的来源

这是我尝试过的:

AffineTransformation f1 = new AffineTransformation(0,0,0,0.25,0,-0.4);
AffineTransformation f2 = new AffineTransformation(0.95,0.005,-0.005,0.93,-0.002,0.5);
AffineTransformation f3 = new AffineTransformation(0.035,-0.2,0.16,0.04,-0.09,0.02);
AffineTransformation f4 = new AffineTransformation(-0.04,0.2,0.16,0.04,0.083,0.12);
int N=Width*Height;
int pixelhistogram[] = new int[N];
for(int i=0;i< N*25;i++)
{
    Point newpoint = new Point();
    double probability = Math.random();
    if(probability < 0.01)
    {
        newpoint = f1.transform(point);
    }
    else if(probability < 0.94)
    {
        newpoint = f2.transform(point);
    }
    else if(probability < 0.97)
    {
        newpoint = f3.transform(point);
    }
    else
    {
        newpoint = f4.transform(point);
    }
    point = newpoint;
    // Translating the point to pixel in the image and 
    // incrementing that index in the pixelHistogram array by 1
            // W and H are the Width and Height
    int X=((int)(point.getX()*W/3)+W/2)/2 + W/4-1;
    int Y=H-((int)(point.getY()*H/8) + H/9) -1;
    pixelhistogram[W*Y+X]++;
}
// Now that I have the pixelhistogram
// I don't know how to render the shades using this  

AffineTransformation 是一个简单的类,它对一个点执行仿射变换。我省略了代码,否则问题会变得太冗长。

【问题讨论】:

    标签: java algorithm colors fractals


    【解决方案1】:

    根据像素[W*Y+X] 是否小于 n1、介于 n1 和 n2 之间或大于 n2,将像素 (X,Y) 渲染为浅绿色、绿色或棕色。要确定 n1 和 n2,试错法可能是最简单的解决方案,但您可以对已记录的像素计数日志制作 actual histogram,以帮助判断在何处放置切口(或更一般地,您可以使用聚类算法自动完成)。

    PS:在您展示的图像中,看起来茎是用 L 系统渲染的,而叶子仅使用三个叶子变换来渲染(即省略第四个“茎变换”);我猜他们正在使用对数像素数来遮蔽绿色,而不是遮蔽茎。

    补充:我被要求在下面讨论对数直方图。为避免陷入困境,我建议首先使用 R 等功能齐全的数据分析软件,看看它是否能满足您的需求。将像素数组写入文本文件,每行一个数字,然后启动 R 并运行:

    ct=scan('pixels_data.txt')
    hist(log(ct))
    

    如果您看到多峰直方图(即,如果它有清晰的峰和谷),这将提示如何选择 n1 和 n2:将它们放在谷中(即如果图上的谷在 y 处,设置 n1= exp(y))。

    如果您最终在 Java 中绘制直方图,显然可以使用 Jfreechart 软件完成。只需使用像素数组中的值的日志创建一个数组,然后从中创建直方图。

    如果您使用标准的 3 变换巴恩斯利蕨类植物,我希望您最多只能在直方图中看到一个山谷,从而将真正高的茎值与叶子分开。要为叶子着色,如果 n 是叶子和茎之间的切口,并且像素 [W*Y+X] 小于 n,则可以使用以下方法着色:

    v=128.0*(log(n)-log(pixels[W*Y+X]))/log(n);
    RGB=(v,255,v)
    

    PS:仅使用随机迭代算法获得粗茎将是一个问题。如果您将第三个变换更改为不那么奇异,您的茎最终会看起来像薄蕨类植物而不是树枝。例如

    {"title":"Thick Stem Fern","alist":[[
    [0.11378443003074948,-0.005060836319767042,0.013131296101198788,0.21863066144310556,0.44540023470694723,0.01726296943557673],
    [0.15415337683611596,-0.17449052243042712,0.23850452316465576,0.2090228040695959,0.3652068203134602,0.11052918709831461],
    [-0.09216684947824424,0.20844742602316002,0.2262266208270773,0.22553569847678284,0.6389950926444947,-0.008256440681230735],
    [0.8478159879190097,0.027115858923993468,-0.05918196850293869,0.8521840120809901,0.08189073762585078,0.1992198482087391]
    ]],"va":[1,0,0,1,0,0],"word_length":6,"level_max":40,"rect_size":1}
    

    json data来形容:

    【讨论】:

    • 感谢您的回复。我将更多地研究 L-Systems 的问题。您能否提供一些代码/伪代码或资源,我可以在其中阅读有关日志直方图的信息?
    • 我在回答中添加了一些关于日志直方图的信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多