1. 程式人生 > >雙線性插值法影象放縮示例

雙線性插值法影象放縮示例

演算法原理簡介

雙線性插值是一階插值,常用於影象的旋轉、縮放處理。

它利用原圖中對應的四個點的畫素值來確定目標影象中的畫素值。

為了便於理解,我們來看兩張尺寸不一樣的圖片:

原圖

變換圖

假設原圖圖片的寬度為yw,高度為xh

變換圖的寬度為jw,高度為ih

於是對於變換圖中任意一個畫素點(j’, i’)我們可以用以下的方法對映到原圖中去:

y' = yw/jw * j'
x' = xh/ih * i'

通常情況下,y’和x’不為整數。

例如,原圖尺寸:

yw = 1000
xh = 800

變換圖尺寸:

jw = 700
ih = 700

對於變換圖中的(400, 400)畫素點:

y' = 1000/700 * 400 = 571.42857
x' = 800/700 * 400 = 457.14286

我們將變換圖中的(400, 400)畫素點對映到原圖中的(571.42857, 457.14286)。

於是我們就用原圖中對應的4點(571,457),(572,457),(571,458),(572,458)來確定變換影象中的(400,400)點畫素值。

t = 571.42857 - 571 = 0.42857
u = 457.14286 - 457 = 0.14286

我們認為距離(y’, x’)點距離越近,其對目標畫素影響的權重應該越大,距離越遠,影響權重越小。

(571,457)點權重為s4面積,(572,457)點權重為s3面積,(571,458)點權重為s2面積,(572,458)點權重為s1面積。

於是我們得到:

(400,400)目標圖 = (571,457)xs4 + (572,457)xs3 + (571,458)xs2 + (572,458)xs1

其中,s1+s2+s3+s4 = 1

以上就是雙線性插值法目標畫素計算公式。

演算法的c程式碼實現

/*
 * param: 
 * Mat src 原始圖片
 * Mat dst 目標圖片
 */
void BGRBilinearScale(const Mat src, Mat dst) {

    double dstH = dst.rows;  //目標圖片高度
    double dstW = dst.cols;  //目標圖片寬度
double srcW = src.cols; //原始圖片寬度,如果用int可能會導致(srcH - 1)/(dstH - 1)恆為零 double srcH = src.rows; //原始圖片高度 double xm = 0; //對映的x double ym = 0; //對映的y int xi = 0; //對映x整數部分 int yi = 0; //對映y整數部分 int xl = 0; //xi + 1 int yl = 0; //yi + 1 double xs = 0; double ys = 0; /* 為目標圖片每個畫素點賦值 */ for(int i = 0; i < dstH; i ++) { for(int j = 0; j < dstW; j ++) { //求出目標影象(i,j)點到原影象中的對映座標(mapx,mapy) xm = (srcH - 1)/(dstH - 1) * i; ym = (srcW - 1)/(dstW - 1) * j; /* 取對映到原圖的xm的整數部分 */ xi = (int)xm; yi = (int)ym; /* 取偏移量 */ xs = xm - xi; ys = ym - yi; xl = xi + 1; yl = yi + 1; //邊緣點 if((xi+1) > (srcH-1)) xl = xi-1; if((yi+1) > (srcW-1)) yl = yi-1; //b dst.at<Vec3b>(i,j)[0] = (int)(src.at<Vec3b>(xi,yi)[0]*(1-xs)*(1-ys) + src.at<Vec3b>(xi,yl)[0]*(1-xs)*ys + src.at<Vec3b>(xl,yi)[0]*xs*(1-ys) + src.at<Vec3b>(xl,yl)[0]*xs*ys); //g dst.at<Vec3b>(i,j)[1] = (int)(src.at<Vec3b>(xi,yi)[1]*(1-xs)*(1-ys) + src.at<Vec3b>(xi,yl)[1]*(1-xs)*ys + src.at<Vec3b>(xl,yi)[1]*xs*(1-ys) + src.at<Vec3b>(xl,yl)[1]*xs*ys); //r dst.at<Vec3b>(i,j)[2] = (int)(src.at<Vec3b>(xi,yi)[2]*(1-xs)*(1-ys) + src.at<Vec3b>(xi,yl)[2]*(1-xs)*ys + src.at<Vec3b>(xl,yi)[2]*xs*(1-ys) + src.at<Vec3b>(xl,yl)[2]*xs*ys); } } }

放縮效果預覽

原圖為1024 x 640圖片,變換目標圖片為800 x 800圖片

原圖

目標圖