欧美日韩在线第一页-欧美日韩在线观看精品-欧美日韩在线观看一区二区-欧美日韩在线免费看-欧美日韩在线视频不卡一区二区三区

圖像處理
新聞詳情

常見圖像插值算法的原理與C++實現

發布時間:2021-03-25 09:33:52 最后更新:2021-03-25 10:11:37 瀏覽次數:4821

講插值之前,首先講像素重采樣的概念。假設有圖像A和圖像B,其中A為源圖像,B為目標圖像,A與B的坐標具有對應關系f:

(xa, ya)=f(xb, yb)

通過關系f,把A的像素值賦值給B中對應像素點的過程,叫做圖像A的像素重采樣,圖像B為重采樣之后的圖像。比如對于B的任意像素點(x, y),其對應的A的像素點為(x', y'),那么則把A中點(x', y')的像素值A(x', y')賦值給B中點(x, y)的像素值B(x, y)。

(x‘, y’)=f(x, y)

B(x, y)=A(x', y')

像素重采樣的常見應用場景為圖像縮放和圖像配準。在實際應用過程中,源圖像A的對應坐標往往不是整數,而是浮點型數據(如下圖所示),因此不能直接取其像素值賦值給目標圖像上的對應點。此時要獲取點A(x', y')的像素值,插值算法就派上用場了。


所謂插值,就是使用浮點型坐標點的周圍整型點的像素值來計算該浮點型坐標點的像素值。比如上圖中,點(x', y')為浮點型坐標點,使用其周圍整型點p0、p1、p2、p3的像素值來計算其像素值A(x', y'),這個過程就是插值。

常見的插值算法有最鄰近插值、雙線性插值、雙三次插值,不管什么插值算法,其本質都是取浮點型坐標點周圍的n*n個整型坐標點的像素值進行加權和,從而得到該浮點型坐標點的像素值,如下式:


不同插值算法的區別在于權重W的計算不一樣,下文將分別詳細講解最鄰近插值、雙線性插值、雙三次插值的計算原理與實現。

1. 最鄰近插值

最鄰近插值取離浮點型坐標點的最近點的像素值作為其像素值,也可以看成使用浮點型坐標點周圍2*2個整型點的像素值來計算其像素值,不過只有最靠近的那個點權重為1,其余3個點權重系數都為0。


插值的計算如下式:


其權重計算如下式:


最鄰近插值的代碼實現最簡單,直接對浮點型坐標進行四舍五入取整即可,假設浮點坐標為(x_float, y_float),那么使用最鄰近插值計算A(x_float, y_float)的代碼實現如下:

int x = (int)(x_float + 0.5);  //加0.5再截斷取整,與四舍五入取整等效
int y = (int)(y_float + 0.5);
uchar inner_value = A.ptr(y)[x];  //A(x',y')=A(x,y)


2. 雙線性插值

雙線性插值與最鄰近插值類似,同樣使用浮點型坐標點周圍2*2個整型點的像素值來計算其像素值,不過其周圍每個整型點的權重都不為0,也就是說,其權重計算與最鄰近插值不一樣:


浮點坐標點(x_float, y_float)雙線性插值的代碼實現如下:

int x0 = floor(x_float);
int x1 = x0 + 1;
int y0 = floor(y_float);
int y1 = y0 + 1;


float fracRow = y_float - y0;  //求浮點坐標的小數部分
float fracCol = x_float - x0;


float k0 = 1.0 - fracRow;
float k1 = 1.0 - fracCol;
float w0 = k0*k1;
float w1 = fracRow*k1;
float w2 = k0*fracCol;
float w3 = fracRow*fracCol;


uchar inner_value = (uchar)(w0 * A.ptr(y0)[x0] + w1 * A.ptr(y1)[x0] + w2 * A.ptr(y0)[x1] + w3 * A.ptr(y1)[x1]);


3. 雙三次插值

雙三次插值使用浮點型坐標點周圍4*4個整型點的像素值來計算其像素值,如下圖所示:


浮點型坐標點的插值為其周圍4*4整型坐標點像素值的加權和:


其中權重W(i,j)的計算如下式,其中a取值范圍-1~0之間,一般取固定值-0.5。




雙三次插值的實現代碼如下。

首先是權重函數的實現:

float cubic_coeff(float x, float a)
{
    if(x <= 1)
    {
        return 1-(a+3)*x*x+(a+2)*x*x*x;
    }
    else if(x < 2)
    {
        return -4*a+8*a*x-5*a*x*x+a*x*x*x;
    }
    return 0.0;
}


接著是權重系數的計算實現:

void cal_cubic_coeff(float x, float y, float *coeff)
{
    /*calc the coeff*/
    float u = x - floor(x);
    float v = y - floor(y);
    
    u += 1;
    v += 1;
    float a = -0.15;
    float a_mul_4 = (a + a) + (a + a);
    float a_mul_5 = a_mul_4 + a;
    float a_mul_8 = a_mul_4 + a_mul_4;
    float a_add_3 = a + 3;
    float a_add_2 = a + 2;


    float A[4];
    A[0] = cubic_coeff(abs(u), a); 
    A[1] = cubic_coeff(abs(u-1), a); 
    A[2] = cubic_coeff(abs(u-2), a); 
    A[3] = cubic_coeff(abs(u-3), a); 


    for (int s = 0; s < 4; s++)    
    {
      float C = cubic_coeff(abs(v-s), a);
      coeff[s*4] = A[0]*C;
      coeff[s*4+1] = A[1]*C;
      coeff[s*4+2] = A[2]*C;
      coeff[s*4+3] = A[3]*C;
    }
}


最后,是雙三次插值代碼:

uchar cubic_inner(Mat A, float x_float, float y_float, float a)
{
   float coeff[16];
   cal_cubic_coeff(x_float, y_float, coeff);  //計算權重系數
   
   float sum = 0.0;
   int x0 = floor(x_float) - 1;
   int y0 = floor(y_float) - 1;
   
   for(int i = 0; i < 4; i++)
   {
      for(int j = 0; j < 4; j++)
      {
           sum += coeff[i*4+j]*A.ptr(y0+i)[x0+j];
      }
   }
   
   uchar inner_value = (uchar)sum;
   return inner_value;
}


從插值效果來說:雙三次插值>雙線性插值>最鄰近插值,從計算復雜度來說,同樣是:雙三次插值>雙線性插值>最鄰近插值。所以實際使用時,根據自己的需要選擇合適的插值算法。


如涉及侵權,請相關權利人與我司聯系刪除

在線客服 雙翌客服
客服電話
  • 0755-23712116
  • 13310869691
主站蜘蛛池模板: 美国黄色a级片| 亚洲国产精品久久卡一| 亚洲a级片在线观看| 久久yy| 亚洲毛片在线播放| 精品亚洲综合在线第一区| 精品久久久久久亚洲| 国产又黄又爽又色视频免费观看| 免费一级特黄特色大片∵黄| 日韩色爱| 2021久久精品国产99国产精品| 日韩欧美一区在线观看| aⅴ在线免费观看| 国产欧美日韩在线观看精品| 国产一毛片| 国产精品自在线| 亚洲国产精品一区二区第一页| www.国产精品.com| 久久婷婷激情| 国模精品视频一区二区三区| 色吊丝永久性观看网站大全| 三级免费毛片| 九九精品视频在线| 国产精品嫩草影院人体模特| 成人久久久久久| 一区二区亚洲精品| 草草网站| 免费黄色资源| 亚洲国产精品a一区二区三区| a毛片在线观看| 国产精品久久久久激情影院| 国产在线一区二区视频| 日本久久久久久久中文字幕| 欧美日韩一区二区三区自拍| 特级aa一级欧美毛片| 亚洲国产精品区| 日韩亚洲欧美综合| 国产精品久久久久久久久齐齐| 中国一级簧色| 久久婷婷综合中文字幕| 国产三级a三级三级天天|