Kübik bir Lagrange enterpolasyon tensör ürünü bikubik enterpolasyon ile aynı mıdır?


11

Sadece en yakın 4x4 piksellerini örnekleyerek ve x ekseni boyunca Lagrange enterpolasyonu yaparak y ekseni üzerinde Lagrange enterpolasyonunu kullanmak için dört değer elde etmek için bazı enterpolasyonlu doku örneklemesi uyguladım.

Bu, bikubik enterpolasyon ile aynı mı yoksa farklı mı? Yoksa farklı türlerde bikubik enterpolasyon var mı, ve bu belki de onlardan biri mi?

Webgl Shadertoy uygulaması ve aşağıda ilgili GLSL (WebGL) kodu: https://www.shadertoy.com/view/MllSzX

Teşekkürler!

float c_textureSize = 64.0;

float c_onePixel = 1.0 / c_textureSize;
float c_twoPixels = 2.0 / c_textureSize;

float c_x0 = -1.0;
float c_x1 =  0.0;
float c_x2 =  1.0;
float c_x3 =  2.0;

//=======================================================================================
vec3 CubicLagrange (vec3 A, vec3 B, vec3 C, vec3 D, float t)
{
    return
        A * 
        (
            (t - c_x1) / (c_x0 - c_x1) * 
            (t - c_x2) / (c_x0 - c_x2) *
            (t - c_x3) / (c_x0 - c_x3)
        ) +
        B * 
        (
            (t - c_x0) / (c_x1 - c_x0) * 
            (t - c_x2) / (c_x1 - c_x2) *
            (t - c_x3) / (c_x1 - c_x3)
        ) +
        C * 
        (
            (t - c_x0) / (c_x2 - c_x0) * 
            (t - c_x1) / (c_x2 - c_x1) *
            (t - c_x3) / (c_x2 - c_x3)
        ) +       
        D * 
        (
            (t - c_x0) / (c_x3 - c_x0) * 
            (t - c_x1) / (c_x3 - c_x1) *
            (t - c_x2) / (c_x3 - c_x2)
        );
}

//=======================================================================================
vec3 BicubicTextureSample (vec2 P)
{
    vec2 pixel = P * c_textureSize + 0.5;

    vec2 frac = fract(pixel);
    pixel = floor(pixel) / c_textureSize - vec2(c_onePixel/2.0);

    vec3 C00 = texture2D(iChannel0, pixel + vec2(-c_onePixel ,-c_onePixel)).rgb;
    vec3 C10 = texture2D(iChannel0, pixel + vec2( 0.0        ,-c_onePixel)).rgb;
    vec3 C20 = texture2D(iChannel0, pixel + vec2( c_onePixel ,-c_onePixel)).rgb;
    vec3 C30 = texture2D(iChannel0, pixel + vec2( c_twoPixels,-c_onePixel)).rgb;

    vec3 C01 = texture2D(iChannel0, pixel + vec2(-c_onePixel , 0.0)).rgb;
    vec3 C11 = texture2D(iChannel0, pixel + vec2( 0.0        , 0.0)).rgb;
    vec3 C21 = texture2D(iChannel0, pixel + vec2( c_onePixel , 0.0)).rgb;
    vec3 C31 = texture2D(iChannel0, pixel + vec2( c_twoPixels, 0.0)).rgb;    

    vec3 C02 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_onePixel)).rgb;
    vec3 C12 = texture2D(iChannel0, pixel + vec2( 0.0        , c_onePixel)).rgb;
    vec3 C22 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_onePixel)).rgb;
    vec3 C32 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_onePixel)).rgb;    

    vec3 C03 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_twoPixels)).rgb;
    vec3 C13 = texture2D(iChannel0, pixel + vec2( 0.0        , c_twoPixels)).rgb;
    vec3 C23 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_twoPixels)).rgb;
    vec3 C33 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_twoPixels)).rgb;    

    vec3 CP0X = CubicLagrange(C00, C10, C20, C30, frac.x);
    vec3 CP1X = CubicLagrange(C01, C11, C21, C31, frac.x);
    vec3 CP2X = CubicLagrange(C02, C12, C22, C32, frac.x);
    vec3 CP3X = CubicLagrange(C03, C13, C23, C33, frac.x);

    return CubicLagrange(CP0X, CP1X, CP2X, CP3X, frac.y);
}

2
Bitrot durumunda ilgili gölgelendirici kodunu buraya gönderebilirsiniz, değil mi?
joojaa

1
gölgelendirici kodu için bazı güzel kod biçimlendirmesi olmalı, birisi beni dövmediyse meta yayınlayacağım!
Alan Wolfe

Sözdizimi vurgulamamızın kapsadığı diller listesinde belirli bir gölgelendirici dili yok mu?
trichoplax

Emin değilim. Sadece GLSL (webgl'den tam olarak!). Her kod satırından önce 4 boşluk yaptım, işaretlemenin daha iyi bir yolu olup olmadığından emin değilim ...
Alan Wolfe

Yanıtlar:


8

Bikubik doku örneklemesi için bikubik Lagrange enterpolasyonunu kullanabilmenize rağmen, en yüksek kalite seçeneği değildir ve muhtemelen kullanılması muhtemel değildir.

Kübik hermit splinelar iş için daha iyi bir araçtır.

Lagrange enterpolasyonu, veri noktalarından geçen ve böylece C0 sürekliliğini koruyan bir eğri oluşturacaktır, ancak hermite spline'lar veri noktalarından da geçerken kenarlardaki türevleri korur, böylece C1 sürekliliğini korur ve çok daha iyi görünür.

Bu sorunun kübik hermit spline hakkında bazı harika bilgileri var: /signals/18265/bicubic-interpolation

İşte soruya gönderdiğim kodun kübik hermite versiyonu:

//=======================================================================================
vec3 CubicHermite (vec3 A, vec3 B, vec3 C, vec3 D, float t)
{
    float t2 = t*t;
    float t3 = t*t*t;
    vec3 a = -A/2.0 + (3.0*B)/2.0 - (3.0*C)/2.0 + D/2.0;
    vec3 b = A - (5.0*B)/2.0 + 2.0*C - D / 2.0;
    vec3 c = -A/2.0 + C/2.0;
    vec3 d = B;

    return a*t3 + b*t2 + c*t + d;
}

//=======================================================================================
vec3 BicubicHermiteTextureSample (vec2 P)
{
    vec2 pixel = P * c_textureSize + 0.5;

    vec2 frac = fract(pixel);
    pixel = floor(pixel) / c_textureSize - vec2(c_onePixel/2.0);

    vec3 C00 = texture2D(iChannel0, pixel + vec2(-c_onePixel ,-c_onePixel)).rgb;
    vec3 C10 = texture2D(iChannel0, pixel + vec2( 0.0        ,-c_onePixel)).rgb;
    vec3 C20 = texture2D(iChannel0, pixel + vec2( c_onePixel ,-c_onePixel)).rgb;
    vec3 C30 = texture2D(iChannel0, pixel + vec2( c_twoPixels,-c_onePixel)).rgb;

    vec3 C01 = texture2D(iChannel0, pixel + vec2(-c_onePixel , 0.0)).rgb;
    vec3 C11 = texture2D(iChannel0, pixel + vec2( 0.0        , 0.0)).rgb;
    vec3 C21 = texture2D(iChannel0, pixel + vec2( c_onePixel , 0.0)).rgb;
    vec3 C31 = texture2D(iChannel0, pixel + vec2( c_twoPixels, 0.0)).rgb;    

    vec3 C02 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_onePixel)).rgb;
    vec3 C12 = texture2D(iChannel0, pixel + vec2( 0.0        , c_onePixel)).rgb;
    vec3 C22 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_onePixel)).rgb;
    vec3 C32 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_onePixel)).rgb;    

    vec3 C03 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_twoPixels)).rgb;
    vec3 C13 = texture2D(iChannel0, pixel + vec2( 0.0        , c_twoPixels)).rgb;
    vec3 C23 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_twoPixels)).rgb;
    vec3 C33 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_twoPixels)).rgb;    

    vec3 CP0X = CubicHermite(C00, C10, C20, C30, frac.x);
    vec3 CP1X = CubicHermite(C01, C11, C21, C31, frac.x);
    vec3 CP2X = CubicHermite(C02, C12, C22, C32, frac.x);
    vec3 CP3X = CubicHermite(C03, C13, C23, C33, frac.x);

    return CubicHermite(CP0X, CP1X, CP2X, CP3X, frac.y);
}

İşte örnekleme yöntemleri arasındaki farkı gösteren bir resim. Soldan sağa: En Yakın Komşu, Bilinear, Lagrange Bicubic, Hermite Bicubic

resim açıklamasını buraya girin


Tüm kübik spline'lar bir anlamda eşdeğer olsa da, Catmull-Rom spline'ları kullanmak muhtemelen kavramsal olarak daha kolaydır. ör. cs.cmu.edu/~462/projects/assn2/assn2/catmullRom.pdf
Simon F

Bu durumda tau parametresinin yardımcı veya engel olduğunu düşünüyor musunuz? Ben yanlış olabilir ama catmull rom çok "kullanıcı tanımlı" (ve ayarlanması gerekir) hissediyorum, oysa hermite spline sadece orada verilerden bilgi kullanmaya çalışır. Kübik hermit, ideal bir iç filtre gibi bir şey olacağını tahmin ediyorum bir "zemin gerçeğine" daha yakın gibi görünüyor. Ne düşünüyorsun?
Alan Wolfe

Catmull-Rom'un nasıl "kullanıcı tanımlı" olduğunu anlamıyorum. 4 bitişik noktadan oluşan bir sıraya sahip olduğunuzda, P [i-1], P [i], P [i + 1], P [i + 2] (2D kasa için 4x4) eğri segmenti P [i arasında tanımlanır ] ve P [i + 1] 'dir ve komşu segmentlerle C1 devamlıdır. Samimi bir filtre ses için iyidir, ancak video için değildir. Bkz. Mitchell ve Netravali: cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/… IIRC Catmull-Rom, önerdikleri filtre ailesinin özel bir durumudur, ancak filtrenin yaklaşık bir eğri olduğunu düşünüyorum, CR'nin aksine, orijinal noktalardan geçmeyebilir.
Simon F

Hermite spline, catmull rom spline'ın kullanıcı tanımlı ek bir parametre tau (gerginlik) içermesi dışında bu şekilde çalışır. Ayrıca, sinc video için geçerli, DSP DSP: P
Alan Wolfe

İtiraf etmeliyim ki, daha önce Catmull Rom spline'larıyla ilişkili bir gerilim parametresi görmedim, ama sonra onları sadece Foley & van Dam (ve ark.) Veya AFAICR'ın yaptığı Watt & Watt aracılığıyla öğrendim. bundan bahsetmiyorum. Aslında, dört kısıtlama olduğu göz önüne alındığında, yani eğri 2 noktadan geçmeli ve bu noktalarda iki tanjant ** olmalıdır ve bu bir kübiktir - Nasıl olduğu konusunda biraz kaybım var gerilim parametresini desteklemek için daha fazla serbestlik derecesi .... ** Teğetlerin ölçeklendirilebileceği anlamına gelmedikçe?
Simon F
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.