37

私は現在、非常に巨大な(65536x65536ピクセル以上の)マンデルブロ画像を生成するプログラムを作成しています。それらを正当化するスペクトルとカラーリングスキームを考案したいと思います。ウィキペディアで紹介されたマンデルブロ画像は、特にシーケンスのすべてのズームレベルでパレットがどのように変化したままであるかを示す優れた例のようです。ただし、パレットを回転させているのか、それとも他のトリックを実行してこれを実現しているのかはわかりません。

私はマンデルブロ集合の滑らかな彩色アルゴリズムに精通しているので、バンディングを回避できますが、このアルゴリズムからの出力値に色を割り当てる方法が必要です。

私が生成している画像はピラミッド型であるため(たとえば、それぞれが前の画像の半分のサイズの一連の画像)、次の画像の間でパレットが変更されている限り、ある種の回転パレットを使用できます。ズームレベルはそれほど明白ではありません。

4

7 に答える 7

42

これはスムーズ カラー アルゴリズムです。

複素数から始めて、それがエスケープするまで何度もz0繰り返すとしましょう。n終点とするzn

スムーズな値は

nsmooth := n + 1 - Math.log(Math.log(zn.abs()))/Math.log(2)

これはマンデルブロでのみ機能します。ジュリア集合の滑らかな関数を計算する場合は、次を使用します

Complex z = new Complex(x,y);
double smoothcolor = Math.exp(-z.abs());

for(i=0;i<max_iter && z.abs() < 30;i++) {
    z = f(z);
    smoothcolor += Math.exp(-z.abs());
}

それからsmoothcolorインターバル(0,max_iter)です。

で除算smoothcolormax_iterて、0 から 1 の間の値を取得します。

値から滑らかな色を取得するには:

これは、たとえば (Java で) 呼び出すことができます。

Color.HSBtoRGB(0.95f + 10 * smoothcolor ,0.6f,1.0f);

HSB カラー パラメーターの最初の値は、カラー サークルから色を定義するために使用されるためです。

于 2009-08-07T09:21:25.367 に答える
6

以下は、単純なマンデルブロ生成器の典型的な内部ループです。滑らかな色を得るには、実際の複雑な「長さ」と、ベイルアウトした反復を渡します。色の計算に使用する変数を確認できるように、マンデルブロ コードを含めました。

for (ix = 0; ix < panelMain.Width; ix++)
    {
    cx = cxMin + (double )ix * pixelWidth;
    // init this go 
    zx = 0.0;
    zy = 0.0;
    zx2 = 0.0;
    zy2 = 0.0;
    for (i = 0; i < iterationMax && ((zx2 + zy2) < er2); i++)
        {
        zy = zx * zy * 2.0 + cy;
        zx = zx2 - zy2 + cx;
        zx2 = zx * zx;
        zy2 = zy * zy;
        }
    if (i == iterationMax)
        {
        // interior, part of set, black
        // set colour to black
        g.FillRectangle(sbBlack, ix, iy, 1, 1);
        }
    else
        {
        // outside, set colour proportional to time/distance it took to converge
        // set colour not black
        SolidBrush sbNeato = new SolidBrush(MapColor(i, zx2, zy2));
        g.FillRectangle(sbNeato, ix, iy, 1, 1);
        }

以下のMapColor:(ColorFromHSV関数を取得するには、このリンクを参照してください)

 private Color MapColor(int i, double r, double c)
                {
                double di=(double )i;
                double zn;
                double hue;

                    zn = Math.Sqrt(r + c);
                    hue = di + 1.0 - Math.Log(Math.Log(Math.Abs(zn))) / Math.Log(2.0);  // 2 is escape radius
                    hue = 0.95 + 20.0 * hue; // adjust to make it prettier
                    // the hsv function expects values from 0 to 360
                    while (hue > 360.0)
                        hue -= 360.0;
                    while (hue < 0.0)
                        hue += 360.0;

                    return ColorFromHSV(hue, 0.8, 1.0);
                }

MapColour は、ベイルアウト値を 0 から 1 に「平滑化」して、恐ろしいバンディングなしで色をマッピングするために使用できます。MapColour や hsv 関数をいじると、使用する色を変更できます。

于 2013-09-07T23:19:44.753 に答える
6

スムーズ カラー アルゴリズムを使用してビューポート内のすべての値を計算し、パレットを最低値から最高値にマッピングします。したがって、拡大して高い値が見えなくなると、パレットも縮小されます。n と B に同じ定数を使用すると、完全にズームアウトしたセットの範囲は 0.0 から 1.0 になりますが、ズームが深くなると、ダイナミック レンジが縮小し、200% ズームで 0.0 から 0.1、200% ズームで 0.0 から 0.0001 になります。 20000%ズームなど

于 2008-12-16T09:22:43.547 に答える
4

試行錯誤で簡単にできるようです。使用するエンドポイントカラー(黒と白、青と黄色、濃い赤と薄緑など)のHSV1とHSV2(色相、彩度、値)を定義でき、アルゴリズムを割り当てて各ピクセルに対して0.0から1.0の間の値P。次に、そのピクセルの色は次のようになります

(H2 - H1) * P + H1 = HP
(S2 - S1) * P + S1 = SP
(V2 - V1) * P + V1 = VP

それが終わったら、結果を観察して、どのように気に入っているかを確認してください。Pを割り当てるアルゴリズムが連続である場合、勾配も滑らかである必要があります。

于 2008-12-15T20:00:38.533 に答える
4

私の最終的な解決策は、見栄えの良い (そしてかなり大きな) パレットを作成し、それを定数配列としてソースに格納してから、スムーズ カラー アルゴリズムを使用してその中のインデックス間を補間することでした。パレットは折り返されます (連続するように設計されています) が、これはあまり問題ではないようです。

于 2008-12-17T10:52:53.987 に答える
-2

ここでは、javascript を使用したバージョンを見つけることができます

利用方法 :

var rgbcol = [] ;
var rgbcol = MapColor ( Iteration , Zy2,Zx2 ) ;
point ( ctx , iX, iY ,rgbcol[0],rgbcol[1],rgbcol[2] );  

関数

/*
 * The Mandelbrot Set, in HTML5 canvas and javascript.
 * https://github.com/cslarsen/mandelbrot-js
 *
 * Copyright (C) 2012 Christian Stigen Larsen
*/

/*
 * Convert hue-saturation-value/luminosity to RGB.
 *
 * Input ranges:
 *   H =   [0, 360] (integer degrees)
 *   S = [0.0, 1.0] (float)
 *   V = [0.0, 1.0] (float)
 */
function hsv_to_rgb(h, s, v)
{
  if ( v > 1.0 ) v = 1.0;
  var hp = h/60.0;
  var c = v * s;
  var x = c*(1 - Math.abs((hp % 2) - 1));
  var rgb = [0,0,0];

  if ( 0<=hp && hp<1 ) rgb = [c, x, 0];
  if ( 1<=hp && hp<2 ) rgb = [x, c, 0];
  if ( 2<=hp && hp<3 ) rgb = [0, c, x];
  if ( 3<=hp && hp<4 ) rgb = [0, x, c];
  if ( 4<=hp && hp<5 ) rgb = [x, 0, c];
  if ( 5<=hp && hp<6 ) rgb = [c, 0, x];

  var m = v - c;
  rgb[0] += m;
  rgb[1] += m;
  rgb[2] += m;

  rgb[0] *= 255;
  rgb[1] *= 255;
  rgb[2] *= 255;

  rgb[0] = parseInt ( rgb[0] ); 
  rgb[1] = parseInt ( rgb[1] );
  rgb[2] = parseInt ( rgb[2] );  

  return rgb;
}

// http://stackoverflow.com/questions/369438/smooth-spectrum-for-mandelbrot-set-rendering
// alex russel : http://stackoverflow.com/users/2146829/alex-russell

function MapColor(i,r,c)
{
    var di= i;
    var zn;
    var hue;

        zn = Math.sqrt(r + c);
        hue = di + 1.0 - Math.log(Math.log(Math.abs(zn))) / Math.log(2.0);  // 2 is escape radius
        hue = 0.95 + 20.0 * hue; // adjust to make it prettier
        // the hsv function expects values from 0 to 360
        while (hue > 360.0)
            hue -= 360.0;
        while (hue < 0.0)
            hue += 360.0;

        return hsv_to_rgb(hue, 0.8, 1.0);
}
于 2016-06-21T10:03:35.357 に答える