雙線性插值算法解析與實(shí)例

雙線性插值在圖像處理和gis分析中用到還比較多,整理下原理并寫(xiě)了個(gè)簡(jiǎn)單的示例

雙線性插值,又稱為雙線性內(nèi)插。在數(shù)學(xué)上,雙線性插值是有兩個(gè)變量的插值函數(shù)的線性插值,其核心思想是在兩個(gè)方向分別進(jìn)行一次線性插值。

線性插值

根據(jù)定義和名字,可以看出就是兩個(gè)方向的線性插值

線性插值法,是指使用連接兩個(gè)已知量的直線來(lái)確定在這兩個(gè)已知量之間的一個(gè)未知量的值的方法。


假設(shè)我們已知坐標(biāo)(x0,y0)與(x1,y1),要得到[x0,x1]區(qū)間內(nèi)某一位置x在直線上的值。根據(jù)圖中所示,我們得到兩點(diǎn)式直線方程:




可以理解為就是用x和x0,x1的距離作為一個(gè)權(quán)重,用于y0和y1的加權(quán)。

雙線性插值

假如我們想得到未知函數(shù)f在點(diǎn)P= (x,y) 的值,假設(shè)我們已知函數(shù)f在Q11 = (x1,y1)、Q12 = (x1,y2),Q21 = (x2,y1) 以及Q22 = (x2,y2) 四個(gè)點(diǎn)的值。



首先在x方向進(jìn)行線性插值,得到R1和R2,




然后在y方向進(jìn)行線性插值,得到P.

整合后的公式如下


示例

先上效果圖:



畫(huà)了4個(gè)canvas,利用四個(gè)角給定固定值(采用了隨機(jī)數(shù)),計(jì)算畫(huà)布內(nèi)的像素值
創(chuàng)建畫(huà)布

    createcanvas('c1', 0, 0);
    createcanvas('c2', 220, 0);
    createcanvas('c3', 0, 220);
    createcanvas('c4', 220, 220);

給定四個(gè)已知量

    var v1 = rn();
    var v2 = rn();
    var v3 = rn();
    var v4 = rn();

畫(huà)出第一個(gè)畫(huà)布的四個(gè)角,其他三個(gè)同樣操作

    createPixel('c1', 0, 0, v1);
    createPixel('c1', 190, 0, v2);
    createPixel('c1', 0, 190, v3);
    createPixel('c1', 190, 190, v4);

插值出第二個(gè)畫(huà)布的四個(gè)邊的中心點(diǎn)

    interpolate('c2', 0, 100);
    interpolate('c2', 100, 0);
    interpolate('c2', 100, 190);
    interpolate('c2', 190, 100);
    interpolate('c2', 100, 100);

第三個(gè)就是多畫(huà)了幾個(gè)點(diǎn),直接插值第四個(gè)的全部

    interpolateGrid('c4');

核心插值實(shí)現(xiàn)也比較簡(jiǎn)單,套公式即可,給出代碼

function createcanvas(id, x0, y0) {
      var canvas = document.createElement('canvas');
      canvas.id = id;
      canvas.setAttribute("width", 200);
      canvas.setAttribute("height", 200);
      canvas.style.position = 'absolute';
      canvas.style.top = x0 + 'px';
      canvas.style.left = y0 + 'px';
      document.body.appendChild(canvas);

      var ctx = canvas.getContext('2d');
      ctx.fillStyle = '#cccccc';
      ctx.fillRect(0, 0, 200, 200);
    }

    function createPixel(id, x, y, value) {
      var canvas = document.getElementById(id);
      var ctx = canvas.getContext('2d');
      var clrRed = value;
      ctx.fillStyle = "rgb(" + value + ",0,0)";;
      ctx.fillRect(x, y, 10, 10);
    }

    function rn() {
      return Math.round(Math.random() * 255);
    }

    function interpolate(id, x, y) {
      //多次線性插值
      // var rx1 = linear(0, v1, 200, v2, x);
      // var rx2 = linear(0, v3, 200, v4, x);
      // var ry = linear(0, rx1, 200, rx2, y);
      
      //直接雙線性插值
      var ry = bilinear(x, y, v1, v2, v3, v4);

      createPixel(id, x, y, ry);
    }

    function linear(x0, y0, x1, y1, x) {
      return (x1 - x) / (x1 - x0) * y0 + (x - x0) / (x1 - x0) * y1
    }

    function bilinear(x, y, g00, g10, g01, g11) { 
      var Δx = 200;
      var Δy = 200;
      var rx = Δx - x;
      var ry = Δy - y;
      var Δv = Δx * Δy
      var a = rx * ry,
        b = x * ry,
        c = rx * y,
        d = x * y;
      var u = g00 / Δv * a + g10 / Δv * b + g01 / Δv * c + g11 / Δv * d;
      return u;
    }

    function interpolateGrid(id) {
      for (let i = 0; i < 190; i++) {
        for (let j = 0; j < 190; j++) {
          interpolate(id, i, j)
        }
      }
    }

歡迎批評(píng)指正

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容