tft每日頭條

 > 生活

 > 圖像匹配算法插值

圖像匹配算法插值

生活 更新时间:2024-08-28 06:16:08

講插值之前,首先講像素重采樣的概念。假設有圖像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')的像素值,插值算法就派上用場了。

圖像匹配算法插值(常見圖像插值算法的原理與C)1

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

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

圖像匹配算法插值(常見圖像插值算法的原理與C)2

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

1. 最鄰近插值

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

圖像匹配算法插值(常見圖像插值算法的原理與C)3

插值的計算如下式:

圖像匹配算法插值(常見圖像插值算法的原理與C)4

其權重計算如下式:

圖像匹配算法插值(常見圖像插值算法的原理與C)5

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

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

2. 雙線性插值

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

圖像匹配算法插值(常見圖像插值算法的原理與C)6

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

int x0 = floor(x_float); int x1 = x0 1; int y0 = floor(y_float); int y1 = y0 1; floatfracRow=y_float-y0;//求浮點坐标的小數部分 floatfracCol=x_float-x0; float k0 = 1.0 - fracRow; float k1 = 1.0 - fracCol; floatw0=k0*k1; floatw1=fracRow*k1; floatw2=k0*fracCol; floatw3=fracRow*fracCol; ucharinner_value=(uchar)(w0*A.ptr<uchar>(y0)[x0] w1*A.ptr<uchar>(y1)[x0] w2*A.ptr<uchar>(y0)[x1] w3*A.ptr<uchar>(y1)[x1]);

3. 雙三次插值

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

圖像匹配算法插值(常見圖像插值算法的原理與C)7

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

圖像匹配算法插值(常見圖像插值算法的原理與C)8

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

圖像匹配算法插值(常見圖像插值算法的原理與C)9

圖像匹配算法插值(常見圖像插值算法的原理與C)10

圖像匹配算法插值(常見圖像插值算法的原理與C)11

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

首先是權重函數的實現:

floatcubic_coeff(floatx,floata) { 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; } return0.0; }

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

voidcal_cubic_coeff(floatx,floaty,float*coeff) { /*calc the coeff*/ floatu=x-floor(x); floatv=y-floor(y); u = 1; v = 1; floata=-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; floata_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; } }

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

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

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

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved