1. 程式人生 > >雙線性插值 - c#實現

雙線性插值 - c#實現

1.雙線性插值 

線性插值是遊戲Unity開發過程中非常常用的演算法,在Unity中直接使用 lerp函式就可以實現。但對於雙線性插值,Unity並沒有給出可以直接使用了API,下面會給出一個利用C#對二維陣列進行雙線性插值的演算法。

下圖是雙線性插值的示意圖(圖片取自維基百科英文頁),對於一個正方形的區域,已知四個頂點的值,我們希望通過這四個值獲取正方形區域某一位置的值,就要用到雙線性插值。我們對四個點取權值,我們假設整個正方形區域的面積為1,求點(x,y)的值就可以把這一個塊面積分成四個,每塊區域的面積佔總面的比例就是其對應頂點的權值,比如右上角的頂點所佔的權值就是黃色區域面積佔總面積的比例。

 2.c#實現

這裡傳入一個原始陣列以及目標陣列的第一維和第二維的長度,返回目標陣列。

    public static float[,] BilinearInterp(float[,] array, int length_0, int length_1)
    {
        float[,] _out = new float[length_0, length_1];
        int original_0 = array.GetLength(0);
        int original_1 = array.GetLength(1);

        float ReScale_0 = original_0 / ((float)length_0);  // 倍數的倒數
        float ReScale_1 = original_1 / ((float)length_1);

        float index_0;
        float index_1;
        int inde_0;
        int inde_1;
        float s_leftUp;
        float s_rightUp;
        float s_rightDown;
        float s_leftDown;

        for (int i = 0; i < length_0; i++)
        {
            for (int j = 0; j < length_1; j++)
            {
                index_0 = i * ReScale_0;
                index_1 = j * ReScale_1;
                inde_0 = Mathf.FloorToInt(index_0);
                inde_1 = Mathf.FloorToInt(index_1);
                s_leftUp = (index_0 - inde_0) * (index_1 - inde_1);
                s_rightUp = (inde_0 + 1 - index_0) * (index_1 - inde_1);
                s_rightDown = (inde_0 + 1 - index_0) * (inde_1 + 1 - index_1);
                s_leftDown = (index_0 - inde_0) * (inde_1 + 1 - index_1);
                _out[i, j] = array[inde_0, inde_1] * s_rightDown + array[inde_0 + 1, inde_1] * s_leftDown + array[inde_0 + 1, inde_1 + 1] * s_leftUp + array[inde_0, inde_1 + 1] * s_rightUp;
            }
        }

        return _out;
    }