动手实现图像双线性插值——实现图像resize

摘要

动手实现图像双线性插值——实现图像resize


双线性插值算法原理概括为一句话就是:
输出图上一个像素投影到原图得到的坐标为浮点型,其对应的像素值由相邻的四个点进行双线性插值得到,如果选择一个合适的坐标系,使得这四个点的uv坐标分别为(0, 0)、(0, 1)、(1, 0) 和 (1, 1),那么双线性插值的公式就简化为:
f ( x , y ) = f ( 0 , 0 ) ( 1 − x ) ( 1 − y ) + f ( 1 , 0 ) x ( 1 − y ) + f ( 0 , 1 ) ( 1 − x ) y + f ( 1 , 1 ) x y f(x, y) = f(0, 0)(1-x)(1-y) + f(1, 0)x(1-y) + f(0, 1)(1-x)y + f(1, 1)xy f(x,y)=f(0,0)(1x)(1y)+f(1,0)x(1y)+f(0,1)(1x)y+f(1,1)xy
其中,f(x, y) 表示坐标 (x, y) 处 的像素值。

更详细的算法原理网上都有,这里不多说,文末参考资料里给出了一些个人觉得比较好的参考资料
下面给出完整的插值代码。

完整代码

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
	// read and show original image
	Mat img_raw = imread("original.jpg");
	cv::imshow("original", img_raw);
	waitKey(0);

	// bilinear interpolation
	double scale = 2.0;
	int32_t out_rows = img_raw.rows * scale + 0.5;
	int32_t out_cols = img_raw.cols * scale + 0.5;
	Mat img_out(out_rows, out_cols, img_raw.type(), Scalar::all(0));

	for (int32_t i = 0; i < img_out.rows; ++i)
	{
		Vec3b *p_out_row = img_out.ptr<Vec3b>(i);
		for (int32_t j = 0; j < img_out.cols; ++j)
		{
			double raw_v = i * (1.0 / scale);
			double raw_u = j * (1.0 / scale);

			// do not deal with the border situation
			if (0 <= raw_u && raw_u + 1 < img_raw.cols && 0 <= raw_v && raw_v + 1 < img_raw.rows)
			{
				Vec3b f00 = img_raw.ptr<Vec3b>((int32_t)raw_v)[(int32_t)raw_u];
				Vec3b f01 = img_raw.ptr<Vec3b>((int32_t)(raw_v + 1))[(int32_t)raw_u];
				Vec3b f10 = img_raw.ptr<Vec3b>((int32_t)raw_v)[(int32_t)(raw_u + 1)];
				Vec3b f11 = img_raw.ptr<Vec3b>((int32_t)(raw_v + 1))[(int32_t)(raw_u + 1)];

				// if you choose a coordinate system that makes the four known point coordinates become 
				// (0, 0), (0, 1), (1, 0), and (1, 1), then the bilinear interpolation formula can reduced to 
				// f(x, y) = f(0, 0)(1-x)(1-y) + f(1, 0)x(1-y) + f(0, 1)(1-x)y + f(1, 1)xy
				double x = (raw_u - (int32_t)raw_u);
				double y = (raw_v - (int32_t)raw_v);

				// 3 color channel
				p_out_row[j][0] = f00[0] * (1 - x) * (1 - y) +
									f10[0] * x * (1 - y) +
									f01[0] * (1 - x) * y +
									f11[0] * x * y;
				p_out_row[j][1] = f00[1] * (1 - x) * (1 - y) +
									f10[1] * x * (1 - y) +
									f01[1] * (1 - x) * y +
									f11[1] * x * y;
				p_out_row[j][2] = f00[2] * (1 - x) * (1 - y) +
									f10[2] * x * (1 - y) +
									f01[2] * (1 - x) * y +
									f11[2] * x * y;

			}
		}
	}

	// show result
	cv::imshow("img_out", img_out);
	waitKey(0);

	return 0;
}

相关/参考链接

OpenCV ——双线性插值(Bilinear interpolation)(给的代码是利用整形替换浮点型的加速版本)
双线性插值算法以及python实现

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值