三十分钟理解:线性插值,双线性插值Bilinear Interpolation算法
线性插值
先讲一下线性插值:已知数据 (x0, y0) 与 (x1, y1),要计算 [x0, x1] 区间内某一位置 x 在直线上的y值(反过来也是一样,略):
上面比较好理解吧,仔细看就是用x和x0,x1的距离作为一个权重,用于y0和y1的加权。双线性插值本质上就是在两个方向上做线性插值。
双线性插值
在数学上,双线性插值是有两个变量的插值函数的线性插值扩展,其核心思想是在两个方向分别进行一次线性插值[1]。见下图:
假如我们想得到未知函数 f 在点 P = (x, y) 的值,假设我们已知函数 f 在 Q11 = (x1, y1)、Q12 = (x1, y2), Q21 = (x2, y1) 以及 Q22 = (x2, y2) 四个点的值。最常见的情况,f就是一个像素点的像素值。首先在 x 方向进行线性插值,得到
然后在 y 方向进行线性插值,得到
综合起来就是双线性插值最后的结果:
由于图像双线性插值只会用相邻的4个点,因此上述公式的分母都是1。opencv中的源码如下,用了一些优化手段,比如用整数计算代替float(下面代码中的*2048就是变11位小数为整数,最后有两个连乘,因此>>22位),以及源图像和目标图像几何中心的对齐
SrcX=(dstX+0.5)* (srcWidth/dstWidth) -0.5
SrcY=(dstY+0.5) * (srcHeight/dstHeight)-0.5,
这个要重点说一下,源图像和目标图像的原点(0,0)均选择左上角,然后根据插值公式计算目标图像每点像素,假设你需要将一幅5x5的图像缩小成3x3,那么源图像和目标图像各个像素之间的对应关系如下。如果没有这个中心对齐,根据基本公式去算,就会得到左边这样的结果;而用了对齐,就会得到右边的结果:
cv::Mat matSrc, matDst1, matDst2;
matSrc = cv::imread("lena.jpg", 2 | 4);
matDst1 = cv::Mat(cv::Size(800, 1000), matSrc.type(), cv::Scalar::all(0));
matDst2 = cv::Mat(matDst1.size(), matSrc.type(), cv::Scalar::all(0));
double scale_x = (double)matSrc.cols / matDst1.cols;
double scale_y = (double)matSrc.rows / matDst1.rows;
uchar* dataDst = matDst1.data;
int stepDst = matDst1.step;
uchar* dataSrc = matSrc.data;
int stepSrc = matSrc.step;
int iWidthSrc = matSrc.cols;
int iHiehgtSrc = matSrc.rows;
for (int j = 0; j < matDst1.rows; ++j)
{
float fy = (float)((j + 0.5) * scale_y - 0.5);
int sy = cvFloor(fy);
fy -= sy;
sy = std::min(sy, iHiehgtSrc - 2);
sy = std::max(0, sy);
short cbufy[2];
cbufy[0] = cv::saturate_cast<short>((1.f - fy) * 2048);
cbufy[1] = 2048 - cbufy[0];
for (int i = 0; i < matDst1.cols; ++i)
{
float fx = (float)((i + 0.5) * scale_x - 0.5);
int sx = cvFloor(fx);
fx -= sx;
if (sx < 0) {
fx = 0, sx = 0;
}
if (sx >= iWidthSrc - 1) {
fx = 0, sx = iWidthSrc - 2;
}
short cbufx[2];
cbufx[0] = cv::saturate_cast<short>((1.f - fx) * 2048);
cbufx[1] = 2048 - cbufx[0];
for (int k = 0; k < matSrc.channels(); ++k)
{
*(dataDst+ j*stepDst + 3*i + k) = (*(dataSrc + sy*stepSrc + 3*sx + k) * cbufx[0] * cbufy[0] +
*(dataSrc + (sy+1)*stepSrc + 3*sx + k) * cbufx[0] * cbufy[1] +
*(dataSrc + sy*stepSrc + 3*(sx+1) + k) * cbufx[1] * cbufy[0] +
*(dataSrc + (sy+1)*stepSrc + 3*(sx+1) + k) * cbufx[1] * cbufy[1]) >> 22;
}
}
}
cv::imwrite("linear_1.jpg", matDst1);
cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 1);
cv::imwrite("linear_2.jpg", matDst2);
好了,本篇到这里,欢迎大家分享转载,注明出处即可。
参考资料
[1] 双线性插值(Bilinear Interpolation)
[2] OpenCV ——双线性插值(Bilinear interpolation)
[3] 双线性插值算法及需要注意事项
[4] OpenCV中resize函数五种插值算法的实现过程
三十分钟理解:线性插值,双线性插值Bilinear Interpolation算法的更多相关文章
- [转载]三十分钟理解:线性插值,双线性插值Bilinear Interpolation算法
[转载]三十分钟理解:线性插值,双线性插值Bilinear Interpolation算法 来源:https://blog.csdn.net/xbinworld/article/details/656 ...
- 三十分钟理解:双调排序Bitonic Sort,适合并行计算的排序算法
欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld 技术交流QQ群:433250724,欢迎对算法.技术.应用感兴趣的同学加入 双调排序是data-indepen ...
- [重磅]Deep Forest,非神经网络的深度模型,周志华老师最新之作,三十分钟理解!
欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术感兴趣的同学加入. 深度学习最大的贡献,个人认为就是表征 ...
- 三十分钟理解计算图上的微积分:Backpropagation,反向微分
神经网络的训练算法,目前基本上是以Backpropagation (BP) 反向传播为主(加上一些变化),NN的训练是在1986年被提出,但实际上,BP 已经在不同领域中被重复发明了数十次了(参见 G ...
- 三十分钟理解博弈论“纳什均衡” -- Nash Equilibrium
欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术感兴趣的同学加入. 纳什均衡(或者纳什平衡),Nash ...
- 数字图像处理实验(4):PROJECT 02-04 [Multiple Uses],Zooming and Shrinking Images by Bilinear Interpolation 标签: 图像处理MATLAB
实验要求: Zooming and Shrinking Images by Bilinear Interpolation Objective To manipulate another techniq ...
- 【转】三十分钟学会STL算法
转载自: http://net.pku.edu.cn/~yhf/UsingSTL.htm 这是本小人书.原名是<using stl>,不知道是谁写的.不过我倒觉得很有趣,所以化了两个晚上把 ...
- 线性插值&双线性插值&三线性插值
http://www.cnblogs.com/yingying0907/archive/2012/11/21/2780092.html 內插是数学领域数值分析中的通过已知的离散数据求未知数据的过程或方 ...
- 【转】三十分钟掌握STL
转自http://net.pku.edu.cn/~yhf/UsingSTL.htm 三十分钟掌握STL 这是本小人书.原名是<using stl>,不知道是谁写的.不过我倒觉得很有趣,所以 ...
随机推荐
- C内存对齐问题-bus error!总线错误!其实是 字符串字面量修改问题!
最近写个小程序,出现bus error! int main(void) { /** * char :1个字节 * char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也 ...
- libevent学习文档(二)eventbase相关接口和参数
Setting up a default event_base The event_base_new() function allocates and returns a new event base ...
- C++实现成绩管理模拟系统
C++实现基本的成绩管理系统 需求: 1-学生姓名等基本字段 2-学生成绩字段 3-实现成绩修改和基本统计输出 #include<iostream> #include<windows ...
- 前端PHP入门-002-安装WAMP的集成环境md
> 第一次讲PHP,让我感觉还是满好玩的,一种新的知识的学习,需要我们努力! > 这次PHP课程计划是15天快速入门的课程! 只是单独的讲PHP语言,不涉及很深的内容,只是想让web前端的 ...
- IIS7.5 HTTP 错误500.19-Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效
IIS7.5 HTTP 错误500.19-Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效 --------------------------------- ...
- My97DatePicker 报错 My97DP is not defined
https://blog.csdn.net/BoomLee/article/details/80967926
- node.js的安装配置——前端的配置
最近琢磨了以下node.js的安装,npm的配置,使用gulp watch监听index.html文件的修改,利用服务器打开网页. 打开自己写的网页不要本地双击打开,这样打开的网址是file:///E ...
- Delphi 常用数据类型 字符串类型 数据类型等等
字符串类型 Delphi有三种类型的字符: ●AnsiChar这是标准的1字节的ANSI字符,程序员都对它比较熟悉. ●WideChar这是2字节的Unicode字符. ●Char在目前Delphi早 ...
- HNOI2019退役祭
对你没看错,是退役祭. Day -2 春游.话说为什么又是植物园? Day -1 白天上文化课,晚上给机房其它童鞋出题. Day 0 给他们考试,然后颓3Dmaze,毕竟没网 Day 1 车上复习了下 ...
- 【洛谷 P1772】 [ZJOI2006]物流运输(Spfa,dp)
题目链接 \(g[i][j]\)表示不走在\(i\text{~}j\)时间段中会关闭的港口(哪怕只关\(1\)天)从\(1\)到\(m\)的最短路. \(f[i]\)表示前\(i\)天的最小花费.于是 ...