溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

基于Python如何實(shí)現(xiàn)二維圖像雙線性插值

發(fā)布時(shí)間:2022-06-13 10:06:38 來(lái)源:億速云 閱讀:241 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容主要講解“基于Python如何實(shí)現(xiàn)二維圖像雙線性插值”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“基于Python如何實(shí)現(xiàn)二維圖像雙線性插值”吧!

    在對(duì)二維數(shù)據(jù)進(jìn)行 resize / mapping / 坐標(biāo)轉(zhuǎn)換等操作時(shí),經(jīng)常會(huì)將原本的整數(shù)坐標(biāo)變換為小數(shù)坐標(biāo),對(duì)于非整數(shù)的坐標(biāo)值一種直觀有效的插值方式為雙線性插值。

    插值簡(jiǎn)介

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

    雙線性插值作為數(shù)值分析中的一種插值算法,廣泛應(yīng)用在信號(hào)處理,數(shù)字圖像和視頻處理等方面。

    假設(shè)我們出現(xiàn)了需要在四個(gè)相鄰正方形整數(shù)點(diǎn)(A,B,C,D)坐標(biāo)中間(正方形范圍內(nèi))選擇一個(gè)點(diǎn)(a,b)取近似值的情形。

    此時(shí)我們已知的是四個(gè)點(diǎn)的數(shù)值VA,VB,VC,VD,給定小數(shù)坐標(biāo)E(a,b),0≤a,b≤1,如何插值求解E點(diǎn)的數(shù)值呢,解決類似問(wèn)題的方法統(tǒng)稱為插值,上圖展示公式為雙線性插值的計(jì)算方法。

    最近鄰法 (Nearest Interpolation)

    一種最簡(jiǎn)便的方法為最近鄰法,直接取與當(dāng)前點(diǎn)距離最近的點(diǎn)的值作為插值結(jié)果:

    基于Python如何實(shí)現(xiàn)二維圖像雙線性插值

    其中 roundroundround 為四舍五入的取整操作,方法簡(jiǎn)便速度極快,但往往不夠精細(xì)

    雙三次插值 (Bicubic interpolation)

    雙三次插值是用原圖像中16(4*4)個(gè)點(diǎn)計(jì)算新圖像中1個(gè)點(diǎn),效果比較好,但是計(jì)算代價(jià)過(guò)大。

    雙線性插值 (Bilinear Interpolation)

    使用一個(gè)點(diǎn)進(jìn)行插值過(guò)于粗暴,16個(gè)點(diǎn)又過(guò)于繁瑣,那就使用EEE點(diǎn)周圍4個(gè)點(diǎn)的數(shù)值來(lái)近似求解,這是一種平衡了計(jì)算代價(jià)和插值效果的折中方案,也是各大變換庫(kù)的默認(rèn)插值操作。

    雙線性插值

    通過(guò)觀察上述動(dòng)圖(可以動(dòng)手挪一挪)可以清晰地看到,雙線性插值本質(zhì)就是把四個(gè)角落的數(shù)值按照正方形面積的比例線性加權(quán)后的結(jié)果。

    好吧一句話已經(jīng)把數(shù)學(xué)的核心部分講完了

    那么既然理解了本質(zhì),數(shù)學(xué)公式就好寫了:

    基于Python如何實(shí)現(xiàn)二維圖像雙線性插值

    python實(shí)現(xiàn)

    在實(shí)現(xiàn)時(shí)當(dāng)然 for 循環(huán)大法可以解決一切問(wèn)題,但總歸是不太優(yōu)雅,我們嘗試使用 numpy 操作完成雙線性插值

    假設(shè)原始圖像 image,變換后的小數(shù)坐標(biāo) X 矩陣 x_grid,Y 矩陣 y_grid,那么可以使用如下的 bilinear_by_meshgrid 函數(shù)快速雙線性插值,已經(jīng)處理好了邊界,可以放心使用。

    def bilinear_by_meshgrid(image, x_grid, y_grid):
    
        #               Ia, Wd                          Ic, Wb
        #           (floor_x, floor_y)              (ceil_x, floor_y)   
        #
        #                               (x, y)
        #
        #               Ib , Wc                         Id, Wa
        #           (floor_x, ceil_y)               (ceil_x, ceil_y)   
        #
    
        assert image.shape == x_grid.shape == y_grid.shape
        assert image.ndim == 2
        H, W = image.shape[:2]
    
        floor_x_grid = np.floor(x_grid).astype('int32')
        floor_y_grid = np.floor(y_grid).astype('int32')
        ceil_x_grid = floor_x_grid + 1
        ceil_y_grid = floor_y_grid + 1
    
        if np.max(ceil_x_grid) > W -1 or  np.max(ceil_y_grid) > H -1 or np.min(floor_x_grid) < 0 or np.min(floor_y_grid) < 0:
            print("Warning: index value out of original matrix, a crop operation will be applied.")
    
            floor_x_grid = np.clip(floor_x_grid, 0, W-1).astype('int32')
            ceil_x_grid = np.clip(ceil_x_grid, 0, W-1).astype('int32')
            floor_y_grid = np.clip(floor_y_grid, 0, H-1).astype('int32')
            ceil_y_grid = np.clip(ceil_y_grid, 0, H-1).astype('int32')
    
        Ia = image[ floor_y_grid, floor_x_grid ]
        Ib = image[ ceil_y_grid, floor_x_grid ]
        Ic = image[ floor_y_grid, ceil_x_grid ]
        Id = image[ ceil_y_grid, ceil_x_grid ]
    
        wa = (ceil_x_grid - x_grid) * (ceil_y_grid - y_grid)
        wb = (ceil_x_grid - x_grid) * (y_grid - floor_y_grid)
        wc = (x_grid - floor_x_grid) * (ceil_y_grid - y_grid)
        wd = (x_grid - floor_x_grid) * (y_grid - floor_y_grid)
    
        assert np.min(wa) >=0 and np.min(wb) >=0 and np.min(wc) >=0 and np.min(wd) >=0
        
        W = wa + wb + wc + wd
        assert np.sum(W[:, -1]) + np.sum(W[-1, :]) == 0
        
        wa[:-1, -1] = ceil_y_grid[:-1, -1] - y_grid[:-1, -1]
        wb[:-1, -1] = y_grid[:-1, -1] - floor_y_grid[:-1, -1]
        
        wb[-1, :-1] = ceil_x_grid[-1, :-1] - x_grid[-1, :-1]
        wd[-1, :-1] = x_grid[-1, :-1] - floor_x_grid[-1, :-1]
        
        wd[-1, -1] = 1
        
        W = wa + wb + wc + wd
        assert np.max(W) == np.min(W) == 1
        
        res_image = wa*Ia + wb*Ib + wc*Ic + wd*Id
    
        return res_image

    該函數(shù)集成在我自己的python庫(kù) mtutils 中,可以通過(guò):

    pip install mtutils

    直接安裝,之后可以直接引用:

    from mtutils import bilinear_by_meshgrid

    到此,相信大家對(duì)“基于Python如何實(shí)現(xiàn)二維圖像雙線性插值”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI