着色Barnsley Fern分形

时间:2014-06-11 06:45:51

标签: java algorithm colors fractals

在渲染巴恩斯利蕨形状分形时,我想出单色图像或最多四个彩色图像,即左下,右下,下茎和其余叶子。这是我得到的图像:

My fern

然而,我想要的是在树叶中加入色调,使树干更厚,颜色也不同,如:

The fern example I want

我挖掘了一些可以使用的算法,然后我在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是一个简单的类,它在一个点上执行仿射变换。我省略了代码,因为否则问题会变得太冗长。

1 个答案:

答案 0 :(得分:4)

根据像素[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:使用随机迭代算法获取粗茎只是一个问题。如果你将第3个变换改为不那么单一,那么你的茎会变得像蕨类植物而不是枝条。 E.g。

{"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是否要描述:

Thick Stem Fern