一个简单的 双三次B样条算法 实现的 图像放大
B样条算法图像放大的学习和实现
一、总体设计思路
本次B样条图像放大的实现建立在之前做的图像的显示,双线性插值图像放大的基础上。因为有之前的基础,所以实际上本次我只是要实现基于B样条的插值即可。本文也只是讨论B样条插值的实现。本次实现是基于双三次B样条曲面的,且对每一个像素点都采用B样条插值的方法来确定颜色值。B样条插值有以下几个步骤:
Step 1:取型值点 16个
Step2:计算每个型值点的(u,v)
Step3:根据B样条曲面矩阵形式的公式(由控制点及(u,v)得到曲面上的点),利用已有的型值点及(u,v),反算出16个控制点。
Step4:计算出欲求像素点的(u,v)。得到对应的像素值,并赋给对应的位置。
二、原理
1、理论支持
我的整个实现过程都是基于这两个公式的,而经过试验。这两个公式都是好用的。 整个
2、公式推导
其实这个实现过程中,最关键的部分就是由该公式由16个型值点构建方程组反求出16个控制点,之后再用这里的公式求点即可。
对此通过计算易得:
设[u3,u2,u,1]XM1=pre[4]; M2X[v3,v2,v,1]T=behind[4];
pre的四个元素为 a b c d bdhind的四个元素为e f g h.易得
p(u,v)=(e(aP00+bP10+cP20+dP30)+f(aP01+bP11+cP21+dP31)+g(aP02+bP12+cP22+dP32)+h(aP03+bP13+cP23+dP33))/36;
也即
一个简单的 双三次B样条算法 实现的 图像放大
p(u,v)=(aeP00+beP10+ceP20+deP30+afP01+bfP11+cfP21+dfP31+agP02+bgP12+cgP22+dgP32+ahP03+bhP13+chP23+dhP33)/36;
由该式即可设立一个 16个未知数的方程。
由16个点就可以得到16个方程并解得16个控制点。
三、具体实现方案及细节
1、具体实现方案
①型值点的选取
先将新图中的坐标转换成原图中的坐标.也即x=X/m;y=Y/m;(m为边长需要放大的倍数)取周边的16个点。按得到的坐标的值就可以往左右上下各延伸2个单位。若上或下不足(左或右)那么就朝另一边发展。
②(u,v)的确定
在我的实现中,(u,v)的确定比较简单。(在平面上确定)。因为型值点是取的一个4X4的矩阵。假设型值点在这个矩阵中的下标为(i,j);则u=i/3.0;v=j/3.0; 假设最小型值点的x为preX,y为preY.则新图中像素点(X,Y)的u=(X-preX)/3.0;v=(Y-preY)/3.0;
③解方程
1) Ax=b->x=A^-1B;因为我的(u,v)对于每一个像素点来说是不变的。(参看(u,v)的确定)所以该式中的A是不变的。
因此给出一个方法就是直接得到A之后对A求逆并保存下来之后每一次就只要做矩阵的乘法即可得到结果。
④根据公式加上16个的控制点和对应的(u,v)即可求出像素值。
2、实现过程中的遇到的问题和解决
①不会确定(u,v),心里想着只能靠(x,y)但是不知道到底怎么弄。最后还是老师指点空间可以参数化到平面上,才确定了现在取型值点的方法。
②解方程我自己先写了一个高斯消元法,但是效率太低所以换成了方案中的矩阵求逆。然后矩阵运算。
③求逆我也写了一个类,解决了行列式的解、求伴随矩阵、求逆序数等问题。最后因为矩阵16X16行列式定义法求解直接卡死了。最后是借助matlab完成了这一步工作。同时这个过程中用代码实现,矩阵的产生和整理 也帮了我很多忙。
④解完方程之后,在程序能运行速度大幅提升的时候心里很高兴。但是这股高兴劲马上就被出来的效果给浇灭了。出来的效果总是无缘无故多出一些点。经查,是因为我没有处理求出的像素值超过范围的情况。也即求出的像素值超过了255或小于0。解决方案就简单了,将大于255的改为255,小于0的改为0.