双线性插值resize实现图片放缩

双线性插值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);
		}
	}
}

结果比对
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值