欢迎光临散文网 会员登陆 & 注册

【Aegisub】吐血奉献!!根据离散点拟合贝塞尔曲线

2022-06-02 12:10 作者:多华宫与火火里  | 我要投稿

        首先先看两个图,图1.01在经过函数处理以后就得到图1.02了:

图1.01
图1.02

将折线给重新拟合回了曲线,这应该能想到很多种用处吧?比如做碎片字幕时,得到的碎片绘图会是一堆全直线绘图,这就意味着字幕的文本量会很大,而且全是折线的绘图可能不太光滑,但是将折线拟合回曲线以后,绘图不仅变得更加光滑了,而且文本量得到了极大的简化!比如你看图1.03这个原本的碎片绘图,将其用拟合函数处理后,就会得到图1.04

图1.03
图1.04

当然这两个绘图代码里的数都不是整数,只是放进assdraw里就取整了,所以有一些重合的点(就是说其实本身这两个绘图代码的结果都是保留了两位小数的),然后碎片在屏幕里是图1.05这样的

图1.05

图1.05的第一行是经过拟合后的碎片绘图,而第二行是全直线的碎片绘图

        除了碎片绘图能用到拟合函数以外,在做流畅变形效果时,也可以把一个有一堆直线的绘图给重新变为曲线,如图1.06拟合后就是图1.07

图1.06
图1.07

比如如果你用直线绘图变形来做波浪,那么这个函数就相当有用,图1.08就可以你拟合得到图1.09

图1.08
图1.09

用一个完整的字来看会很清楚,拟合效果很好,文本量节约很多,如图1.10变到图1.11

图1.10
图1.11

然后图1.12是对比,第一行是全直线绘图,第二行是拟合后的绘图

图1.12

拟合函数也没用什么复杂的东西,你只要明白矩阵、牛顿迭代、最小二乘法即可。代码在相应的视频里讲


        然后,关于拟合曲线还要说明一下。比如有一堆数据,你想根据这堆数据拟合贝塞尔曲线,比如3个点要你拟合一个曲线,那么讲道理拟合的曲线就差不多是图1.13这样

图1.13

拟合曲线就是得到相应的曲线使得原本的数据点尽可能的靠近拟合的曲线。也就是说,如果你用线段把各个点连起来得到一条折线,这条折线的形状看起来很有可能和拟合出的曲线是有一定区别的,如图1.14,这并不意味着拟合曲线是错的,而是拟合曲线的本意本来就不是让曲线的形状接近用线段连接数据点得到的折线,而是拟合出一条足够贴近原本数据点的光滑曲线

图1.14

但是做特效的话,就需要拟合出的结果和绘图原本的形状几乎一样,那么这样就要增加代码,使拟合结果更理想,所以我写了两个函数,第一个是专门拟合曲线用的函数,第二个就是专门用来拟合出形状几乎一样的绘图的函数。

        那么怎么样让拟合出的曲线和折线形状几乎一样呢,这很简单,增加可以判断的点即可,比如线段的中点和你拟合曲线上相应的点的距离是否在允许范围内,如图1.15

图1.15

如果D和E不够接近或者F和G不够接近,那么就拆分数据点(比如有9个数据点,根据情况拆分后就是一组3个一组6个数据点,当然这是举例子,拆分是根据情况拆分的,你哪个点不满足你设定的误差,你就在哪个点拆开这组数据),拆分后再来一组组尝试拟合(当然会拟合出多条曲线了)。不过有的时候,就每段增加一个中点来判断是不够的,比如线段很长的时候,只增加这一个点判断曲线和折线形状是否接近是不够的,就像图1.16这样

图1.16

图1.16一共3个点,然后增加了中点D、E,可就算增加了点,拟合曲线还是和A、B、C连成的折线有不小的区别。所以这种就分情况处理即可,当线段短一点的时候,可以不增加点辅助判断或者就增加中点来辅助判断,而线段长一点的时候,就多增加几个点来判断即可,分别取线段上0.25处、0.5处、0.75处的点,它们一起来辅助判断即可。这样就会有很好的拟合效果了

如果只是长一点的线段才用增加点来辅助判断的话,那么在线段较短时,也有可能出现一些问题,如图1.17,拟合的曲线和这线段的形状还是不一样

图1.17
图1.17

只是举个例子,实际情况下只是说有可能出现类似的情况。现在这个曲线就是一个波浪状的样子,和线段的形状差距很大。(曲线看起来不太看得清楚,可以大概理解为下图这样的形状)

遇到这种情况,只有可能就是线段太短,此时可以直接判断你拟合出的曲线相比你的线段来说是不是大过头了。求出曲线的边界框的宽w和高h、求出折线的边界框的宽w1和高h1,如果w1不为0且w比w1大好几倍或者h1不为0且h比h1大好几倍,那自然说明这拟合出的曲线是不合格的,于是当然就要拆开数据点了



(本文写于2021年8月5日)

【Aegisub】吐血奉献!!根据离散点拟合贝塞尔曲线的评论 (共 条)

分享到微博请遵守国家法律