贝塞尔曲线和B样条,bicubic(zz)

标签:
股票 |
分类: computerVision |
from
参考: 硕士论文1
相信很多同学都知道“贝塞尔曲线”这个词,我们在很多地方都能经常看到。但是,可能并不是每位同学都清楚地知道,到底什么是“贝塞尔曲线”,又是什么特点让它有这么高的知名度。
贝塞尔曲线的数学基础是早在 1912 年就广为人知的伯恩斯坦多项式。但直到
1959 年,当时就职于雪铁龙的法国数学家
正是因为控制简便却具有极强的描述能力,贝塞尔曲线在工业设计领域迅速得到了广泛的应用。不仅如此,在计算机图形学领域,尤其是矢量图形学,贝塞尔曲线也占有重要的地位。今天我们最常见的一些矢量绘图软件,如 Flash、Illustrator、CorelDraw 等,无一例外都提供了绘制贝塞尔曲线的功能。甚至像 Photoshop 这样的位图编辑软件,也把贝塞尔曲线作为仅有的矢量绘制工具(钢笔工具)包含其中。
贝塞尔曲线在 web 开发领域同样占有一席之地。CSS3 新增了
下面我们就通过例子来了解一下如何用 de Casteljau 算法绘制一条贝塞尔曲线。
在平面内任选 3 个不共线的点,依次用线段连接。http://htmljs.b0.upaiyun.com/uploads/1386078245509-bezier-quadratic-start.png
在第一条线段上任选一个点 D。计算该点到线段起点的距离 AD,与该线段总长 AB 的比例。http://htmljs.b0.upaiyun.com/uploads/1386078258661-bezier-quadratic-step1.png
根据上一步得到的比例,从第二条线段上找出对应的点 E,使得 AD:AB
= BE:BC
。http://htmljs.b0.upaiyun.com/uploads/1386078272369-bezier-quadratic-step2.png
连接这两点 DE。http://htmljs.b0.upaiyun.com/uploads/1386078284528-bezier-quadratic-step3.png
从新的线段 DE 上再次找出相同比例的点 F,使得 DF:DE
= AD:AB
= BE:BC
。http://htmljs.b0.upaiyun.com/uploads/1386078293828-bezier-quadratic-step4.png
到这里,我们就确定了贝塞尔曲线上的一个点 F。接下来,请稍微回想一下中学所学的极限知识,让选取的点 D 在第一条线段上从起点 A 移动到终点 B,找出所有的贝塞尔曲线上的点 F。所有的点找出来之后,我们也得到了这条贝塞尔曲线。http://htmljs.b0.upaiyun.com/uploads/1386078307084-bezier-quadratic-end.png
如果你实在想象不出这个过程,没关系,看动画!http://htmljs.b0.upaiyun.com/uploads/1415845715278-bezier-quadratic-animation.gif
回过头来看这条贝塞尔曲线,为了确定曲线上的一个点,需要进行两轮取点的操作,因此我们称得到的贝塞尔曲线为二次曲线(这样记忆很直观,但曲线的次数其实是由前面提到的伯恩斯坦多项式决定的)。
当控制点个数为 4 时,情况是怎样的?http://htmljs.b0.upaiyun.com/uploads/1386078421816-bezier-cubic-start.png
步骤都是相同的,只不过我们每确定一个贝塞尔曲线上的点,要进行三轮取点操作。如图,AE:AB
= BF:BC
= CG:CD
= EH:EF
= FI:FG
= HJ:HI
,其中点 J
就是最终得到的贝塞尔曲线上的一个点。http://htmljs.b0.upaiyun.com/uploads/1386078436764-bezier-cubic-points.png
这样我们得到的是一条三次贝塞尔曲线。http://htmljs.b0.upaiyun.com/uploads/1386078443819-bezier-cubic-end.png
在上面的曲线中,控制点的数目是很关键的,有的时候如果某个区域需要曲线填充,也可以把控制点增加到那个区域中去。
从图中可以看到,第一个和最后一个控制点总是最终的贝塞尔曲线上的点(固定点)。但是其它的控制点是用来调节曲线的形状的。比如使用三次贝塞曲线(cubic Bezier)进行近似。贝塞尔曲线有两个固定点(起点和终点),另加两个决定曲线形状的控制点(CP)。
from
考虑设计一个花瓶的剖面图。下图左边是11次(degree)的贝塞尔曲线;但是它很难弯曲瓶颈到线段 P4P5。当然,我们可以在这个线段附近增加控制点来增加该区域的权重。但是这会增加曲线的次数(degree)。许多情况下,不值得使用如此高次(degree)的多项式。
http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline//bs-motiv-3.jpg
看过了二次和三次曲线,更高次的贝塞尔曲线大家应该也知道要怎么画了吧。那么比二次曲线更简单的一次(线性)贝塞尔曲线存在吗?长什么样?根据前面的介绍,只要稍作思考,想必你也能猜出来了。哈!就是一条直线~http://htmljs.b0.upaiyun.com/uploads/1415845739049-bezier-linear-animation.gif
能画曲线也能画直线,是不是很厉害?要绘制更复杂的曲线,控制点的增加也仅仅是线性的。这一特点使其不光在工业设计领域大展拳脚,就连数学基础不好的人也可以比较容易地掌握,比如大多数平面美术设计师们。http://htmljs.b0.upaiyun.com/uploads/1415845756871-complex-bezier-curve.gif
上面介绍的内容并不足以展示贝塞尔曲线的真正威力。推广到三维空间的贝塞尔曲面,以及更进一步的非均匀有理 B 样条(NURBS),早已成为当今计算机辅助设计(CAD)的行业标准,不论是我们平常用到的各种产品,还是在电影院看到的精彩大片,都少不了它们的功劳。http://htmljs.b0.upaiyun.com/uploads/1386078496790-bezier-surface.png
http://htmljs.b0.upaiyun.com/uploads/1386078505773-industrial-design.png
动态绘制贝塞尔曲线的在线演示
from
from
最不能理解的一点,一讨论软件的曲面,曲线功能,最后就变成曲线、曲面的数学原理的讨论了,但是里面也没数学好的,讨论的结果可想而知。
我不是数学家,我不懂这么复杂的方程,只要好用就行了。
在CAD中,设计师需要设计出各种各样的曲线;数学中,曲线是通过各种各样的方程表示的,比如一条通过点A(0,0)、B(1,1)的直线可以表示为:
y=x
或者用参数方程表示:
再比如一个通过原点(1,2)、半径为2的圆可以表示为:
或者用参数方程表示:
上面举例的是两种很简单的曲线,对于更复杂的曲线可以用更复杂的方程来表示(比如用高次多项式);
如果我们的设计师是一位数学家就好了,他可以根据自己的需要,设计出一个复杂的方程来表示自己想要的一条优美的曲线,但是事与愿违,设计师们往往想通过一种直观的方式来设计曲线,而不是利用方程。
因此,诸位科学家和工程师设计出了Bezier曲线、B样条和NURBS,下面是一个有四个控制点的Bezier曲线:
http://p.blog.csdn.net/images/p_blog_csdn_net/wangzhi0417/bezier_nurbs_example.bmp
可以通过改变一个控制点的位置来改变曲线的形状,比如将上图曲线中左边第二个控制点往上移,就可以得到下面的曲线:
http://p.blog.csdn.net/images/p_blog_csdn_net/wangzhi0417/bezier_nurbs_example2.bmp
可以看到,这种曲线生成方式比较直观和灵活,我只需要放置控制点,然后调整控制点的位置来得到想要的曲线,这就避免了和复杂的数学方程打交道,岂不快哉?
实际上在最初的做法中,为了达到B样条的功能,可以使用多个贝塞尔曲线连接在一起的做法,但是必须保证连接点是连续的:
http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline//bs-motiv-3.jpg
Bezier曲线、B样条和NURBS都是根据控制点来生成曲线的,那么他们有什么区别了?简单来说,就是:
§
§
B样条克服了Bezier曲线的一些缺点,Bezier曲线的每个控制点对整条曲线都有影响,也就是说,改变一个控制点的位置,整条曲线的形状都会发生变化,而B样条中的每个控制点只会影响曲线的一段参数范围,从而实现了局部修改;
http://netclass.csu.edu.cn/NCourse/hep089/Chapter3/CG_Txt_3_016.htm
http://huaonline.iteye.com/blog/1069578
如图3.1.10所示,设P0、P02、P2是一条抛物线上顺序三个不同的点。过P0和P2点的两切线交于P1点,在P02点的切线交P0P1和P2P1于P01和P11,则如下比例成立:
http://netclass.csu.edu.cn/NCourse/hep089/Chapter3/CG_Gif_3_275.gif
http://netclass.csu.edu.cn/NCourse/hep089/Chapter3/312img/CG_Gif_3_010.gif
图3.1.10 抛物线三切线定理
这个就是如何画贝塞尔曲线的过程。
当P0,P2固定,引入参数t,令上述比值为t:(1-t),即有:当t=0的时候P01就是P0,当t=1的时候P01就是P1.当t>0.5时,靠近P1点,否则靠近P0点。这是和我们的观察一致的。
http://netclass.csu.edu.cn/NCourse/hep089/Chapter3/CG_Gif_3_276.gif
http://netclass.csu.edu.cn/NCourse/hep089/Chapter3/CG_Gif_3_277.gif
http://netclass.csu.edu.cn/NCourse/hep089/Chapter3/CG_Gif_3_278.gif
由此得到Bezier曲线的递推计算公式:
http://netclass.csu.edu.cn/NCourse/hep089/Chapter3/CG_Gif_3_279.gif
http://netclass.csu.edu.cn/NCourse/hep089/Chapter3/312img/CG_Gif_3_011.gif
图3.1.11 n=3时,Pin的递推关系
http://netclass.csu.edu.cn/NCourse/hep089/Chapter3/CG_Gif_3_280.gif长度为t:(1-t)的两段。依次对原始控制多边形每一边执行同样的定比分割,所得分点就是第一级递推生成的中间顶点Pi1(i=0,1,...,n-1),对这些中间顶点构成的控制多边形再执行同样的定比分割,得第二级中间顶点Pi2(i=0,1,...,n-2)。重复进行下去,直到n级递推得到一个中间顶点P0n即为所求曲线上的点P(t),如图3.1.12所示。
http://netclass.csu.edu.cn/NCourse/hep089/Chapter3/312img/CG_Gif_3_012.gif
图3.1.12 几何作图法求Bezier曲线上一点(n=3,t=1/4)
bezier曲线(又称貝茲曲線或贝塞尔曲线)的定义和性质请看维基百科貝茲曲線。它的定义是:
http://farm3.static.flickr.com/2522/4149447065_515b971535.jpg
其中,
http://farm3.static.flickr.com/2493/4149447231_836f1a330f.jpg,约定00
e Casteljau算法揭示了Bezier数学上很美的一个性质,我八成相信是先有了这个性质,才有了上面的定义式,当然它们是等价的。首先来看维基百科中的三张图:
二次Bezier曲线http://farm3.static.flickr.com/2671/4149447845_f29b211847_o.gif
三次Bezier曲线:http://farm3.static.flickr.com/2755/4149449087_122cfae235_o.gif
四次Bezier曲线:http://farm3.static.flickr.com/2670/4149449879_c449cbcedc_o.gif
这三张图展现了Bezier曲线漂亮的数学性质。图中的参数变量t的从0增长到1,红色的线就是Bezier曲线,Bezier曲线上的任一个点(t),都是其它相邻线段的同等比例(t)点处的连线,再取同等比例(t)的点再连线,一直取到最后那条线段的同等比例(t)处,该点就是Beizer曲线上的点(t). 以二次Bezier曲线为例,如该曲线上的1/3点,就是线段P0P1取1/3点,P1P2取1/3点,两点连线,再取其1/3点处即是。这就是de Casteljau算法提出来的,其数学表达式是一个递推公式(三角形,2点汇聚到一点):
http://farm3.static.flickr.com/2685/4150209650_aa0ff7a629.jpg
上式中,k表示第k层,以四次Bezier曲线为例,k=0时,就是灰色线段,k=1时,就是绿色线段,k=2就是蓝色线段,一直递推下去就是Bezier上的点(t)了。于是用de Casteljau算法很容易求出Bezier曲线上的任一点(t)的位置。换一种图示的方法表示这种递推关系:
http://farm3.static.flickr.com/2708/4150209822_497420a903.jpg
这是用几何画板画的,很难看,解释一下。左边一列是原来(k=0)的控制顶点,第二列是(k=1)的控制顶点,以此类推。每个箭头表示两个点分别乘以1-t和t并加起来,得到右边的点。这样一直做到最后的点就是Bezier上的点(t).
先看P0的系数为什么是,因为每次P0都是乘以(1-t)传到右边的点,这样一直传了n次到达最右端。仔细看一下就可以发现,最左边的点传递到最右边,是靠乘以一系列的t或1-t到达的,那么Pi的系数就是Pi走到最右边左右的"路"的系数之和。比如,P0只能一直走斜下的边,而且只有一条路,记住能不往左走,因此它的系数就是
。那么P1的系数就是
,因为它到最右边有两条路,且t和1-t的次数是一样的。可以发现每个Pi的每条路的t和1-t的次数都是一样的,而路的条数的系数很熟悉。没错,把上图逆时钟转90°就是杨辉三角了。
杨辉三角有这样的特征:每个数字表示从顶点走下来到该点不同走法的数目,而且无论是哪条路走到该点,向左和向右的次数是一样的,等于该点的二次多项式展开系数。
到了这里,如果看懂了的话,我想已经证明了,剩下就是一些说明性言语了。数学美还没结束,见下图:
http://farm3.static.flickr.com/2651/4149450537_f80aa00f3c.jpg
绿色线按顺序排列的点P0到P0n这n个点可以画出一条n次Bezier曲线,记为B1;蓝色的n个点也可以画出一条n次Bezier曲线;这两条曲线直接接起来,就是原来P0到Pn画出的n次Bezier曲线!神奇吧,它们居然有类似向量的性质。实际应用也是用这个性质,一般取t=1/2,将一条Bezier曲线变成两条小的,再继续分下去,当Bezier曲线足够小时就可以用线段代替曲线了。这个性质同样可以证明,但写到网上很麻烦就不写了,大家推荐好一点的数学画图软件,谢谢。数学有时很美。
贝塞尔曲线插值:目的就是插出一条贝塞尔曲线。
http://www.cnblogs.com/winter-cn/archive/2010/12/29/1919266.html
总结:从上面的分析可以知道,贝塞尔曲线上的点可以由控制点组成的模型来表示是,也就是说只要有控制点和参数就可以得到整个曲线的形状。
前面的例子中的一次贝塞尔曲线上的点满足下面的公式:和所有的控制点的函数。
t=0, P0
t=1
曲线不通过P1点。
http://netclass.csu.edu.cn/NCourse/hep089/Chapter3/CG_Gif_3_277.gif
在广义上,任何插值算法都可以认为是一种贝塞尔曲线的形式(如上面的公式中,控制点对应 neibor pixels,参数对应插值函数).
比如下面的一个例子就是这样的推广(len shading):
The Lens Shading compensation module is used to correct for the spatially variant illumination across the sensor due to imperfections in the optical system of the camera. It does this by evaluating a 3x3 array of bi-cubic patches which describe the 2-demensional spatial brightness variation across the surface of the sensor.
首先把一个图像打断成3x3的贝塞尔patch。 每一个patch使用4x4个control point(16个).
从图上可以看到,有些control point在几个patch之间有共享,因此实际的控制点的数目10x10=100个。
下面对于每一个patch中的插值:
比如现在要对红色的位置进行插值,这是一个分数位置。使用的控制点为16个。在video中我们也做过这种插值,H264的6-tap插值就是类似的。这里把它作为了一个贝塞尔理论:
P(x,y)
v = y / TOP_HEIGHT

从上面的例子可以看到,实际上它和贝塞尔曲线没什么关系,但是可以类比成特殊的贝塞尔曲线而已。
比如下面的例子:
y方向由y方向的3个控制点生成的贝塞尔曲线来模拟
在校正应用中,上面的图像校正后是一个正方形,在正方形上的每一个整数pixel都需要在distortion的图像中找到对应点,使用t作为在正方形图像上的水平位置的delta(比如整像素为1),通过距离t和上面的曲线公式就可以得到在曲线中对应的(x,y)。把这个位置上的pixel value填到正方形对应的位置上就完成了最终的校正。
可见这个曲线实际上就是校正前和校正后的图像对应的校正曲线函数。
注意到对于中间的点也是可以得到对应关系的(知道了在原图像中的x,y就可以用上面的公式来计算).
控制点在贝塞尔方程已经给出。可见,控制点实际上和正方形上的点是完全对应的(类似于给定的特征点)
t= 0 ,
t= 1,
t=1/2,
可见和实际的贝塞尔曲线相比,过了所有的控制点。实际上这个就是一个曲线插值算法,曲线的插值函数已经给定。
方程的硬件实现:因为t是按照原图像的pixel位置来扫描的,因此t的增量是可以知道和控制的:
但是如果每一个点都去这么按照公式去计算,那么计算量是很大的,为了降低计算量,使用了递推的方法来得到(利用前面一个的值+delta来得到后面这个位置的值). (sigma+delta的方法)
而dx/dtn 也可以使用递推,利用前面一个导数+delta来得到。
初始化值t=0时候的是已知的。
dx/dt0
二阶导数也是从上面的公式直接得到的。因为最大的指数就是2次,因此只有二阶导数,更高阶的都是0.
在校正中有2种方法,
一种称为前向投影,也就是以distortion的图像进行循环,对这个图像中的每一个整数像素点去校正后的图像中找应该在的位置,注意到distortion中的整数像素位置在校正后的图像中可能是分数位置,因此校正后的图像需要做插值。
这个方法的好处是:校正后的图像质量比较好。但是很难保证输出图像中没有hole(比如鱼眼图像中,有些pixel可能在校正图像中是没有对应的);要求read-modify-write(三个步骤:先读出来,再修改,再写回去)。
另外一种是后向投影,也就是假设有了校正后的图像,遍历校正后的图像中的每一个整数位置,在distortion的图像中去找对应点,同样,distortion图像中可能对应到分数位置,在distortion图像中去对这个分数位置进行插值,得到的结果pixel的value就是校正图像中这个整数像素位置的值。注意到:校正是从校正后的图像出发的,也就是按照校正后图像的整数pixel来扫描,去distortion图像中找对应点,大部分情况下,校正后图像的整数位置在distortion图像中是分数位置,因此才需要进行插值得到这些分数位置。
对于控制点实际上就是一些特征的对应点:
比如对于一个鱼眼校正,目标图像上的控制点是均匀的有规律的,容易描述:
Uniformly spaced – all patches are the same size.
Only need to program a single set of width, height, horizontal and vertical increments
通常是用来做插值,使得波形比较平滑。
from
之前 comp.graphic.algorithms
上有一个讨论,是关于怎么样使用曲线对多边形进行插值处理,使得最终产生的曲线是光滑的而且能通过所有的顶点。Gernot Hoffmann
建议说使用著名的 B-Spline 来进行插值。这里有他当时的文章
就是产生一个平滑的曲线通过多边形所有的顶点。
http://images.cnblogs.com/cnblogs_com/liyiwen/WindowsLiveWriter/AGG_11435/spline_polygon2_thumb.jpg
http://images.cnblogs.com/cnblogs_com/liyiwen/WindowsLiveWriter/AGG_11435/bezier_interpolation_thumb.jpg但我有个大胆的推测,我觉得肯定还存在更简单的方法。比如,使用三次贝塞曲线(cubic
Bezier)进行近似。贝塞尔曲线有两个固定点(起点和终点),另加两个决定曲线形状的控制点(CP)。关于贝塞尔曲线的更多知识可以在搜索引擎中找到,比如,你可以参考
B样条是从贝塞尔曲线的改进,在贝塞尔曲线中任何一个控制点的变化都会导致整个曲线的变化,为了限制这种变化到局部,因此希望能够对贝塞尔曲线进行分段(类似于多个贝塞尔曲线的连接),这样某个控制点的变化只会引起该段曲线的变化。
对比两个定义:B样条进行了分段
次数和控制顶点的数目无关,而贝塞尔曲线中,次数=控制顶点数目-1.这可以从基函数的定义上看出来。
从B样条基函数的定义可以知道,和样条的分段长度是有关系的,因此对于均匀样条来说是:每一段都是相同的基函数。
这是2D空间中常用的插值算法。一共使用了4x4的模板,也就是16个pixel插值一个点。最高次方为3次。
Bi-quadratic 算法 :使用3x3 模板,也就是9个点插值一个点,最高次方为2次方。