插值法的原理(常见图像插值算法的原理与C++实现)
插值法的原理(常见图像插值算法的原理与C++实现)
讲插值之前,首先讲像素重采样的概念。假设有图像A和图像B,其中A为源图像,B为目标图像,A与B的坐标具有对应关系f:
(xa, ya)=f(xb, yb)
通过关系f,把A的像素值赋值给B中对应像素点的过程,叫做图像A的像素重采样,图像B为重采样之后的图像。比如对于B的任意像素点(x, y),其对应的A的像素点为(x’, y’),那么则把A中点(x’, y’)的像素值A(x’, y’)赋值给B中点(x, y)的像素值B(x, y)。
(x‘, y’)=f(x, y)
B(x, y)=A(x’, y’)
像素重采样的常见应用场景为图像缩放和图像配准。在实际应用过程中,源图像A的对应坐标往往不是整数,而是浮点型数据(如下图所示),因此不能直接取其像素值赋值给目标图像上的对应点。此时要获取点A(x’, y’)的像素值,插值算法就派上用场了。

所谓插值,就是使用浮点型坐标点的周围整型点的像素值来计算该浮点型坐标点的像素值。比如上图中,点(x’, y’)为浮点型坐标点,使用其周围整型点p0、p1、p2、p3的像素值来计算其像素值A(x’, y’),这个过程就是插值。
常见的插值算法有最邻近插值、双线性插值、双三次插值,不管什么插值算法,其本质都是取浮点型坐标点周围的n*n个整型坐标点的像素值进行加权和,从而得到该浮点型坐标点的像素值,如下式:

不同插值算法的区别在于权重W的计算不一样,下文将分别详细讲解最邻近插值、双线性插值、双三次插值的计算原理与实现。
1. 最邻近插值
最邻近插值取离浮点型坐标点的最近点的像素值作为其像素值,也可以看成使用浮点型坐标点周围2*2个整型点的像素值来计算其像素值,不过只有最靠近的那个点权重为1,其余3个点权重系数都为0。

插值的计算如下式:

其权重计算如下式:

最邻近插值的代码实现最简单,直接对浮点型坐标进行四舍五入取整即可,假设浮点坐标为(x_float, y_float),那么使用最邻近插值计算A(x_float, y_float)的代码实现如下:
intx=(int)(x_float+0.5);//加0.5再截断取整,与四舍五入取整等效inty=(int)(y_float+0.5); ucharinner_value=A.ptr(y)[x];//A(x',y')=A(x,y)
2. 双线性插值
双线性插值与最邻近插值类似,同样使用浮点型坐标点周围2*2个整型点的像素值来计算其像素值,不过其周围每个整型点的权重都不为0,也就是说,其权重计算与最邻近插值不一样:

浮点坐标点(x_float, y_float)双线性插值的代码实现如下:
intx0=floor(x_float);intx1=x0+1;inty0=floor(y_float);inty1=y0+1;floatfracRow=y_float-y0;//求浮点坐标的小数部分floatfracCol=x_float-x0;floatk0=1.0-fracRow;floatk1=1.0-fracCol;floatw0=k0*k1;floatw1=fracRow*k1;floatw2=k0*fracCol;floatw3=fracRow*fracCol; ucharinner_value=(uchar)(w0*A.ptr(y0)[x0]+w1*A.ptr(y1)[x0]+w2*A.ptr(y0)[x1]+w3*A.ptr(y1)[x1]);
3. 双三次插值
双三次插值使用浮点型坐标点周围4*4个整型点的像素值来计算其像素值,如下图所示:

浮点型坐标点的插值为其周围4*4整型坐标点像素值的加权和:

其中权重W(i,j)的计算如下式,其中a取值范围-1~0之间,一般取固定值-0.5。



双三次插值的实现代码如下。
首先是权重函数的实现:
float
cubic_coeff
(
float
x,
float
a){
if
(x <=
1
) {
return
1
-(a+
3
)*x*x+(a+
2
)*x*x*x; }
else
if
(x <
2
) {
return
-4
*a+
8
*a*x
-5
*a*x*x+a*x*x*x; }
return
0.0
; }
接着是权重系数的计算实现:
void
cal_cubic_coeff
(
float
x,
float
y,
float
*coeff){
/*calc the coeff*/
float
u=x-
floor
(x);
float
v=y-
floor
(y); u +=
1
; v +=
1
;
float
a=
-0.15
;
float
a_mul_4 = (a + a) + (a + a);
float
a_mul_5 = a_mul_4 + a;
float
a_mul_8 = a_mul_4 + a_mul_4;
float
a_add_3 = a +
3
;
float
a_add_2=a+
2
;
float
A[
4
]; A[
0
] = cubic_coeff(
abs
(u), a); A[
1
] = cubic_coeff(
abs
(u
-1
), a); A[
2
] = cubic_coeff(
abs
(u
-2
), a); A[
3
] = cubic_coeff(
abs
(u
-3
), a);
for
(
int
s =
0
; s <
4
; s++) {
float
C = cubic_coeff(
abs
(v-s), a); coeff[s*
4
] = A[
0
]*C; coeff[s*
4
+
1
] = A[
1
]*C; coeff[s*
4
+
2
] = A[
2
]*C; coeff[s*
4
+
3
] = A[
3
]*C; } }
最后,是双三次插值代码:
ucharcubic_inner(MatA,floatx_float,floaty_float,floata){floatcoeff[16]; cal_cubic_coeff(x_float,y_float,coeff);//计算权重系数floatsum=0.0;intx0=floor(x_float)-1;inty0=floor(y_float)-1;for(inti=0;i<4;i++) {for(intj=0;j<4;j++) { sum+=coeff[i*4+j]*A.ptr(y0+i)[x0+j]; } } ucharinner_value=(uchar)sum;returninner_value; }
从插值效果来说:双三次插值>双线性插值>最邻近插值,从计算复杂度来说,同样是:双三次插值>双线性插值>最邻近插值。所以实际使用时,根据自己的需要选择合适的插值算法。
-
- cosmetea小怪兽气垫ee霜真假怎么辨别_对比图
-
2025-11-09 03:17:42
-
- 糖脆排骨的做法
-
2025-11-09 03:15:36
-
- 11月2日天津市发热门诊、核酸检测候诊信息定时播报
-
2025-11-09 03:13:30
-
- 北京朝阳区房价走势北京整体房价水平 样
-
2025-11-09 03:11:24
-
- 做扇子,做了一把扇子的朋友圈说说?
-
2025-11-09 03:09:18
-
- 我爱读书的作文400(我爱读书的作文500字)
-
2025-11-09 03:07:13
-
- 母鬣狗身体构造鬣狗都是母的
-
2025-11-09 03:05:07
-
- 灰色西裤配什么颜色好看衣服(灰色裤子最佳配色表)
-
2025-11-09 03:03:01
-
- 挽回男友攻略:怎么能和前男友复合
-
2025-11-08 23:04:56
-
- 天蝎座男与狮子座女:爱情配对指数和有效沟通方法
-
2025-11-08 23:02:41
-
- 双鱼座 梦幻和现实之间的情感体验
-
2025-11-08 23:00:27
-
- 十大唱片公司排行榜 唱片公司哪家好
-
2025-11-08 22:58:12
-
- 七夕礼物送男生什么好 七夕礼物送男生什么好寓意的
-
2025-11-08 22:55:58
-
- 离婚后遭遇前任施暴是否属于家庭暴力分析
-
2025-11-08 22:53:43
-
- 婚姻破裂两个终极原因,如何挽救一段即将破碎的婚姻
-
2025-11-08 22:51:28
-
- PDD讲解新版骚套路 玩转EZ偷钱流派符文
-
2025-11-08 22:49:13
-
- 谈恋爱好累不想谈了怎么办
-
2025-11-08 22:46:59
-
- 气球装饰前景怎么样?
-
2025-11-08 22:44:44
-
- 避孕套影响性爱快感真的吗 戴套性爱的正确方法
-
2025-11-08 13:44:39
-
- 六十多岁可以考驾照吗(科目二70分)
-
2025-11-08 13:42:25



美国有几艘航母(美国11艘航母名字及服役时间表)
余声个人资料简介(安徽卫视主持人余声简历图片)