Là một sản phẩm tenxơ nội suy Lagrange giống như nội suy bicubic?


11

Tôi vừa thực hiện một số lấy mẫu kết cấu nội suy bằng cách lấy mẫu các pixel gần nhất 4 x 4 sau đó thực hiện phép nội suy Lagrange trên trục x để có bốn giá trị sử dụng phép nội suy Lagrange trên trục y.

Đây có phải giống như nội suy bicubic hay nó khác nhau? Hoặc có nhiều loại nội suy hai chiều khác nhau, và đây chỉ là một trong số chúng?

Triển khai Webgl Shadertoy tại đây và mã GLSL (WebGL) có liên quan bên dưới: https://www.shadertoy.com/view/MllSzX

Cảm ơn!

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
Bạn có thể đăng mã shader có liên quan ở đây trong trường hợp bitrot, không?
joojaa

1
chúng ta nên có một số đánh dấu mã đẹp hơn cho mã shader, tôi sẽ đăng lên meta nếu ai đó không đánh bại tôi với nó!
Alan Wolfe

Có phải đó là một ngôn ngữ đổ bóng cụ thể không có sẵn trong danh sách các ngôn ngữ được tô đậm bởi cú pháp tô sáng của chúng tôi?
trichoplax

Tôi không chắc. Đó chỉ là GLSL (chính xác là từ webgl!). Tôi chỉ thực hiện 4 khoảng trắng trước mỗi dòng mã, không chắc có cách nào tốt hơn để đánh dấu nó không ...
Alan Wolfe

Câu trả lời:


8

Hóa ra là không, trong khi bạn có thể sử dụng phép nội suy Lagrange hai chiều để lấy mẫu kết cấu hai chiều, thì đó không phải là tùy chọn chất lượng cao nhất và có lẽ không thực sự được sử dụng.

Splines hermite splines là một công cụ tốt hơn cho công việc.

Nội suy Lagrange sẽ tạo một đường cong đi qua các điểm dữ liệu, do đó bảo toàn tính liên tục của C0, nhưng các ẩn ẩn giữ các đạo hàm ở các cạnh trong khi cũng đi qua các điểm dữ liệu, do đó bảo toàn tính liên tục của C1 và nhìn tốt hơn nhiều.

Câu hỏi này có một số thông tin tuyệt vời về splines hermite khối: /signals/18265/bicubic-interpolation

Đây là phiên bản khối ẩn của mã tôi đã đăng trong câu hỏi:

//=======================================================================================
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);
}

Dưới đây là hình ảnh cho thấy sự khác biệt giữa các phương pháp lấy mẫu. Từ trái sang phải: Hàng xóm gần nhất, Bilinear, Lagrange bicubic, Hermite bicubic

nhập mô tả hình ảnh ở đây


Mặc dù tất cả các spline hình khối, theo một nghĩa nào đó, tương đương, nhưng về mặt khái niệm có thể dễ dàng hơn để sử dụng các spline Catmull-Rom. ví dụ: cs.cmu.edu/~462/projects/assn2/assn2/catmullRom.pdf
Simon F

Bạn có nghĩ rằng tham số tau giúp hoặc cản trở trong trường hợp này? Tôi có thể sai nhưng tôi cảm thấy như catmull rom quá "do người dùng định nghĩa" (và phải được điều chỉnh), trong khi spline ẩn sĩ cố gắng chỉ sử dụng thông tin từ dữ liệu ở đó. Có vẻ như hermite khối gần với một "sự thật mặt đất" hơn, mà tôi đoán sẽ giống như một bộ lọc chân thành lý tưởng. Bạn đang nghĩ gì qua?
Alan Wolfe

Tôi không thấy Catmull-Rom là "người dùng định nghĩa" như thế nào. Khi bạn có một chuỗi gồm 4 điểm tiếp giáp nhau, P [i - 1], P [i], P [i + 1], P [i + 2] (4 x 4 cho trường hợp 2D), đoạn đường cong được xác định giữa P [i ] và P [i + 1] và là C1 liên tục với các phân đoạn lân cận. Một bộ lọc chân thành là tốt cho âm thanh nhưng không phải video. Xem Mitchell & Netravali: cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/... IIRC Catmull-Rom là một trường hợp đặc biệt trong gia đình của các bộ lọc họ đề xuất, nhưng tôi nghĩ rằng bộ lọc đó là một đường cong Tạo xấp xỉ như vậy, Không giống như CR, có thể không đi qua các điểm ban đầu.
Simon F

Đó là cách anh ta ẩn náu spline hoạt động ngoại trừ việc spline catmull rom có ​​thêm một tham số tau (độ căng) do người dùng xác định. Ngoài ra, chân thành không áp dụng cho video, DSP là DSP: P
Alan Wolfe

Tôi phải thừa nhận, tôi chưa bao giờ thấy một tham số căng thẳng liên quan đến các spline Catmull Rom trước đây, nhưng sau đó tôi thực sự chỉ biết về chúng thông qua Foley & van Dam (et al) hoặc, nói, Watt & Watt, AFAICR, tạo ra không đề cập đến như vậy. Trên thực tế, đã nói rằng, có bốn ràng buộc - tức là đường cong phải đi qua 2 điểm và có hai tiếp tuyến xác định ** tại các điểm đó và đó là một hình khối - Tôi có một chút mất mát về cách có bất kỳ nhiều mức độ tự do hơn để hỗ trợ một tham số căng thẳng .... ** Trừ khi bạn có nghĩa là các tiếp tuyến có thể được thu nhỏ?
Simon F
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.