interpolation

//! interpolation algorithm
enum
{
    INTER_NEAREST=CV_INTER_NN, //!< nearest neighbor interpolation
    INTER_LINEAR=CV_INTER_LINEAR, //!< bilinear interpolation
    INTER_CUBIC=CV_INTER_CUBIC, //!< bicubic interpolation
    INTER_AREA=CV_INTER_AREA, //!< area-based (or super) interpolation
    INTER_LANCZOS4=CV_INTER_LANCZOS4, //!< Lanczos interpolation over 8x8 neighborhood
    INTER_MAX=7,
    WARP_INVERSE_MAP=CV_WARP_INVERSE_MAP
};

//! resizes the image
CV_EXPORTS_W void resize( InputArray src, OutputArray dst,
                          Size dsize, double fx=0, double fy=0,
                          int interpolation=INTER_LINEAR );

//! warps the image using affine transformation
CV_EXPORTS_W void warpAffine( InputArray src, OutputArray dst,
                              InputArray M, Size dsize,
                              int flags=INTER_LINEAR,
                              int borderMode=BORDER_CONSTANT,
                              const Scalar& borderValue=Scalar());

//! warps the image using perspective transformation
CV_EXPORTS_W void warpPerspective( InputArray src, OutputArray dst,
                                   InputArray M, Size dsize,
                                   int flags=INTER_LINEAR,
                                   int borderMode=BORDER_CONSTANT,
                                   const Scalar& borderValue=Scalar());
 
 

(2)imgwarp.cpp中有插值函数,resize

(3) float a=1.0f在内存中的表示是3f800000,这个3f800000是怎么得出的?
3f800000H=0 01111111 00000000000000000000000B (注意我分成了三段)
符点型数据在X86机上占四个字节,其存储按IEEE754标准实现,即:
1位的符号位s 0(代表正数,1代表负数)
8位的指数位e(移码表示)01111111是0的移码
23位的小数位f 0000000000000000000000 表示小数部分为0
计算机在表示符点数时,要将10进制数转成二进制的规范数形式进行存储的。即:1.f*2^e在存储时,小数前面的1是隐式存储的,不体现在数据中。
现在翻译一下:
3f800000H=1.0*2^0=1.0

(4)移码

移码(又叫增码)是符号位取反的 补码,一般用做浮点数的阶码,引入的目的是为了保证浮点数的机器零为全0。  [1]  
①移码的定义:设由1位符号位和n位数值位组成的阶码,则 [X]移=2En + X (-2n<X<2n)
例如: X=+1011 [X]移=11011
X=-1011 [X]移=00101
②移码与补码的关系: [X]移与[X]补的关系是符号位互为相反数(仅符号位不同),
例如: X=+1011 [X]补=01011 [X]移=11011
X=-1011 [X]补=10101 [X]移=00101
③移码运算应注意的问题
◎对移码运算的结果需要加以修正,修正量为2En ,即对结果的符号位取反后才是移码形式的正确结果。
◎移码表示中,0有唯一的编码——1000…00,当出现000…00时(表示-2En),属于浮点数下溢。

符号位 阶码 尾数

第一步:求阶差: │ΔE│=|1010-0110|=0100
第二步:对阶:Y的阶码小, Y的尾数右移4位
[Y]浮变为 0 1 010 0000110 1101暂时保存
第三步:尾数相加,采用双符号位的补码运算
00 1100110
+00 0000110
00 1101100
第四步:规格化,满足规格化要求
第五步:舍入处理,采用0舍1入法处理
故最终运算结果的浮点数格式为: 0 1 010 1101101,
即X+Y=+0. 1101101*210

浮点数的运算规则

1、浮点加减法的运算步骤
设两个浮点数 X=Mx※2Ex Y=My※2Ey
实现X±Y要用如下5步完成:
①对阶操作:小阶向大阶看齐
②进行尾数加减运算
③规格化处理:尾数进行运算的结果必须变成规格化的浮点数,对于双符号位的补码尾数来说,就必须是
001×××…×× 或110×××…××的形式
若不符合上述形式要进行左规或右规处理。
④舍入操作:在执行对阶或右规操作时常用“0”舍“1”入法将右移出去的尾数数值进行舍入,以确保精度。
⑤判结果的正确性:即检查阶码是否溢出
若阶码下溢(移码表示是00…0),要置结果为机器0;
若阶码上溢(超过了阶码表示的最大值)置溢出标志。
例题:
假定X=0 .0110011*211,Y=0.1101101*2-10(此处的数均为二进制) ?? 计算X+Y;
解:[X]浮: 0 1 011 1100110
[Y]浮: 0 0 110 1101101
2、浮点乘除法的运算步骤
①阶码运算:阶码求和(乘法)或阶码求差(除法)
即 [Ex+Ey]移= [Ex]移+ [Ey]补
[Ex-Ey]移= [Ex]移+ [-Ey]补
②浮点数的尾数处理:浮点数中尾数乘除法运算结果要进行舍入处理
例题:
X=0 .0110011*2E11,Y=0.1101101*2E-10
求X※Y
解:[X]浮: 0 1 010 1100110
[Y]浮: 0 0 110 1101101
第一步:阶码相加
[Ex+Ey]移=[Ex]移+[Ey]补=1 010+1 110=1 000
1 000为移码表示的0
第二步原码尾数相乘的结果为:
0 10101101101110
第三步:规格化处理:已满足规格化要求,不需左规,尾数不变,阶码不变。
第四步:舍入处理:按舍入规则,加1进行修正
所以 X※Y= 0.1010111※2E+000

(1)最近邻插值

1 最近领内插值算法

就是令变换后像素的灰度值等于距它最近的输入像素的灰度值

 

如上图 按照比例一致 可知道

Y = W / w * y;

X = H / h * x;

则目标图(x, y)处的灰度值与原图(X, Y )处的灰度值一致: f(x, y) = f(X, Y)

2 双线性插值

在x y两个方向上分别进行一次线性插值,方向先后不影响顺序。

如上图所示

目标图(x, y) 映射到原图是(X + u, Y + v)(计算方法同最邻近插值)。设u与v分别为X + u,Y + v的小数部分。

由于下标都是整数,因此原图其实并不存在该点。

则取其附近四个领域点为(X, Y) (X, Y + 1) (X + 1, Y) (X + 1, Y + 1)

则目标图(x, y)处的值为 f(x , y) = f(X + u, Y + v) =f (X, Y)  * (1 - u) * (1 - v) + f(X, Y + 1) * (1 - u) * v + f(X + 1, Y) * u * (1 - v) + f (X + 1, Y + 1) * u * v;

(6)

目前比较常用的插值算法有这么几种:最邻近插值,双线性二次插值,三次插值,Lanczos插值等等,

1,最邻近插值

    最邻近插值算法也叫做零阶插值算法,主要原理是让输出像素的像素值等于邻域内

离它距离最近的像素值。例如下图中所示,P1距离0灰度值像素的距离小于100灰度值的

距离,因此,P1位置的插值像素为0。这个算法的优点是计算简单方便,缺点是图像容

易出现锯齿。

2,双线性二次插值

    在介绍双线性插值前,我们先介绍一下拉格朗日插值多项式。本文参考引用均来自

张铁的《数值分析》一书。

 

  我们的方法是这样的,根据水平方向上的双线性二次插值,由f(I,j)和f(i+1,j)求取f(x,j),由

f(I,j+1)和f(i+1,j+1)求取f(x,j+1),然后再根据这两点的二次插值求取f(x,y)。

  根据前面的例题,我们可以很容易的求取各点插值如下:

                        f(x,j)=(i+1-x)f(I,j)+(x-i)f(i+1,j)               公式1-(4)

                      f(x,j+1)=(i+1-x)f(I,j+1)+(x-i)f(i+1,j+1)           公式1-(5)

                       f(x,y)=(i+1-y)f(x,j)+(y-j)f(x,j+1)               公式1-(6)

  以上三式综合可以得到:

  f(x,y)=(j+1-y)(i+1-x)f(I,j)+(j+1-y)(x-i)f(i+1,j)+(y-j)(i+1-x)f(I,j+1)+(y-j)(x-i)f(i+1,j+1)     公式1-(7)

  我们令x=i+p,y=j+q得:

  f(i+p,j+q)=(1-q)(1-p)f(I,j)+p(1-q)f(i+1,j)+q(1-p)f(I,j+1)+pqf(i+1,j+1)                公式1-(8)

  上式即为数字图像处理中的双线性二次插值公式。


3,双线性三次插值


4,Lanczos插值算法

该算法的主要原理介绍地址:http://en.wikipedia.org/wiki/Lanczos_resampling

这里我大概介绍一下算法的流程:

这个算法也是一个模板算法,主要内容是计算模板中的权重信息。

对于一维信息,假如我们输入点集为X,那么,Lanczos对应有个窗口模板Window,这个窗口中每个位置的权重计算如下:

                         1-(12)


                 Fig.6 Lanczos

通常,这个a取2或者3,a=2时,该算法适用于图像缩小插值;a=3时,该算法适用于放大插值;对应不同a值得Lanczos插值曲线如上图6所示;上述的公式分别为连续和离散的公式。我们根据输入点X的位置,确定对应window中不同位置的权重L(x),然后对模板中的点值取加权平均,公式如下:

                                                    1-(13)

这个S(x)即为X处的插值结果。

根据上述一维插值,推广得到多维插值公式如下(这里以二维为例):

 1-(14)


上述内容是对不同插值算法简单的进行了介绍,如果不明白可以查找相关知识。

现在我们来看下相应的效果图:


上面的一组效果图均是先将原图缩小50%,然后使用不同算法放大到原图大小得到的。由上面这组图我们可以发现,效果最差的是最邻近插值算法,效果最好的是双线性三次插值,Lanczos算法跟三次插值大致一致;

由于编程语言不同,可能会造成耗时的差距,但是,对于同一种语言,统计得出:最邻近插值速度最快,三次插值速度最慢,而Lanczos算法与二次插值相仿。

综上,Lanczos插值具有速度快,效果好,性价比最高的优点,这也是目前此算法比较流行的原因。


双三次插值(也称协调板元),二元双三次插值公式共有(3+1)2=16个系数,其一般形式可写成:

 a00 + a10x + a01y + a20x2 + a11xy + a02y2 + a21x2y + a12xy2 + a22x2y2 + a30x3 + a03y3 + a31x3y + a13xy3 + a32x3y2 + a23x2y3 + a33x3y3    

或者更简单的形式 :



双三次插值方法能够克服双线性插值和最邻近插值算法的缺点。计算精度比较高,插值效果较最近邻插值法和双线性插值法好,但是计算量大。在图像领域中,该方法考虑一个浮点坐标(i+u,j+v)周围的16个邻点,目标像素值f(i+u,j+v)可由如下插值公式得到:
    f(i+u,j+v)=[A]×[B]×[C]

     [A]=[S(u+1)  S(u+0)  S(u-1)  S(u-2)]       


个人分类:  算法导论 && AC


猜你喜欢

转载自blog.csdn.net/weixin_41484240/article/details/80577158