介绍几种常用的插值方法以及代码-双三次插值

双三次插值 接着双线性插值,此次为双三次插值(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个点。

tempX = ((float)w/(w+x))*i; //final convent to original picture 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计算权值的方法如下:
double bicubPram6(double x){//bi-cubic interpolation 6 parameter compute double temp = 0; if(x<0){ x = -x; } if(x <= 1){ temp = (((float)(6.0/5.0))* x - (11.0/5.0)) * x * x + 1; } else if (x < 2) { temp = ((-0.6 * x + (16.0/5.0)) * x - (27.0/5.0)) * x + (14.0/5.0); } else if (x < 3) { temp = ((0.2 * x - (8.0/5.0)) * x + (21.0/5.0)) * x - (18.0/5.0); } return temp; }


整体计算的代码如下:
void bicubic6(IplImage *src,int h, int w,char *wf, int x, int y,IplImage *dst,int startX,int startY,int endX,int endY){ int i,j; float tempX,tempY; int xOr, yOr,xOr2,yOr2; float aX,aY; double k1[6],k2[6]; double temp[6]= {{0.0}}; double s[6][6] = {{0.0}}; CvScalar sf, s1; int grayValue = https://www.it610.com/article/0; for(i = startY; i-4; n--){ k1[n+3] = bicubPram6(aY+(double)n); //compute the y parameter k2[n+3] = bicubPram6(aX+(double)n); //compute the x parameter } for(int q = 3; q>-3; q--){ for(int k = -2; k<4; k++){ int tx =xOr+k; int ty = yOr+q; s1 =cvGet2D(src,tx,ty); s[q+2][k+2] = s1.val[0]; temp[q+2] += k2[k+2]*s[q+2][k+2]; } } 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]; for(int z = 0; z<6; z++){ temp[z] = 0; } sf = cvGet2D(src,xOr,yOr); if(abs(result-sf.val[0])<200){ sf.val[0] = result; cvSet2D(dst,i,j,sf); } } } }

拉格朗日和B-Splin是类似的,只是权值的计算方法不同。就不赘述了……
额,头一次发帖,发现和自己想的不一样,可能写的乱七八糟的,没有逻辑……不懂的可以问我。
拉格朗日方法
只是权值计算方法不同,需要重新写权值计算方法如下:
double LagPram(double x){//lagrange interpolation parameter compute double temp = 0; if(x<0){ x = -x; } if(x <= 1){ temp = (0.5 * x - 1) * x * x -0.5*x+ 1; } else if (x < 2) { temp = ((-((float)(1.0/6.0)) * x + 1) * x - ((float)(11.0/6.0))) * x + 1; } else temp = 0; return temp; }

把上面程序里的那个计算权值的地方都改成拉格朗日的就好啦~
B-Splin方法也是类似的,就是不太理解这个方法的原理……

还有一种需要周围36个点的方法,也就是到最远的点的距离是3点几,周边的点是36个。
权值的计算方法如下:
double bicubPram8(double x){//bi-cubic interpolation 8 parameter compute double temp = 0; if(x<0){ x = -x; } if(x <= 1){ temp = (((float)(67.0/56.0))* x - (123.0/56.0)) * x * x + 1; } else if (x < 2) { temp = ((-(33.0/56.0) * x + (177.0/56.0)) * x - (75.0/14.0)) * x + (39.0/14.0); } else if (x < 3) { temp = (((9.0/56.0) * x - (75.0/56.0)) * x + (51.0/14.0)) * x - (45.0/14.0); } else if (x < 4) { temp = ((-(3.0/56.0) * x + (33.0/56.0)) * x - (15.0/7.0)) * x + (18.0/7.0); } return temp; }

计算像素的方法如下:
void bicubic8(IplImage *src,int h, int w,char *wf, int x, int y,IplImage *dst,int startX,int startY,int endX,int endY){ int i,j; float tempX,tempY; int xOr, yOr,xOr2,yOr2; float aX,aY; double k1[8],k2[8]; double temp[8]= {{0.0}}; double s[8][8] = {{0.0}}; //double s[4][4] = {0.0}; 不可以都赋值为0 CvScalar sf, s1; int grayValue = https://www.it610.com/article/0; for(i = startY; i-5; n--){ k1[n+4] = bicubPram8(aY+(double)n); //compute the y parameter k2[n+4] = bicubPram8(aX+(double)n); //compute the x parameter } for(int q = 4; q>-4; q--){ for(int k = -3; k<5; k++){ int tx =xOr+k; int ty = yOr+q; s1 =cvGet2D(src,tx,ty); s[q+3][k+3] = s1.val[0]; temp[q+3] += k2[k+3]*s[q+3][k+3]; } } 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]; for(int z = 0; z<8; z++){ temp[z] = 0; }sf = cvGet2D(src,xOr,yOr); if(abs(result-sf.val[0])<200){ sf.val[0] = result; cvSet2D(dst,i,j,sf); } } } }

其实学会一个方法,其他就类似了。


    推荐阅读