Title: Julia smooth-colouring : how to do ? Post by: Matplotlib on April 24, 2017, 01:00:04 PM Hello,
I am running a Julia set program, and I have some issues... I don't want to enter in the language's details, it's not what's wrong. I run z\mapsto z^2+c several times, till I escape or I get to the max number of iterations possible. During the process, I sum over all the exp(-|z|) values (is it the good way for smooth-colouring ?), that I store in a var (let's name it "escape_count"). In the end, I get a number that I don't know how to use ! How to get a color from the value of escape_count ? Any examples with explanations would be very helpful, even if you redirect to some papers ! (I haven't been able to find something clear about the smooth-colouring) Title: Re: Julia smooth-colouring : how to do ? Post by: lycium on April 24, 2017, 04:16:03 PM Welcome to the forum :) Some resources I've found on this topic a few years ago:
http://www.iquilezles.org/www/articles/mset_smooth/mset_smooth.htm http://linas.org/art-gallery/escape/escape.html Also there is even a master's thesis on this topic by Jussi Härkönen: http://jussiharkonen.com/gallery/coloring-techniques/ Title: Re: Julia smooth-colouring : how to do ? Post by: xenodreambuie on April 24, 2017, 10:09:12 PM That is said to be a good smooth colouring method, though I haven't tried it. The most general way to map a scalar to colours is to multiply it by a strength (or density) parameter and add an offset parameter. Then wrap it into a fixed range as an index into a gradient. The alternative is to generate colour values algorithmically, typically to make some kind of endlessly varying combination of waves.
Title: Re: Julia smooth-colouring : how to do ? Post by: FractalStefan on April 24, 2017, 11:52:31 PM Hi Matplotlib,
in your Iterate function, where you do the Z->Z²+C iteration, just do the following before you return the iterator value (it): Code: it = it + 2 - log(log(a² + b²)) / log(2) it is the iterator value, and a and b are the real and imaginary part of Z after Z escaped to infinity. For maximum speed, you can define log(2) as a constant. Your color mapping code should of course be able to cope with a fractional iterator value. The escape radius should be greater than the usual 2, e.g. 4 or 5, to get best results. Example script (http://www.stefanbion.de/fraktal-generator/mandelbeispiel.htm) (Mandelbrot, but should also work for Julia since they both use the same iteration equation). Click the checkbox to see the difference. Stefan Title: Re: Julia smooth-colouring : how to do ? Post by: lycium on April 24, 2017, 11:57:08 PM For maximum speed, you can define log(2) as a constant. Pretty sure maximum speed requires 1/log(2), not log(2) ;) Furthermore pretty much every compiler will precompute log(2), but won't do the 1/log(2) optimisation. Title: Re: Julia smooth-colouring : how to do ? Post by: FractalStefan on April 25, 2017, 12:25:35 AM Pretty sure maximum speed requires 1/log(2), not log(2) ;) Because multiplying is faster than dividing? I made a quick test in JavaScript (http://www.stefanbion.de/tmp/divmultest.htm). The result: Division: 1204 ms Multiplication: 1203 ms Really a big difference! ;-) Edit: But you're right - at least in JavaScript there's no difference if log(2) is defined as constant or used directly as operand: Quote Using a constant as operand Division: 1205 ms Multiplication: 1202 ms Using log(2) as operand Division: 1203 ms Multiplication: 1204 ms Edit2: Okay, I was wrong, multiplication is faster than division. JavaScript tricked me as it optimized the testing loop. Apparently it saw that I did nothing with the result, so I changed the script (here's version 2 (http://www.stefanbion.de/tmp/divmultest2.htm)) so that it now outputs the results - and indeed, the diffrences are now significant: Quote Using a constant as operand Division: 19465 ms (result: 721337883.3478911) Multiplication: 13629 ms (result: 721369432.0115957) Using log(2) as operand Division: 20261 ms (result: 721312455.102812) Multiplication: 13846 ms (result: 721337110.8961784) So big difference between mul and div, but not between using log(2) as a constat or directly... 88) Edit2: Wow, Opera and Chrome are really slow compared to Firefox which I used for the above results! Opera: Quote Using a constant as operand Division: 32267 ms (result: 721345943.255802) Multiplication: 29262 ms (result: 721320344.2994019) Using log(2) as operand Division: 31125 ms (result: 721339741.0393113) Multiplication: 28634 ms (result: 721362340.1294624) Chrome: Quote Using a constant as operand Division: 28945 ms (result: 721352593.7384236) Multiplication: 26304 ms (result: 721348815.09295) Using log(2) as operand Division: 28062 ms (result: 721325577.7421819) Multiplication: 26247 ms (result: 721343337.9390984) Title: Re: Julia smooth-colouring : how to do ? Post by: lycium on April 25, 2017, 06:27:16 AM lol, "performance" testing with JavaScript :D
You have two "Edit2" btw ;) Title: Re: Julia smooth-colouring : how to do ? Post by: Matplotlib on April 26, 2017, 09:13:18 PM @lycium the PhD is just amazing ! Explains everything in details ! In fact, I had already been on the other links you gave to me, and I did not quite understand properly what they wanted to do.
@FractalStefan thanks ! Also, thanks for the speed comparisons ! I never thought to store 1/ln(2) in a var, which appears to be a simple but great idea (and yes, I use ln for log_e !) Title: Re: Julia smooth-colouring : how to do ? Post by: Matplotlib on May 10, 2017, 05:42:40 PM Okay ! I've read that PhD, it's just as great as I expected ! I looove when things are detailed and as clear as mountain water !
Hence, I've generated by myself some images : + http://matplotlib.deviantart.com/art/Julia-set-SIC-algorithm-c-0-5-0-25i-679827575 + http://matplotlib.deviantart.com/art/Julia-set-SIC-algorithm-c-0-75-0-11i-679827809?ga_submit_new=10%3A1494428357 + http://matplotlib.deviantart.com/art/Julia-set-SIC-algorithm-c-0-4-0-6i-679829631?ga_submit_new=10%3A1494429324 Let me copy/paste the info I gave on the images' page : Smooth iteration count : u(z0)=n+1+logd{ln(M)/ln|zn|} where n is the number of iterations, M the maximum radius bound, and d the degree of equation : zn+1=aznd+Q(zn) where deg(Q)<=d-1 Now, the palette I use is defined as follows : + r=⌊u(z0)/nmax⌋ + g,b = r,r This means I have a palette that has length 256, and palette[i]=i for i∈[|0,255|]. But here are some issues I get : + u(z0) appears to never reach nmax. Therefore, I never get r greater than a bouded value (usually around 150). What is the maximum bound of this function u I'm using ? I have tried using the famous u(z0)=n+1-logd{|zn|}, but this does not change much the values taken. + How to use an adapted coloured palette ? It looks like the values taken by u get stuck on one side of the palette, that side depending on the current fractal. I have no clue of how to generate beautiful images using all the colours on the palette. Instead, it only uses half the palette. Here's a palette I'm using (.python/numpy code) : Code: palette_r = list(map(lambda z: int(z),np.linspace(0,90,538).tolist() +np.linspace(90,251,428).tolist() +np.linspace(251,251,544).tolist()+np.linspace(251,130,542).tolist())) (https://img15.hostingpics.net/pics/547076palette.png) Now, let's generate the Julia set for the value c=0.5+0.25i using this palette (smaller size) : (https://img15.hostingpics.net/pics/525468Julia05025jsmall.png) I'm basically calling palette_X[I] for I=⌊L*u/nmax⌋ where L=len(palette_X). As you can notice, the render is not that good, as a lot of the image is coloured blue. Also, another issue is that sometimes, u/nmax can exceed 1, so I have an "out of range" error raised. That can be easily fixed by having the palette looping itself and using a modulo, but I just don't get why it behaves like this, as I noticed that u never reached values higher than nmax (I had no problems using the B&W palette). Title: Re: Julia smooth-colouring : how to do ? Post by: FractalStefan on May 14, 2017, 12:59:08 AM In order to see more of the palette colors, you can use a nonlinear function to stretch the colors at the higher end of the iteration count and compress them at the lower end.
In -> this thread (http://www.fractalforums.com/programming/non-parametric-color-mapping-techniques/msg101580/#msg101580) I described some formulas for this purpose. Title: Re: Julia smooth-colouring : how to do ? Post by: Matplotlib on May 15, 2017, 08:18:59 PM Okay, I'm now using the hyperbolic tangent as a non-linear index for the palette. I also noticed I need a "smooth palette", which the linear interpolation does not provide. I'm now using a Bezier interpolation, and I got this render : http://matplotlib.deviantart.com/art/Julia-set-SIC-algorithm-c-0-4-0-6i-680773601 (details in description)
Most of my issues are now solved, thanks ! Title: Re: Julia smooth-colouring : how to do ? Post by: FractalStefan on May 15, 2017, 09:11:44 PM Okay, I'm now using the hyperbolic tangent as a non-linear index for the palette. Interesting idea - I have to try this, too! :) However - since tanh(x) only approximates the value of 1, you should use i = tanh(n * u/Nmax) / tanh(n) with n = ]0,10] (for example 0.1 ... 10) Also, if you set n by a slider control (or some other input control), the user can set the linearity of the gradient individually. I also noticed I need a "smooth palette", which the linear interpolation does not provide. I'm now using a Bezier interpolation, and I got this render : http://matplotlib.deviantart.com/art/Julia-set-SIC-algorithm-c-0-4-0-6i-680773601 (details in description) Nice! Can you explain this more detailed (Bezier interpolation)? Title: Re: Julia smooth-colouring : how to do ? Post by: Matplotlib on May 15, 2017, 10:10:20 PM Nice! Can you explain this more detailed (Bezier interpolation)? I'll make a more detailed thread tomorrow with the the computer as I already thought about creating one :)Title: Re: Julia smooth-colouring : how to do ? Post by: FractalStefan on May 16, 2017, 01:18:34 AM I'll make a more detailed thread tomorrow with the the computer as I already thought about creating one :) Very good! :) And I tried the hyperbolic tangent function meanwhile. The results are included in the comparision chart in my new article about color mapping methods: http://www.stefanbion.de/fraktal-generator/colormapping/ BTW: I don't use a predefined color palette; instead the actual colors are calculated dynamically by interpolation. For example, if color 1 is #008000 and color 2 is #FF0080, then with a normalized color index of 0.5, the resulting color will be #7F4040. This way the colors automatically become smoothed (when using a fractional iteration count) . Is this similar to what you are doing, except that you are using this Bezier thing instead of linear interpolation as I do? Title: Re: Julia smooth-colouring : how to do ? Post by: Matplotlib on May 16, 2017, 11:58:55 AM You won't believe it but the color-mapping I prefer amongst all the ones you tried is the tanh :) Anyways, here's what we talked about yesterday evening : http://www.fractalforums.com/programming/creating-a-good-palette-using-bezier-interpolation/ |