高阶插值——三次插值及实现

转自:https://blog.csdn.net/messi_cyc/article/details/78096649


双三次插值

接着双线性插值,此次为双三次插值(Bi-cubic interpolation),前面我们知道双线性插值是周边的四个点进行计算,这次双三次是通过计算周边的16个点进行插值的。

Bicubicinterpolation solves for the value at a new point by analyzing the 16 datapoints surrounding the interpolationregion, see the example below.

我们在新生成的图像中,像素点是f(x,y),先映射到源图像中的坐标为f(i+u,j+v)需要找到对应的原图像中离最近的16个点。

[cpp]  view plain  copy
  1. tempX = ((float)w/(w+x))*i;//final convent to original picture  
  2.                 tempY = ((float)h/(h+y))*j;  
[cpp]  view plain  copy
  1. tempX = ((float)w/(w+x))*i;//final convent to original picture  
  2.                 tempY = ((float)h/(h+y))*j;  

上面的这两句是计算新图像中的像素映射到源图像中的位置,假设两个像素点之间的距离是1,w/(w+x)是占的比例,然后乘i,也就是要得到的位置,就是映射到源图像中的位置,一定是个小数,像上面的图中那样,z22,z23,z32,z33这四个点是离要得到点最近的四个点,。映射到源图像中的也就是红色的点到四个最近点之间的距离都为小数,离其他点的距离是1点几。以下就是计算方法:

s()表示的是权值,权值是通过权值计算公式得出的,权值计算公式如下:

Inour project we set a=-0.5,and then we will get w value计算权值的方法如下:

[cpp]  view plain  copy
  1. double bicubPram6(double x){//bi-cubic interpolation 6 parameter compute  
  2.     double temp = 0;  
  3.     if(x<0){  
  4.         x = -x;  
  5.     }  
  6.      if(x <= 1){  
  7.         temp = (((float)(6.0/5.0))* x - (11.0/5.0)) * x * x + 1;  
  8.     }  
  9.     else if (x < 2) {    
  10.         temp = ((-0.6 * x + (16.0/5.0)) * x - (27.0/5.0)) * x + (14.0/5.0);    
  11.  }  
  12.     else if (x < 3) {    
  13.         temp = ((0.2 * x - (8.0/5.0)) * x + (21.0/5.0)) * x - (18.0/5.0);    
  14.  }  
  15.     return temp;  
  16. }  
[cpp]  view plain  copy
  1. double bicubPram6(double x){//bi-cubic interpolation 6 parameter compute  
  2.     double temp = 0;  
  3.     if(x<0){  
  4.         x = -x;  
  5.     }  
  6.      if(x <= 1){  
  7.         temp = (((float)(6.0/5.0))* x - (11.0/5.0)) * x * x + 1;  
  8.     }  
  9.     else if (x < 2) {    
  10.         temp = ((-0.6 * x + (16.0/5.0)) * x - (27.0/5.0)) * x + (14.0/5.0);    
  11.  }  
  12.     else if (x < 3) {    
  13.         temp = ((0.2 * x - (8.0/5.0)) * x + (21.0/5.0)) * x - (18.0/5.0);    
  14.  }  
  15.     return temp;  
  16. }  


整体计算的代码如下:

[cpp]  view plain  copy
  1. void bicubic6(IplImage *src,int h, int w,char *wf, int x, int y,IplImage *dst,int startX,int startY,int endX,int endY){  
  2.     int i,j;  
  3.     float tempX,tempY;  
  4.     int xOr, yOr,xOr2,yOr2;  
  5.     float aX,aY;  
  6.     double k1[6],k2[6];  
  7.     double temp[6]= {{0.0}};  
  8.     double s[6][6] = {{0.0}};  
  9.     CvScalar sf, s1;  
  10.     int grayValue = 0;  
  11.     for(i = startY; i<endY; i++){  
  12.             for(j = startX; j<endX; j++){  
  13.                 tempX = ((float)w/(w+x))*i;//final convent to original picture  
  14.                 tempY = ((float)h/(h+y))*j;  
  15.   
  16.                 xOr = floor(tempX);//get integer of original  
  17.                 yOr = floor(tempY);  
  18.   
  19.                 aX = tempX - xOr;//the float number  
  20.                 aY = tempY - yOr;  
  21.   
  22.                 for(int n = 2; n>-4; n--){  
  23.                         k1[n+3] = bicubPram6(aY+(double)n); //compute the y parameter  
  24.                         k2[n+3] = bicubPram6(aX+(double)n);//compute the x parameter                      
  25.                 }  
  26.                 for(int q = 3;q>-3;q--){  
  27.                     for(int k = -2;k<4;k++){  
  28.                         int tx =xOr+k;  
  29.                         int ty = yOr+q;  
  30.                         s1 =cvGet2D(src,tx,ty);  
  31.                          s[q+2][k+2] = s1.val[0];  
  32.                          temp[q+2] += k2[k+2]*s[q+2][k+2];  
  33.                     }     
  34.                 }  
  35.                 int result = temp[5]*k1[0]+temp[4]*k1[1]+temp[3]*k1[2]+temp[2]*k1[3]+temp[1]*k1[4]+temp[0]*k1[5];  
  36.                 for(int z = 0; z<6;z++){  
  37.                     temp[z] = 0;  
  38.                 }  
  39.                 sf = cvGet2D(src,xOr,yOr);  
  40.                 if(abs(result-sf.val[0])<200){             
  41.                 sf.val[0] = result;  
  42.                 cvSet2D(dst,i,j,sf);  
  43.                 }  
  44.                     }  
  45.                 }  
  46. }  
[cpp]  view plain  copy
  1. void bicubic6(IplImage *src,int h, int w,char *wf, int x, int y,IplImage *dst,int startX,int startY,int endX,int endY){  
  2.     int i,j;  
  3.     float tempX,tempY;  
  4.     int xOr, yOr,xOr2,yOr2;  
  5.     float aX,aY;  
  6.     double k1[6],k2[6];  
  7.     double temp[6]= {{0.0}};  
  8.     double s[6][6] = {{0.0}};  
  9.     CvScalar sf, s1;  
  10.     int grayValue = 0;  
  11.     for(i = startY; i<endY; i++){  
  12.             for(j = startX; j<endX; j++){  
  13.                 tempX = ((float)w/(w+x))*i;//final convent to original picture  
  14.                 tempY = ((float)h/(h+y))*j;  
  15.   
  16.                 xOr = floor(tempX);//get integer of original  
  17.                 yOr = floor(tempY);  
  18.   
  19.                 aX = tempX - xOr;//the float number  
  20.                 aY = tempY - yOr;  
  21.   
  22.                 for(int n = 2; n>-4; n--){  
  23.                         k1[n+3] = bicubPram6(aY+(double)n); //compute the y parameter  
  24.                         k2[n+3] = bicubPram6(aX+(double)n);//compute the x parameter                      
  25.                 }  
  26.                 for(int q = 3;q>-3;q--){  
  27.                     for(int k = -2;k<4;k++){  
  28.                         int tx =xOr+k;  
  29.                         int ty = yOr+q;  
  30.                         s1 =cvGet2D(src,tx,ty);  
  31.                          s[q+2][k+2] = s1.val[0];  
  32.                          temp[q+2] += k2[k+2]*s[q+2][k+2];  
  33.                     }     
  34.                 }  
  35.                 int result = temp[5]*k1[0]+temp[4]*k1[1]+temp[3]*k1[2]+temp[2]*k1[3]+temp[1]*k1[4]+temp[0]*k1[5];  
  36.                 for(int z = 0; z<6;z++){  
  37.                     temp[z] = 0;  
  38.                 }  
  39.                 sf = cvGet2D(src,xOr,yOr);  
  40.                 if(abs(result-sf.val[0])<200){             
  41.                 sf.val[0] = result;  
  42.                 cvSet2D(dst,i,j,sf);  
  43.                 }  
  44.                     }  
  45.                 }  
  46. }  

拉格朗日和B-Splin是类似的,只是权值的计算方法不同。就不赘述了……


拉格朗日方法

只是权值计算方法不同,需要重新写权值计算方法如下:

[cpp]  view plain  copy
  1. double LagPram(double x){//lagrange interpolation parameter compute  
  2.     double temp = 0;  
  3.     if(x<0){  
  4.         x = -x;  
  5.     }  
  6.      if(x <= 1){  
  7.         temp = (0.5 * x - 1) * x * x -0.5*x+ 1;  
  8.     }  
  9.     else if (x < 2) {    
  10.         temp = ((-((float)(1.0/6.0)) * x + 1) * x - ((float)(11.0/6.0))) * x + 1;   
  11.  }  
  12.     else temp = 0;  
  13.     return temp;  
  14. }  
[cpp]  view plain  copy
  1. double LagPram(double x){//lagrange interpolation parameter compute  
  2.     double temp = 0;  
  3.     if(x<0){  
  4.         x = -x;  
  5.     }  
  6.      if(x <= 1){  
  7.         temp = (0.5 * x - 1) * x * x -0.5*x+ 1;  
  8.     }  
  9.     else if (x < 2) {    
  10.         temp = ((-((float)(1.0/6.0)) * x + 1) * x - ((float)(11.0/6.0))) * x + 1;   
  11.  }  
  12.     else temp = 0;  
  13.     return temp;  
  14. }  

把上面程序里的那个计算权值的地方都改成拉格朗日的就好啦~

B-Splin方法也是类似的,就是不太理解这个方法的原理……

 

还有一种需要周围36个点的方法,也就是到最远的点的距离是3点几,周边的点是36个。

权值的计算方法如下:

[cpp]  view plain  copy
  1. double bicubPram8(double x){//bi-cubic interpolation 8 parameter compute  
  2.     double temp = 0;  
  3.     if(x<0){  
  4.         x = -x;  
  5.     }  
  6.      if(x <= 1){  
  7.         temp = (((float)(67.0/56.0))* x - (123.0/56.0)) * x * x + 1;  
  8.     }  
  9.     else if (x < 2) {    
  10.         temp = ((-(33.0/56.0) * x + (177.0/56.0)) * x - (75.0/14.0)) * x + (39.0/14.0);    
  11.  }  
  12.     else if (x < 3) {    
  13.         temp = (((9.0/56.0) * x - (75.0/56.0)) * x + (51.0/14.0)) * x - (45.0/14.0);    
  14.  }  
  15.     else if (x < 4) {    
  16.         temp = ((-(3.0/56.0) * x + (33.0/56.0)) * x - (15.0/7.0)) * x + (18.0/7.0);    
  17.  }  
  18.     return temp;  
  19. }  
[cpp]  view plain  copy
  1. double bicubPram8(double x){//bi-cubic interpolation 8 parameter compute  
  2.     double temp = 0;  
  3.     if(x<0){  
  4.         x = -x;  
  5.     }  
  6.      if(x <= 1){  
  7.         temp = (((float)(67.0/56.0))* x - (123.0/56.0)) * x * x + 1;  
  8.     }  
  9.     else if (x < 2) {    
  10.         temp = ((-(33.0/56.0) * x + (177.0/56.0)) * x - (75.0/14.0)) * x + (39.0/14.0);    
  11.  }  
  12.     else if (x < 3) {    
  13.         temp = (((9.0/56.0) * x - (75.0/56.0)) * x + (51.0/14.0)) * x - (45.0/14.0);    
  14.  }  
  15.     else if (x < 4) {    
  16.         temp = ((-(3.0/56.0) * x + (33.0/56.0)) * x - (15.0/7.0)) * x + (18.0/7.0);    
  17.  }  
  18.     return temp;  
  19. }  

计算像素的方法如下:

[cpp]  view plain  copy
  1. void bicubic8(IplImage *src,int h, int w,char *wf, int x, int y,IplImage *dst,int startX,int startY,int endX,int endY){  
  2.     int i,j;  
  3.     float tempX,tempY;  
  4.     int xOr, yOr,xOr2,yOr2;  
  5.     float aX,aY;  
  6.     double k1[8],k2[8];  
  7.     double temp[8]= {{0.0}};  
  8.     double s[8][8] = {{0.0}};//double s[4][4] = {0.0};不可以都赋值为0  
  9.     CvScalar sf, s1;  
  10.     int grayValue = 0;  
  11.     for(i = startY; i<endY; i++){  
  12.             for(j = startX; j<endX; j++){  
  13.                 tempX = ((float)w/(w+x))*i;//final convent to original picture  
  14.                 tempY = ((float)h/(h+y))*j;  
  15.   
  16.                 xOr = floor(tempX);//get integer of original  
  17.                 yOr = floor(tempY);  
  18.   
  19.                 aX = tempX - xOr;//the float number  
  20.                 aY = tempY - yOr;  
  21.   
  22.                 for(int n = 3; n>-5; n--){  
  23.                         k1[n+4] = bicubPram8(aY+(double)n); //compute the y parameter  
  24.                         k2[n+4] = bicubPram8(aX+(double)n);//compute the x parameter                      
  25.                 }  
  26.                 for(int q = 4;q>-4;q--){  
  27.                     for(int k = -3;k<5;k++){  
  28.                         int tx =xOr+k;  
  29.                         int ty = yOr+q;  
  30.                         s1 =cvGet2D(src,tx,ty);  
  31.                          s[q+3][k+3] = s1.val[0];  
  32.                          temp[q+3] += k2[k+3]*s[q+3][k+3];  
  33.                     }     
  34.                 }  
  35.                 int result = temp[7]*k1[0]+temp[6]*k1[1]+temp[5]*k1[2]+temp[4]*k1[3]+temp[3]*k1[4]+temp[2]*k1[5]+temp[1]*k1[6]+temp[0]*k1[7];  
  36.                 for(int z = 0; z<8;z++){  
  37.                     temp[z] = 0;  
  38.                 }  
  39.   
  40.                 sf = cvGet2D(src,xOr,yOr);  
  41.                 if(abs(result-sf.val[0])<200){             
  42.                 sf.val[0] = result;  
  43.                 cvSet2D(dst,i,j,sf);  
  44.                 }  
  45.                     }  
  46.                 }  
  47. }  
[cpp]  view plain  copy
  1. void bicubic8(IplImage *src,int h, int w,char *wf, int x, int y,IplImage *dst,int startX,int startY,int endX,int endY){  
  2.     int i,j;  
  3.     float tempX,tempY;  
  4.     int xOr, yOr,xOr2,yOr2;  
  5.     float aX,aY;  
  6.     double k1[8],k2[8];  
  7.     double temp[8]= {{0.0}};  
  8.     double s[8][8] = {{0.0}};//double s[4][4] = {0.0};不可以都赋值为0  
  9.     CvScalar sf, s1;  
  10.     int grayValue = 0;  
  11.     for(i = startY; i<endY; i++){  
  12.             for(j = startX; j<endX; j++){  
  13.                 tempX = ((float)w/(w+x))*i;//final convent to original picture  
  14.                 tempY = ((float)h/(h+y))*j;  
  15.   
  16.                 xOr = floor(tempX);//get integer of original  
  17.                 yOr = floor(tempY);  
  18.   
  19.                 aX = tempX - xOr;//the float number  
  20.                 aY = tempY - yOr;  
  21.   
  22.                 for(int n = 3; n>-5; n--){  
  23.                         k1[n+4] = bicubPram8(aY+(double)n); //compute the y parameter  
  24.                         k2[n+4] = bicubPram8(aX+(double)n);//compute the x parameter                      
  25.                 }  
  26.                 for(int q = 4;q>-4;q--){  
  27.                     for(int k = -3;k<5;k++){  
  28.                         int tx =xOr+k;  
  29.                         int ty = yOr+q;  
  30.                         s1 =cvGet2D(src,tx,ty);  
  31.                          s[q+3][k+3] = s1.val[0];  
  32.                          temp[q+3] += k2[k+3]*s[q+3][k+3];  
  33.                     }     
  34.                 }  
  35.                 int result = temp[7]*k1[0]+temp[6]*k1[1]+temp[5]*k1[2]+temp[4]*k1[3]+temp[3]*k1[4]+temp[2]*k1[5]+temp[1]*k1[6]+temp[0]*k1[7];  
  36.                 for(int z = 0; z<8;z++){  
  37.                     temp[z] = 0;  
  38.                 }  
  39.   
  40.                 sf = cvGet2D(src,xOr,yOr);  
  41.                 if(abs(result-sf.val[0])<200){             
  42.                 sf.val[0] = result;  
  43.                 cvSet2D(dst,i,j,sf);  
  44.                 }  
  45.                     }  
  46.                 }  
  47. }  

猜你喜欢

转载自blog.csdn.net/wp1351553202/article/details/80306373