双三次插值 接着双线性插值,此次为双三次插值(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);
}
}
}
}
其实学会一个方法,其他就类似了。
推荐阅读
- 控制算法|惯性测量单元IMU基础
- opencv图像处理(七)sobel、Laplacian
- Opencv|移动平均的阈值处理 opencv实现
- 数字图像处理|Kirsch边缘检测原理
- 数字图像处理|二值图像--形态学处理4 击中,边界提取,孔洞填充,连通分量提取,凸壳,细化,骨架,形态学重建
- opencv|C++实现最简单的边缘连接(局部处理)