jitter for Moire reduction

  • 1 Replies
  • 279 Views

0 Members and 1 Guest are viewing this topic.

Offline claude

  • *
  • Fractal Frankfurter
  • *
  • Posts: 589
    • mathr.co.uk
« on: February 12, 2018, 09:05:02 PM »
A uniform grid is known to produce Moire patterns from the interaction of thin near-parallel lines with the regularly spaced sampling points.  See attached image uniform.png.

I tried to jitter the sampling points at pseudo-random using Pippin's a_dither algorithm: http://pippin.gimp.org/a_dither/  However results were not much of an improvement, see attached a_dither.png

Finally I tried the Wang integer hash algorithm for jittering the sampling points: http://www.burtleburtle.net/bob/hash/integer.html  Results were very satisfactory, see attached wang_hash.png

Code: [Select]
uint32_t wang_hash(uint32_t a)
{
    a = (a ^ 61) ^ (a >> 16);
    a = a + (a << 3);
    a = a ^ (a >> 4);
    a = a * 0x27d4eb2d;
    a = a ^ (a >> 15);
    return a;
}

double dither(uint32_t x, uint32_t y, uint32_t c)
{
  return wang_hash(c + wang_hash(y + wang_hash(x))) / (double) (0x100000000LL) - 0.5;
}

I used it something like this:
Code: [Select]
real_x = x0 + pixel_spacing * dither(pixel_x, pixel_y, 0);
real_y = y0 + pixel_spacing * dither(pixel_x, pixel_y, 1);

For rotation/skewing/etc of escape time fractals, it's easier to jitter the integer pixel_x, pixel_y by +/- 0.5 pixel before transforming to the desired C plane.

I didn't want to use rand() or some other pseudo-random number generator, due to threading and non-determinism issues - better for my purposes to have it depend on pixel coordinates and (eventually) subframe index.
« Last Edit: March 14, 2018, 10:05:23 PM by claude, Reason: fix broken ? e »

Offline claude

  • *
  • Fractal Frankfurter
  • *
  • Posts: 589
    • mathr.co.uk
« Reply #1 on: February 20, 2018, 07:48:32 AM »
With the "- 0.5" removed from the dither function above, and renamed to uniform_dither, gaussian_dither can be implemented with Box-Muller transform https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform :
Code: [Select]
gaussian_dither(uint32_t i, uint32_t j, uint32_t c, double &x, double &y)
{
  double u = uniform_dither(i, j, 2 * c + 0);
  double v = uniform_dither(i, j, 2 * c + 1);
  double r = u ? sqrt(-2 * log(u)) : 0;
  double t = 2 * 3.141592653589793 * v;
  x = r * cos(t);
  y = r * sin(t);
}

c should be different for different subframes that will be stacked to form the final image.

Note: the rejection-sampling methods for Gaussian generation are not appropriate here, we can't generate more uniform samples without more deterministic inputs.

EDIT using a Gaussian for jitter is probably a mistake, as it "biases towards the center of the pixel" as pointed out by gerrit.
« Last Edit: March 14, 2018, 11:15:03 PM by claude, Reason: bad Gauss no biscuit »


xx
Gaussian jitter for Moire reduction

Started by claude on Kalles Fraktaler

90 Replies
1317 Views
Last post March 27, 2018, 06:23:12 AM
by claude
xx
kf jitter test (uniform jitter, 6 layers)

Started by claude on Fractal Image Gallery

0 Replies
48 Views
Last post February 20, 2018, 06:10:07 AM
by claude
xx
kf jitter test (gaussian jitter, 6 layers)

Started by claude on Fractal Image Gallery

0 Replies
55 Views
Last post February 20, 2018, 06:27:44 AM
by claude
xx
kf jitter test (uniform jitter)

Started by claude on Fractal Image Gallery

0 Replies
78 Views
Last post February 20, 2018, 06:08:31 AM
by claude
xx
kf jitter test (gaussian jitter)

Started by claude on Fractal Image Gallery

2 Replies
65 Views
Last post February 20, 2018, 07:56:31 AM
by claude