双线性插值resize实现图片放缩
opencv的resize的双线性插值实现
简简单单两张图说明原理,仔细看一会原理就懂了,不要怕图二的数学公式,看明白就知道有多简单了。
原理看懂了的话,就来看实现吧。
这里实现的重点是要以两张图片的中心建立坐标系,进行计算。
图中黑点即为坐标原点,第一种在进行图片放缩时是错误的做法,正确做法第二种,以中心为坐标原点进行计算,并且需要注意一点的是,**当你用将浮点数截断转整,在不同的象限求x1,x2,y1,y2所做的操作是不同的。**例如 -3.5得到的是-3和-4 ,是x的x-1的值,而3.5得到的是3和4,是x和x+1的值。
需要注意的地方是要注意判定是否出了边界。
附上我的代码
struct point {
double x, y;
};
int in_range(int it,int min, int max) {
it = it < min ? min : it;
return it > max ? max : it;
}
void resize(int srcH, int srcW, int dstH, int dstW, uchar src[], uchar dst[]) {
point sO, dO,S,D;
sO.x = srcW / 2.0; sO.y = srcH / 2.0;
dO.x = dstW / 2.0; dO.y = dstH / 2.0;//原点计算
double sigmaX = srcW *1.0/ dstW,sigmaY=srcH*1.0/dstH;
for (int i = 0; i < dstH; i++) {
for (int j = 0; j < dstW; j++) {
D.x = j - dO.x;
D.y = i - dO.y;
S.x = D.x*sigmaX+sO.x;
S.y = D.y*sigmaY+sO.y;
int x1, x2, y1, y2;
if (S.x > 0) {
x1 = (int)(S.x); x2 = x1 + 1;
}
else {
x1 = (int)(S.x)-1; x2 = x1 + 1;
}
if (S.y > 0) {
y1 = (int)(S.y); y2 = y1 + 1;
}
else {
y1 = (int)(S.y) - 1; y2 = y1 + 1;
}
//对应点的确定
x1=in_range(x1, 0, srcW - 1);
x2=in_range(x2, 0, srcW - 1);
y1=in_range(y1, 0, srcH - 1);
y2=in_range(y2, 0, srcH - 1);//避免出界
double Q1, Q2, Q;
if (x1 == x2) {
Q1 = src[y1*srcW + x1];
Q2 = src[y2*srcW + x1];
}
else {
Q1 = (x2 - S.x)*src[y1*srcW + x1] + (S.x - x1)*src[y1*srcW + x2];
Q2 = (x2 - S.x)*src[y2*srcW + x1] + (S.x - x1)*src[y2*srcW + x2];
}
if (y1 == y2)Q = Q1;
else
Q = (y2 - S.y)*Q1 + (S.y - y1)*Q2;//结果的计算
dst[i*dstW + j] = int(Q);
}
}
}
结果比对