熱(re)線(xian)電話:0755-23712116
郵箱:contact@legoupos.cn
地址:深圳市寶(bao)安區沙井街道后亭(ting)茅洲山工(gong)業(ye)(ye)園(yuan)工(gong)業(ye)(ye)大廈(sha)全至科技創(chuang)新園(yuan)科創(chuang)大廈(sha)2層(ceng)2A
講插(cha)值之(zhi)前,首先講像(xiang)(xiang)素重采樣的(de)概念(nian)。假設(she)有圖(tu)(tu)像(xiang)(xiang)A和圖(tu)(tu)像(xiang)(xiang)B,其中A為源圖(tu)(tu)像(xiang)(xiang),B為目標圖(tu)(tu)像(xiang)(xiang),A與B的(de)坐標具有對應關系(xi)f:
(xa, ya)=f(xb, yb)
通(tong)過(guo)關系(xi)f,把(ba)A的(de)(de)(de)(de)像(xiang)(xiang)(xiang)素(su)值(zhi)(zhi)賦(fu)值(zhi)(zhi)給B中對應像(xiang)(xiang)(xiang)素(su)點(dian)的(de)(de)(de)(de)過(guo)程,叫做圖(tu)像(xiang)(xiang)(xiang)A的(de)(de)(de)(de)像(xiang)(xiang)(xiang)素(su)重(zhong)采(cai)樣(yang)(yang),圖(tu)像(xiang)(xiang)(xiang)B為(wei)重(zhong)采(cai)樣(yang)(yang)之(zhi)后的(de)(de)(de)(de)圖(tu)像(xiang)(xiang)(xiang)。比如對于(yu)B的(de)(de)(de)(de)任意像(xiang)(xiang)(xiang)素(su)點(dian)(x, y),其對應的(de)(de)(de)(de)A的(de)(de)(de)(de)像(xiang)(xiang)(xiang)素(su)點(dian)為(wei)(x', y'),那么則把(ba)A中點(dian)(x', y')的(de)(de)(de)(de)像(xiang)(xiang)(xiang)素(su)值(zhi)(zhi)A(x', y')賦(fu)值(zhi)(zhi)給B中點(dian)(x, y)的(de)(de)(de)(de)像(xiang)(xiang)(xiang)素(su)值(zhi)(zhi)B(x, y)。
(x‘, y’)=f(x, y)
B(x, y)=A(x', y')
像(xiang)素重采樣(yang)的(de)(de)常(chang)見(jian)應(ying)用(yong)場景為(wei)圖像(xiang)縮放和圖像(xiang)配準(zhun)。在實(shi)際應(ying)用(yong)過程(cheng)中,源圖像(xiang)A的(de)(de)對應(ying)坐標(biao)往(wang)往(wang)不是整數,而是浮點型數據(如下圖所(suo)示),因(yin)此(ci)不能直接取(qu)其像(xiang)素值(zhi)(zhi)賦值(zhi)(zhi)給目標(biao)圖像(xiang)上的(de)(de)對應(ying)點。此(ci)時要獲取(qu)點A(x', y')的(de)(de)像(xiang)素值(zhi)(zhi),插(cha)值(zhi)(zhi)算法就派上用(yong)場了(le)。
所謂插值(zhi),就(jiu)是使用浮點型(xing)(xing)坐標(biao)點的(de)周(zhou)圍整型(xing)(xing)點的(de)像(xiang)素值(zhi)來(lai)計(ji)(ji)算該浮點型(xing)(xing)坐標(biao)點的(de)像(xiang)素值(zhi)。比(bi)如上圖中,點(x', y')為浮點型(xing)(xing)坐標(biao)點,使用其(qi)周(zhou)圍整型(xing)(xing)點p0、p1、p2、p3的(de)像(xiang)素值(zhi)來(lai)計(ji)(ji)算其(qi)像(xiang)素值(zhi)A(x', y'),這個過程就(jiu)是插值(zhi)。
常見(jian)的插(cha)值(zhi)(zhi)算法有最(zui)鄰近插(cha)值(zhi)(zhi)、雙(shuang)線性插(cha)值(zhi)(zhi)、雙(shuang)三次插(cha)值(zhi)(zhi),不管什么插(cha)值(zhi)(zhi)算法,其本(ben)質都是取浮點(dian)(dian)型坐標(biao)點(dian)(dian)周圍的n*n個整型坐標(biao)點(dian)(dian)的像素(su)值(zhi)(zhi)進行加權(quan)和,從而得到該浮點(dian)(dian)型坐標(biao)點(dian)(dian)的像素(su)值(zhi)(zhi),如下式:
不同插(cha)值(zhi)算(suan)法的區別在于權重(zhong)W的計(ji)算(suan)不一(yi)樣(yang),下(xia)文將分別詳細講解最鄰近插(cha)值(zhi)、雙(shuang)線性插(cha)值(zhi)、雙(shuang)三次插(cha)值(zhi)的計(ji)算(suan)原理與實現。
1. 最鄰近插(cha)值(zhi)
最(zui)鄰近(jin)插值取離(li)浮點(dian)(dian)型坐(zuo)標(biao)點(dian)(dian)的(de)最(zui)近(jin)點(dian)(dian)的(de)像素(su)值作為(wei)其(qi)(qi)像素(su)值,也可以看成(cheng)使用浮點(dian)(dian)型坐(zuo)標(biao)點(dian)(dian)周(zhou)圍2*2個整型點(dian)(dian)的(de)像素(su)值來計算其(qi)(qi)像素(su)值,不過只有最(zui)靠近(jin)的(de)那個點(dian)(dian)權重為(wei)1,其(qi)(qi)余3個點(dian)(dian)權重系數都為(wei)0。
插值的計算如下式(shi):
其(qi)權重計算如下式:
最鄰(lin)近(jin)插值(zhi)的代碼(ma)實現最簡單(dan),直接對浮點(dian)型坐標(biao)進(jin)行四(si)舍五(wu)入取(qu)整即可,假設浮點(dian)坐標(biao)為(x_float, y_float),那么使用最鄰(lin)近(jin)插值(zhi)計算(suan)A(x_float, y_float)的代碼(ma)實現如下:
int x = (int)(x_float + 0.5); //加0.5再截斷取(qu)整(zheng),與四舍(she)五(wu)入取(qu)整(zheng)等效(xiao)
int y = (int)(y_float + 0.5);
uchar inner_value = A.ptr(y)[x]; //A(x',y')=A(x,y)
2. 雙(shuang)線性插值
雙線性(xing)插(cha)值與最鄰近(jin)插(cha)值類似(si),同樣使用浮點(dian)型坐(zuo)標點(dian)周圍2*2個整型點(dian)的像素(su)值來計算其(qi)(qi)像素(su)值,不過其(qi)(qi)周圍每個整型點(dian)的權重(zhong)都不為0,也就是說,其(qi)(qi)權重(zhong)計算與最鄰近(jin)插(cha)值不一樣:
浮點坐(zuo)標點(x_float, y_float)雙線性(xing)插值的代碼實現如下:
int x0 = floor(x_float);
int x1 = x0 + 1;
int y0 = floor(y_float);
int y1 = y0 + 1;
float fracRow = y_float - y0; //求浮點(dian)坐標的小(xiao)數(shu)部分
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. 雙三次插值
雙三次(ci)插(cha)值使用浮(fu)點型坐標(biao)點周圍4*4個整型點的像素值來計算(suan)其像素值,如下圖(tu)所示:
浮點型坐標點的插值(zhi)為(wei)其周圍4*4整型坐標點像(xiang)素值(zhi)的加權和:
其(qi)中權重W(i,j)的計算(suan)如下式,其(qi)中a取(qu)值范(fan)圍-1~0之間(jian),一般取(qu)固定值-0.5。
雙三次插(cha)值的實現代碼(ma)如下(xia)。
首先是權重函數的實(shi)現:
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;
}
接著是權重系(xi)數的計算實現(xian):
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;
}
}
最(zui)后,是(shi)雙三次(ci)插值代碼:
uchar cubic_inner(Mat A, float x_float, float y_float, float a)
{
float coeff[16];
cal_cubic_coeff(x_float, y_float, coeff); //計算權重系(xi)數
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;
}
從(cong)插(cha)值(zhi)效果來說:雙(shuang)三次(ci)插(cha)值(zhi)>雙(shuang)線性插(cha)值(zhi)>最鄰近插(cha)值(zhi),從(cong)計算復(fu)雜度來說,同樣是:雙(shuang)三次(ci)插(cha)值(zhi)>雙(shuang)線性插(cha)值(zhi)>最鄰近插(cha)值(zhi)。所以實(shi)際使(shi)用時,根據自己(ji)的需要選擇合適的插(cha)值(zhi)算法。
如涉(she)及侵權,請相關(guan)權利人與我司(si)聯(lian)系刪除