首页 > 学院 > 开发设计 > 正文

震撼!只能用这两个字了,真是奇女子

2019-11-08 20:00:32
字体:
来源:转载
供稿:网友

一千个圆零一个姑娘http://www.withparadox2.com/archives/90#comments

我参考Hanson在1960年发表的一篇论文(点击这里查看)做了这个动画。如果你看过我之前的一篇名为《图片迷宫》的文章,便不会对下面这位女同学感到陌生。与上次不一样,这一次我先征得了她的同意方才对照片进行了大刀阔斧的处理,由于手艺不好,勾勒出的人物效果也不尽人意,在此对她表达深深的歉意。

这个动画实际是一套行星圆系统,设想太阳不动,地球绕着太阳转,月球绕着地球转,XX绕着月球转……圆越多,得出的形状也就越复杂。Hanson在论文中论证了,如果给出的圆足够多,理论上是可以得出任何形状的轨迹线。下面简要介绍一下基本的制作步骤。

1,处理图片首先需要勾勒出线条图,最好能够一笔从头画到尾。但在这个图里,由于人物的眉毛、嘴巴的存在,没办法一笔画出来,我采取的办法是加上辅助线,最后作图时将辅助线抹掉。

然后通过下面这段代码将上面的位图转化为坐标,但这里线段的顺序是乱的,需要很大的耐心去手动调整。目前没找到好的方法。

pic = Import["location of your picture"];lcp = ListCurvePathPlot@   Position[ImageData[Thinning@Binarize[ColorNegate@pic]], 1];lines = Cases[lcp[[1, 1, 3]], _Line] /. {x_Real, y_Real} :> {y, -x};

2,复数及傅里叶变换下面仅简单介绍一下与本文有关的知识,更具体的内容参看其他资料。对于平面上的一点,可以用复数z=x+iy来表示,极坐标形式为z=reiθ。对于一个以坐标c=x+iy为圆心,以ρ为半径,以T为周期,以α为初始角的圆周运动,可用下式表示(其中t代表时间):

z=c+ρei(2πt/T+α)例如当t=t0时,点的坐标为:z=c+ρei(2πt0/T+α)=x+iy+ρ⋅cos(2πt/T+α)+iρ⋅sin(2πt/T+α)=(x+ρ⋅cos(2πt/T+α)+i(y+ρ⋅sin(2πt/T+α)))f(t)表示运动的点的轨迹,那么以此点为圆心做圆周运动的点可以表示为:z=f(t)+ρ1ei(2πt/T1+α1)对于N个圆,除了第一个圆心是固定点(c=x+iy)外,还剩下N个运动的点(除了N-1个运动的圆心,第N个圆上还有一个运动的点),由上可得出第N个圆上点的轨迹:z=c+∑k=1N−1ρkei(2πt/Tk+αk)事实上,这已经和复数的离散傅里叶变换有了绝大部分的相似,下面就越来越简单了。首先,将之前得到的图片坐标转化为复数坐标,即:(x,y)→x+iy,然后对这N个复数进行傅里叶变换,得到X[k],然后再用逆变换通过另一种形式得到原来的坐标:x[n]=∑k=0N−1X[k]ej2πkn/Nn/N=tk=1/Tk。上面ρk为实数,这里X[k]为复数,好像不一样。那是因为X[k]中既包括了半径,也包括了初始角,进一步变换可知:x[t]=∑k=0N−1X[k]ej2πt/Tk=X[0]+∑k=1N−1|X[k]|X[k]|X[k]|ej2πt/Tk=X[0]+∑k=1N−1|X[k]|ejαkej2πt/Tk=X[0]+∑k=1N−1|X[k]|ej(2πt/Tk+αk)=X[0]+∑k=1N−1|X[k]|ej(2πt/Tk+αk)这里的|X[k]|便是圆的半径,通过求和得到圆心坐标,当改变t(0⩽t⩽1),圆心坐标就会得到更新,从而生成连续动画。

在作图时,可以根据半径大小排序,将半径小的作为“笔尖”,并且可以去掉一些半径太小的圆。

3,一千个圆零一个姑娘【看原址,辣鸡CSDN传不上】


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表