雙線性插值法影象放縮示例
阿新 • • 發佈:2019-02-11
演算法原理簡介
雙線性插值是一階插值,常用於影象的旋轉、縮放處理。
它利用原圖中對應的四個點的畫素值來確定目標影象中的畫素值。
為了便於理解,我們來看兩張尺寸不一樣的圖片:
原圖
變換圖
假設原圖圖片的寬度為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圖片