Pierwszą z sekwencji jest sekwencja Van Der Corput'a. Parametrem do generacji serii punktów jest
Base - podstawa systemu liczbowego dla której będzie generowana sekwencja, czyli powinna być większa od 1 (2 dla binarnego, 10 dla dziesiętnego). Sekwencja wielowymiarowe, których bazy są liczbami relatywnie pierwszymi dla siebie to sekwencja Haltona.
Parametrem do generacji poszczególnych liczb w sekwencji jest $n \in {1,2,3,4,...}$. Dla sekwencji wielowymiarowych dla każdego wymiaru powinniśmy użyć inną bazę by uniknąć degradacji. Poza tym by uniknąć degradacji bazy sekwencji wielowymiarowych nie powinny mieć wspólnych podzielników - powinny być liczbami relatywnie pierwszymi (coprime).
Generowanie sekwencji opisowo wygląda tak. Weźmy kolejną liczbę dodatnią
N. Potraktujmy ją jako liczbę w systemie o zadanej bazie $abcd_{BASE}$. Odpowiednik w sekwencji ma postać: $\frac{d}{BASE}+\frac{c}{BASE^2}+\frac{b}{BASE^3}+\frac{a}{BASE^4}$. Np. dla systemu dziesiętnego: $214 \rightarrow 0.412$.Kod:
public static class LowDiscrepancyMath
{
public static double RadicalInverse(int a_n, int a_base)
{
double y = 0;
double b = a_base;
while (a_n > 0)
{
int d_i = a_n % a_base;
y += d_i / b;
a_n /= a_base;
b *= a_base;
}
return y;
}
}
public abstract class LowDiscrepancySequenceSampler : NonUniformSampler
{
public int Subresolution = 3;
public override IEnumerable<Vector2> GetSamples(Rectangle a_rect)
{
int samples_x = a_rect.Width * Subresolution;
int samples_y = a_rect.Height * Subresolution;
for (int y = 0; y < samples_y; y++)
{
for (int x = 0; x < samples_x; x++)
{
Vector2 sample = NextSample();
yield return new Vector2(
a_rect.Left + sample.X * a_rect.Width,
a_rect.Top + sample.Y * a_rect.Height);
}
}
}
protected abstract Vector2 NextSample();
}
public class HaltonSampler : LowDiscrepancySequenceSampler
{
protected int m_n = 1;
public int BaseX = 2;
public int BaseY = 3;
protected override Vector2 NextSample()
{
int n = m_n;
m_n++;
return new Vector2(
LowDiscrepancyMath.RadicalInverse(n, BaseX),
LowDiscrepancyMath.RadicalInverse(n, BaseY));
}
public override SamplerType SamplerType
{
get
{
return SamplerType.Halton;
}
}
}
Przykłady sekwencji:
(2,3)

(2,4)

(2,5)

Poniższy przykład zakłada sekwencję, w której na każdy piksel przypada jedna próbka. W przypadku samplowania typu Grid byłby to biały prostokąt. Tutaj możemy zauważyć jak dla tej sekwencji co pewną ilość punktów następuje duża zmiana w rozkładzie próbek utrzymująca się przez pewien czas.

Periodogram dla (2,3):

Widać na nim pewną powtarzalność i tym samym podatność na aliasing.
Brak komentarzy:
Prześlij komentarz