常见图像插值算法的原理与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’)的像素值 , 插值算法就派上用场了 。

常见图像插值算法的原理与C++实现  插值法的原理

文章插图
所谓插值 , 就是使用浮点型坐标点的周围整型点的像素值来计算该浮点型坐标点的像素值 。比如上图中 , 点(x’, y’)为浮点型坐标点 , 使用其周围整型点p0、p1、p2、p3的像素值来计算其像素值A(x’, y’) , 这个过程就是插值 。
常见的插值算法有最邻近插值、双线性插值、双三次插值 , 不管什么插值算法 , 其本质都是取浮点型坐标点周围的n*n个整型坐标点的像素值进行加权和 , 从而得到该浮点型坐标点的像素值 , 如下式:
不同插值算法的区别在于权重W的计算不一样 , 下文将分别详细讲解最邻近插值、双线性插值、双三次插值的计算原理与实现 。
1. 最邻近插值
最邻近插值取离浮点型坐标点的最近点的像素值作为其像素值 , 也可以看成使用浮点型坐标点周围2*2个整型点的像素值来计算其像素值 , 不过只有最靠近的那个点权重为1 , 其余3个点权重系数都为0 。
常见图像插值算法的原理与C++实现  插值法的原理

文章插图
插值的计算如下式:
其权重计算如下式:
常见图像插值算法的原理与C++实现  插值法的原理

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

文章插图
浮点坐标点(, )双线性插值的代码实现如下:
int x0 = floor(x_float);int x1 = x0 + 1;int y0 = floor(y_float);int y1 = y0 + 1;float fracRow = y_float - y0;//求浮点坐标的小数部分float fracCol = x_float - x0;float k0 = 1.0 - fracRow;float k1 = 1.0 - fracCol;float w0 = k0*k1;float w1 = fracRow*k1;float w2 = k0*fracCol;
常见图像插值算法的原理与C++实现  插值法的原理

文章插图
float w3 = fracRow*fracCol;uchar inner_value = http://www.kingceram.com/post/(uchar)(w0 * A.ptr(y0)[x0] + w1 * A.ptr(y1)[x0] + w2 * A.ptr