Smooth 1D coloring

  • 9 Replies
  • 501 Views

0 Members and 1 Guest are viewing this topic.

Offline Spyke

  • *
  • Strange Attractor
  • ******
  • Posts: 98
    • Spyke Art
« on: April 15, 2019, 07:54:42 PM »
I started a thread on 2D coloring, then spent most of my time describing a 1D coloring method. So I am forking the thread with a new appropriate title. This post is a follow up of https://fractalforums.org/fractal-mathematics-and-new-theories/28/2d-coloring/2745/msg13948#msg13948

TL;DR summary:
If f(z,c) is a continuous fractal generating formula, zi or more properly zi(c) are the iterations for parameter space value c, N is the max iteration cutoff value, and R is a good escape radius, that is \( |z_i|>R, j>i => |z_j| > R \). Then \(  \sum_{i=0}^{N}\max(R-|z_i|,0) \) is a continuous function \( \mathbb{C \rightarrow R} \), and so suitable for use in a smooth coloring algorithm.

I choose R-|zi| originally because both these values are readily available during the fractal calculation. Actually the proof only requires \[ (1) |z| \geq R => g_1(z)=0  \]
If g1 satisfies condition (1) then \(  \sum_{i=0}^{N}g_1(z_i) \) is continuous.

Consider the more relaxed condition \[ (2) |z| \geq R => g_1(z) \leq 0  \]\[ (3)g_1(z)=\max(g_2(z),0) \]
If g2 satisfies (2) the g1 defined by (3) satisfies condition (1). To reduce verbosity, in what follows when I define a function can call it g2, it satisfies condition (2) and it defines a companion function g1 via (3).

The function in the last post, \( g_2(z)=R-|z| \), is heavily depends on the value or R. If you are working on an image, then changing R will really mess up your colors.

 \( g_2(z)=1-|z|/R \) works much better. It still depends on R, but the color changes due to changes in R are more subtle. Note that \( 0 \leq g_1(z) \leq 1 \). If n is the iteration where the orbit escapes then summation is in the range  \(  0 \leq \sum_{i=0}^{N}g_1(z_i) \leq n \). This is starting to look like an iteration count. In fact for large R the summation starts to approach the iteration count step function. Of course, that is what we are trying to avoid. Still it is nice to know that R is a dial we can turn where one extreme is the familiar iteration count.

Both of these examples have \( |z|<R => g_1(z)>0 \). Which kind of complements condition (1). Don't be fooled, it is not necessary. Purists may object to relaxing this condition. It was already blasphemy to not give each iteration its full count value of 1, now some pre-escape steps in the iteration may contribute nothing, or horrors! even negatively to computation. Well you know I am not a purist, this is just another artistic tool to add to the tool box.

\( g_2(z)=1-|z|/R_1 \, where \, R_1 \leq R \). Now the radius that contributes to the summation is smaller, potentially much smaller than the escape radius. Small values for R1 tends to put stronger emphasis, and direct viewer focus on points close to the fractal boundary. Again an artistic consideration not necessarily a mathematical one.

Variations on absolute value are possible. set z = x + iy
\[ g_2(z)=1-(|x|+|y|)/R_1\\
g_2(z)=1-\max(|x|,|y|)/R_1\\
g_2(z)=1-| |z| - a | / R_1 \, where \, a + R_1 <= R
 \]
The first is a filled in diamond, the second is a filled in square, the third, if a > R1 is a circle of radius a and width R1. Generally these choices only make subtle differences in the final image. If you do something extreme, like fractal formula is f(z,c) = c, and iteration count is 1, then you will see the shapes described, fuzzy around the edges. Each formula has a personality, but they look nothing like the single-iteration shape.

You can move the center \( g_2(z)=1-| z - c_0 | / R_1 \, where \, c_0 \in \mathbb{C}, |c_0| + R_1 <= R \). There are obvious similar variations for the other functions. Moving the center like this creates some asymmetry in the coloring. The colors are different on different sides of a feature in the image, often creating a shadowing like effect. Don't push this too far, displacing the coloring center too much results in disconnected splotches rather than subtle shading effects.

Want more functions? Let g1 be any function that satisfies (1). Let h be any function mapping  \( \mathbb{C \rightarrow R} \). Any function at all, really, no restrictions. Then h1(z) = g(z) * h(z) satisfies condition (1) and can be used for continuous colors. Go wild! But make sure your color palette can handle negative numbers.

Sometimes, for functions defined by (3), you get bands where \( g_2(z_i) = 0 \) for some zi in the orbit. If you look closely the color change is actually continuous but the gradient changes sharply. The problem is the derivative is not continuous. Mathematics define different levels of smoothness. C0 is the class of continuous functions, C1 is the class of continuously differentiable functions. See https://en.wikipedia.org/wiki/Smoothness.

Derivatives, at least in high school calculus, are for functions  \( \mathbb{R  \rightarrow  R} \, or \, \mathbb{C \rightarrow  C} \). Our functions are \( \mathbb{C \rightarrow  R} \). But let's discard mathematical rigor for now and pretend we can differentiate these functions. (If you insist on rigor, consider g as \( g:\mathbb{R^2  \rightarrow  R} \) and look at the partial derivatives.)

Assume g2 is differentiable, that is, \( g_2 \in C^1 \). g1(z) = max(g2(z),0) is continuous, but in general not differentiable. The derivative is discontinuous when g2(z) = 0. (or undefined, or two-sided, or whatever it is a bad deal)

This is easily fixed. \( h_1(z) = g_1(z)^2 \) is differentiable. Both side of the derivative is 0 where g2(z)=0. So  \( h_1 \in C^1 \).

You can attain any level of smoothness. If \( g_1 \in C^2 \, then \, h_2(z) = g_1(z)^3 \in C^2 \), etc.



« Last Edit: April 15, 2019, 08:12:20 PM by Spyke »
Earl Hinrichs, offering free opinions on everything.

Offline gerrit

  • *
  • 3f
  • ******
  • Posts: 1811
« Reply #1 on: April 15, 2019, 11:18:49 PM »
Can you give some examples? Below a test I applied to the Mandelbrot set.
Top-left: normal iteration coloring, Top-right: your method with R=1e6.
Bottom-left: linear interpolation on loglog scale (see Newton-Hines for exact formula https://fractalforums.org/fractal-mathematics-and-new-theories/28/newton-hines-fractals/2737/msg13924#msg13924),
Bottom-right: Greens function coloring (\( iter - log(log(|z|))/log(2) \)).

The latter only works if escaping is quadratic (log(3) for cubic etc), the linear interpolation only assumes escape is doubly exponential.

Your method produces apparent bands, if I got it right, but zooming reveals they are smooth at the apparent jumps, just rapidly varying.
Changing your method to use \( g(z) = 1 - log(|z|)/log(R) \) works better, but still some faint bands see second attachment.

Offline Spyke

  • *
  • Strange Attractor
  • ******
  • Posts: 98
    • Spyke Art
« Reply #2 on: April 16, 2019, 03:17:40 AM »
gerrit: I will put together some examples tomorrow. I started to do some today, but that is going down the proverbial rabbit hole. I had to abandon the pictures to have time to get the text written. I think you have it implemented correctly, thank you for trying it out.

For large R, at least with the \( 1-|z|/R \) variant, this method is approximately that same as iteration counting. (Each step is adding something very close to 1.) So for R=1e6 it is going to have bands. Try a smaller R. As I pointed out half way through the post, the coloring radius does not have to match the escape radius. You can use \( 1-|z|/R_1 \)  where \( R_1 \) < R works. Try \( R_1 \) = 1 or 2, and the banding should go away.

It is also true that the derivative of the color function has discontinuities. It is continuous, but the derivative discontinuites can also create a banding effect. The function is \( C^0 \) but not \( C^1 \). Exponents can move the function into higher smoothness classes.  \( (1-|z|/R_1)^n \) will move the summation up to \( C^{n-1} \). I usually go with n=2. However, that does not help much when R is so large.

\( g(z) = 1 - \log(|z|)/\log(R) \) looks dangerous, it blows up if |z|=0. \( g(z) = 1 - \log(|z|+1)/\log(R) \) would be safer. But who wants safe, your version is more exciting. It is likely smoother simply because the denominator log(R) is a whole lot smaller that R=1e6.
« Last Edit: April 16, 2019, 02:58:45 PM by Spyke »

Offline gerrit

  • *
  • 3f
  • ******
  • Posts: 1811
« Reply #3 on: April 16, 2019, 04:39:48 AM »
I tried for R=2 (smallest possible). Attachments a,b,c  use \( (1-|z|/R)^p \) for p=1,2,4.
Looks good for p=4. A nice general approach, seems to work well.

Offline pauldelbrot

  • *
  • 3f
  • ******
  • Posts: 1421
« Reply #4 on: June 05, 2019, 03:12:42 AM »
I've implemented something similar that I call "smooth traps". The idea is that there is a trap shape somewhere, and when an orbit point lands inside it a value is added to a sum. The base value ranges from 1 at the trap center to 0 at the edge, is raised to a power and possibly put through an additional function, and then added into the sum. The sum is put through another function before being used to color the pixel. And the orbit points can be modified with a function beforehand, as well as only every nth one counted.

If the trap shape is a disk, the center is at (0,0), and the three functions are the identity function, this appears to be the same thing discussed in this thread. Of course the center can be elsewhere and the functions can be non-trivial. Making the orbit modifying function be 1/x results in the trap effectively becoming the outside of the disk, with 0 at the edge and 1 at infinity, for instance.

I also implemented two other shapes: half-plane (0 at the edge, 1 at infinity, can be translated or rotated, the position within the half-plane is put through a rational function with a horizontal asymptote tending to 1) and ribbon (infinitely long, finitely high rectangle, 0 at the edges and 1 along the midline, can be translated or rotated).

Two images are attached. 1: Hnon map parameter space. Trap is a radius-3 disk about the point (1.31900998, -0.4622137328), power is two, the only non-identity function is the transfer of the sum to the color gradient, where I used log. 2: A space-filling triple matchmaker Julia set (there are no attractors; the whole Riemann sphere is the Julia set). 2D colored by combining two sums of this type. The first uses the exact same parameters, down to the disk center, as the Hnon image. The second uses a ribbon trap whose midline passes through (11.31900998, -0.4622137328), of midline-to-edge width 2, rotated 0.61111 of a complete circle, and again with logarithmic transfer into color space.

Offline pauldelbrot

  • *
  • 3f
  • ******
  • Posts: 1421
« Reply #5 on: June 05, 2019, 07:57:30 AM »
I also did something similar with your "smooth min z" coloring, described in another thread:

Quote
I am trying a variation, of sorts, of min-z. I wanted a 2D version. Using the z that gives the minimum is discontinuous. It looks similar to Claude's i of min |zi| coloring. I wanted something continuous.

I take a starting value, v, large and arbitrary. On each iteration if |z| < |v| then replace v with a weighted average of z and v. For example, if b = |z|/|v| then v = b * v + (1-b) * z provides a smooth transition from v to z. v keeps getting smaller, so it is sort of like min-z. The final v is used for selecting the color.

Again, I gave my version the ability to transform the orbit point beforehand; to use any point as the center (so, min |z - center|); and to apply a function to the output before turning it over to the color gradient mapper.

First image: the Hnon "Mandelbrot" again, using distance from the point (0.3564814814, -0.8240740737) rather than the origin. The result is noisier than "smooth traps" but does also bring out the structures in the strange-attractor "beach".

Second image: a triple matchmaker Julia set without finite attractors (not the same one as in the previous post). 2D colored using two different sets of "smooth min-z" parameters. For one layer, the orbit point is run through the exp function and translated to move (-5.24280599365, -4.73679442832) to the origin before applying the method. For the other, the orbit's distances from the point (-1.27381, 0.34524) are used, without any modification by added functions. The results are interesting and highlight some of the structures well, but this method seems prone to attaching "blobs" or "warts" to other structures, and gives an overall less clear picture of the true underlying Julia-set structural shapes than "smooth traps" does.

No doubt this method has a place in the smooth-colorer's toolkit, but it seems that for these two particular types of fractals "smooth traps" is generally going to give better results. I will, of course, be doing further research on this ... at some point.

Offline Spyke

  • *
  • Strange Attractor
  • ******
  • Posts: 98
    • Spyke Art
« Reply #6 on: June 08, 2019, 11:01:04 PM »
Paul: "smooth traps" sounds very similar.

In accumulator colors I try to require that the pseudo-distance inner function is 0 outside a bounded region and always <= 1.

The function range bound makes it possible to say, "see it is like iteration counting, after all counting is just adding 1 each iteration." The bounded range also helps when deciding how to scale the palette, but otherwise it is mostly unnecessary.

The bounded non-zero domain avoids color banding, provided it is contained inside the escape threshold.

In the general version, it can be any function from Complex numbers to Real numbers. This is in fact how I have coded it in my program. I have tried several wild things, and will probably experiment there in the future. But almost always the more ascetically pleasing results are found keeping to functions limited this way.

I usually just mess with the \( \mathbb{C}\Rightarrow\mathbb{R} \) function directly, I like your idea of transforming z with a \( \mathbb{C}\Rightarrow\mathbb{C} \)  function first, and then applying a \( \mathbb{C}\Rightarrow\mathbb{R} \)  function. Logically equivalent, but much easier to track.

What additional things do you do with the sum? It can be re-scaled and shaped with sqrt or log like iteration count values to tame a noisy palette. Are you doing more?

I like your ideas dealing with infinity. I think I spent too much time with polynomials and iteration cut-offs, so that was never a consideration. If everything is "inside", then there is no reason for a bounded domain. The [0,1] or similarly bounded range is probably still necessary.

The upper half plane is conformally isomorphic to the unit disk by \( z \Rightarrow \frac{i-z}{i+z} \). This would be an interesting transformation to drop into your preliminary transformation.

I had also tried grabbing every nth orbit point. I did not notice much difference, the output range is reduced to 1/n and some performance speed up, since 100*(n-1)/n percent of the color calculation operations are avoided.

One variation I tried was taking a \( p : \mathbb{Z}\Rightarrow\mathbb{R} \) function, let q(k) be the value from above at step k , and  evaluating \( \sum p(k)*q(k) \). If \( p(k) = cos( k * 2* \pi / n ) \), this is like a DFT and teases out components with frequency k. I tried this with space filling mess, but it made no difference. However it does a great job of lighting up certain bulbs and minis in polynomial based fractals.

Offline Spyke

  • *
  • Strange Attractor
  • ******
  • Posts: 98
    • Spyke Art
« Reply #7 on: June 09, 2019, 12:11:38 AM »
Smooth min z coloring now golf coloring

Unless someone can point me to a conflicting precedent (which I doubt), I am going to start calling "smooth min z coloring" "golf coloring". Anyway let me try it for one post.

Paul: I have also noticed some strange artifacts in the "golf" coloring. I get some flat circles amid nice swirling colors. I have been meaning to investigate it. My first hypothesis is that somehow the value v shrinks too far too fast. The orbit falls into an repelling almost-cycle close to the center. By the time the orbit diverges from this cycle, v is pulled in and the "is z closer than v" test thereafter is always false. But that is just speculation, someday I will investigate.

I actually used a weighted-weighted average.

v the moving point (the golf ball)
z the orbit point
w >= 0 the weight.
(center = 0, just to simplify the presentation)
b = |z|/|v| < 1

v = ((w+b)*v + (1-b)*z)/(1+w)

Still a linear sum, and still moves v closer to the center. w=0 is the simple version. w>0 slows down v's movement toward the center.

Often by tweaking the weight and the starting point for v I can squeeze some interesting colors out of an otherwise bland image.

I apologize if I am stating the obvious, v is a complex number. At the end of the iteration, v is a two dimensional value that can be used for coloring.

I have tried many variations, most are consigned to archive files now. The two methods I regular use are

(i) extract a color  for the real and imaginary parts from two different palettes (or the same palette if it is a good one), and blend the colors 50/50.

(ii) Real value controls light and dark, imaginary value selects a color from a palette.

OK, so why golf coloring? The tracking value v is the golf ball. The center is the hole. At each step of the iteration the orbit point gets a chance to hit the golf ball closer to the hole. (OK, it is more like z is pulling on v, but please don't tear down my cool analogy.)


Offline pauldelbrot

  • *
  • 3f
  • ******
  • Posts: 1421
« Reply #8 on: June 09, 2019, 12:17:47 AM »
Interesting. I shall certainly try the weighted version.

Offline Spyke

  • *
  • Strange Attractor
  • ******
  • Posts: 98
    • Spyke Art
« Reply #9 on: June 11, 2019, 06:09:48 PM »
Paul, I am giving up on the golf coloring, at least for now. It seems to only work well on fractals that are already well behaved. When there is a lot of space filling type mixing, it stubbornly becomes a uniform color, except for the strange artifacts.


clip
Smooth 1D coloring

Started by Spyke on Image Threads

17 Replies
444 Views
Last post April 20, 2019, 12:49:06 AM
by Spyke
clip
Smooth histogram coloring failure

Started by Smolt on Programming

3 Replies
148 Views
Last post August 23, 2019, 03:47:41 AM
by Duncan C
clip
Exporting smooth mesh

Started by meshcarver on Mandelbulb3d

17 Replies
656 Views
Last post September 23, 2019, 01:17:09 AM
by thargor6
xx
A Smooth Exit from Eternal Inflation?

Started by F. Bernkastel on Physics

3 Replies
646 Views
Last post November 07, 2018, 05:42:39 PM
by Alef
xx
How to implement Smooth Histogram Rendering?

Started by Iluso on Programming

6 Replies
251 Views
Last post January 18, 2019, 10:31:30 PM
by FractalDave