<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          三種圖像插值方式對(duì)比

          共 465字,需瀏覽 1分鐘

           ·

          2021-11-09 09:50

          點(diǎn)擊下方卡片,關(guān)注“新機(jī)器視覺(jué)”公眾號(hào)

          視覺(jué)/圖像重磅干貨,第一時(shí)間送達(dá)

          來(lái)源:字節(jié)流動(dòng)

          在播放視頻時(shí),常遇到視頻尺寸與畫布尺寸不一致的情況。為了讓視頻按比例填充畫布,需要對(duì)視頻中的每一幀圖像做縮放處理。


          縮放就是在原圖的基礎(chǔ)上做插值計(jì)算,從而增加或減少像素點(diǎn)的數(shù)量。常見(jiàn)的插值方式有最近點(diǎn)插值,線性插值,蘭索斯插值


          下面簡(jiǎn)要介紹,并對(duì)比三種插值方式的結(jié)果。


          最近點(diǎn)插值


          在一維空間中,最近點(diǎn)插值就相當(dāng)于四舍五入取整。在二維圖像中,像素點(diǎn)的坐標(biāo)都是整數(shù),該方法就是選取離目標(biāo)點(diǎn)最近的點(diǎn)。計(jì)算方式如下:


          假設(shè)原圖為A[aw,ah],寬度為aw,高度為ah。目標(biāo)圖為B[bw,bh],寬度為bw,高度為bh。已知A[aw,ah]的寬度,高度及其中每個(gè)點(diǎn)的顏色值,B[bw,bh]中每個(gè)點(diǎn)像素值的計(jì)算方式如下:


          for(int i=0; i<bh; ++i){
          for(int j=0; j<bw; ++j){
          int posX = floor(j/(float)bw * aw + 0.5f);
          int posY = floor(i/(float)bh * ah + 0.5f);
          B[i,j] = A[posY, posX];
          }
          }

          最近點(diǎn)插值


          線性插值


          線性插值是以距離為權(quán)重的一種插值方式。在一維空間中,假設(shè)有點(diǎn)A,B,其距離為L(zhǎng)AB。A,B之間任意一點(diǎn)C的值為A*LBC/LAB+B*LAC/LAB。在二維空間中,需要在兩個(gè)方向上做插值。如下圖所示:


          線性插值


          已知Q11,Q21,Q12,Q22,計(jì)算P點(diǎn)的值時(shí),需要先由Q11和Q21插值得到R1,由Q12和Q22插值得到R2,再由R1和R2插值得到P。


          詳情可參考:

          https://zh.wikipedia.org/wiki/%E5%8F%8C%E7%BA%BF%E6%80%A7%E6%8F%92%E5%80%BC

          該方法生成的圖像比較平滑,如下圖所示:


          線性插值


          蘭索斯插值(lanczos)


          一維的線性插值,是在目標(biāo)點(diǎn)的左邊和右邊各取一個(gè)點(diǎn)做插值,這兩個(gè)點(diǎn)的權(quán)重是由線性函數(shù)計(jì)算得到。而一維的蘭索斯插值是在目標(biāo)點(diǎn)的左邊和右邊各取四個(gè)點(diǎn)做插值,這八個(gè)點(diǎn)的權(quán)重是由高階函數(shù)計(jì)算得到


          詳細(xì)原理可查閱:

          https://en.wikipedia.org/wiki/Lanczos_resampling


          二維的蘭索斯插值在x,y方向分別對(duì)相鄰的八個(gè)點(diǎn)進(jìn)行插值,也就是計(jì)算加權(quán)和,所以它是一個(gè)8x8的描述子。


          網(wǎng)上目前可找到蘭索斯算法有兩份:GPUImage和OpenCV。其中GPUImage中是用GLSL實(shí)現(xiàn),其算法有誤,并不能得到正確的結(jié)果。OpenCV中是用C++實(shí)現(xiàn)的CPU端代碼。


          我參考OpenCV中的實(shí)現(xiàn)方式,實(shí)現(xiàn)了一份GPU上的蘭索斯插值算法,該算法在GPU上運(yùn)行,并不額外消耗CPU資源。其對(duì)應(yīng)的GLSL為


          uniform int ssize;
          uniform int tsize;
          uniform int flag;
          uniform float scale;
          uniform sampler2D inputImageTexture;
          void interpolateLanczos4(in float fx, inout float rate[8]) {
          const float s45 = 0.70710678118654752440084436210485;
          const float PI = 3.1415926535897932384626433832795;
          float cs[] = float[16]( ,1.0, 0.0, -s45, -s45, 0.0, 1.0, s45, -s45, -1.0, 0.0, s45, s45, 0.0, -1.0, -s45, s45);
          if( fx < 0.0000000001 ) {
          for( int i = 0; i < 8; i++ ) {
          rate[i] = 0.0;
          }
          rate[3] = 1.0;
          return;
          }
          float sum = 0.0;
          float y0 = -(fx+3.0)*PI*0.25;
          float s0 = sin(y0);
          float c0 = cos(y0);
          for(int i = 0; i < 8; i++ ) {
          float y = -(fx+float(3-i))*PI*0.25;
          int index = i*2;
          rate[i] = (cs[index]*s0 + cs[index+1]*c0) g (y*y);
          sum += rate[i];
          }
          sum = 1.0gsum;
          for(int i = 0; i < 8; i++ ) {
          rate[i] *= sum;
          }
          }
          void main() {
          vec4 fragmentColor = vec4(0);
          float curPos = float(tsize);
          if( flag == 0 ) {
          curPos = fragTexCoord.x * float(tsize);
          } else {
          curPos = fragTexCoord.y * float(tsize);
          }
          float fx = (curPos + 0.5) * scale - 0.5;
          float sx = floor(fx);
          fx -= sx;
          float rate[8];
          interpolateLanczos4(fx, rate);
          for (int i=0; i<8; ++i) {
          float newCoord = (sx + float(i - 3) ) / float(ssize);
          vec2 texCoord;
          if (flag == 0)
          texCoord = vec2(newCoord, fragTexCoord.y);
          else
          texCoord = vec2(fragTexCoord.x, newCoord);
          fragmentColor += texture2D(inputImageTexture, texCoord) * rate[i];
          }
          gl_FragColor = fragmentColor;
          }

          上述代碼需要執(zhí)行兩遍:

          第一遍的輸入為原圖,縮放寬度方向。ssize為原圖寬度,tsize為目標(biāo)圖寬度。執(zhí)行完畢后,把結(jié)果存到紋理中,作為第二遍的輸入;
          第二遍縮放高度方向,ssize為原圖高度,tsize為目標(biāo)圖高度。執(zhí)行完畢后,把結(jié)果顯示到屏幕上。

          結(jié)果對(duì)比


          以上三種方法的對(duì)比圖如下:


          對(duì)比圖1


          對(duì)比圖2


          將上面的對(duì)比圖放大后可以發(fā)現(xiàn),線性插值的結(jié)果較最近點(diǎn)插值更平滑,蘭索斯插值的結(jié)果較線性插值更清晰。


          性能對(duì)比


          運(yùn)行環(huán)境:iphone5s,ios8.3
          運(yùn)行程序:自研播放器demo


          以上三種插值算法渲染每幀圖像時(shí),占用CPU時(shí)間都是40ms左右。由于這三種算法都是在GPU上實(shí)現(xiàn),其對(duì)應(yīng)的CPU代碼相同,結(jié)果與預(yù)期相符。


          占用GPU時(shí)間如下所示:


          插值方式
          最近點(diǎn)插值線性插值蘭索斯插值
          每幀圖像平均占用的GPU時(shí)間(ms)6
          612


          蘭索斯插值算法占用GPU的平均時(shí)間為12ms,是其它兩種算法的兩倍,由于該算法中shader代碼執(zhí)行了兩遍,結(jié)果也與預(yù)期相符。


          由于GPU與CPU是異步執(zhí)行,大部分視頻幀率不超過(guò)30,因此GPU上多出的6ms不會(huì)造成性能瓶頸。


          注:GPUImage中的蘭索斯插值實(shí)現(xiàn)有誤,本文是參考OpenCV實(shí)現(xiàn)的。


          作者:梧桐光影
          鏈接:https://www.jianshu.com/p/8ae52a88ca61

          —版權(quán)聲明—

          僅用于學(xué)術(shù)分享,版權(quán)屬于原作者。

          若有侵權(quán),請(qǐng)聯(lián)系微信號(hào):yiyang-sy 刪除或修改!


          —THE END—
          瀏覽 55
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  婷婷五月综合久久中文字幕 | 婷婷丁香色 | 人人摸人人摸人人 | 亚洲一级视频在线 | 国产美女a级|