Wolfram | Alpha博客现在是Wolfram博客的一部分。加入我们,了解Wolfram | Alpha和其他Wolfram产品的最新信息»
迈克尔·特罗特

制定公式……适用于一切——从圆周率到粉红豹,再到艾萨克·牛顿爵士

2013年5月17日-
关闭注释

此处沃尔夫勒姆研究公司Wolfram|Alpha公司我们热爱数学和计算。我们最喜欢的主题是算法,其次是公式和方程式。例如,数学软件可以计算数百万(更准确地说,对于所有实际用途,无穷多)积分,Wolfram|Alpha知道数十万数学公式(来自欧拉公式圆周率的BBP型公式包含sin(x)的复定积分)以及大量的物理公式(例如波苏伊勒定律矩形中点粒子的经典力学解超球坐标4D中的反距离势),以及不太为人所知的公式,例如湿狗的抖动频率,的沙堡的最大高度,或火鸡的烹饪时间.

最近,我们为各种形状和形式添加了公式Wolfram|Alpha博客展示了一些通过数学方程式和不等式表示的形状示例。这些包括虚构人物曲线:

虚构人物曲线

形状曲线:

形状曲线

而且,最受用户欢迎的是,人的曲线:

人的曲线

虽然这些是数学意义上的曲线,类似于柠檬状的或a笛卡尔叶,与其说它们的数学特性有趣,不如说它们对人类的视觉意义有趣。

理查德的博客帖子发表后,我的一位同事问我,“你怎么能为斯蒂芬·沃尔夫拉姆的脸做一个等式?”对这个问题思考了一会儿后,我意识到真正令人惊讶的问题不是有一个公式:数字图像(为简单起见,假设是灰度图像)是灰度值的矩形数组。从这样的数组中,您可以构建插值函数,甚至是多项式。但这样一个显式函数将非常大,大小为数百页,对任何实际应用都没有用处。真正的问题是,如何制作一个结构简单、适合一页纸的、类似于人的脸的公式。描述斯蒂芬·沃尔夫拉姆脸的曲线公式大约有一页长,大约是一个复杂物理公式的大小,例如立方体的引力势.

找到斯蒂芬·沃尔夫拉姆面部曲线的公式

描述Stephen Wolfram面部的曲线公式

在这篇文章中,我想展示如何生成这样的方程。作为一个“如何计算…”,这篇帖子将毫不奇怪地包含相当多的数学软件代码,但我将从一些简单的介绍性解释开始。

假设你用铅笔在一张纸上画了一条线,假设你只画了线;没有阴影,也没有填充。然后从一组曲线段绘制图形。数学概念傅立叶级数允许我们为每个线段写下一个有限的数学公式,该公式与绘制的曲线非常接近。

作为一个简单的示例,考虑以下一系列函数n个(x个),

示例函数

它是各种频率和振幅的正弦函数的总和。以下是此函数序列的前几个成员:

求正弦函数的序列

正弦函数

绘制这个函数序列表明n个增加,n个(x个)接近三角形函数。

绘图[sinSums,{x,-Pi,Pi},PlotRange?All]

正弦函数序列图

正弦函数是一个奇函数,因此所有的项之和都是sin(k个 x个)也是奇数函数。如果我们使用余弦函数,我们可以得到偶数函数。正弦和余弦项的混合允许我们近似更一般的曲线形状。

概括上述内容(-1)(k个– 1)/2) k个-2正弦函数前面的前置符指向以下偶数或奇数函数,

新功能

允许我们建模更广泛的形状:

演示一般形状曲线

事实证明,任何平滑的曲线(x个)可以在任何区间上任意逼近[x个1,x个2]由傅里叶级数表示。对于平滑曲线,sin的系数(k个 x个)和cos(k个 x个)大型项目接近零k个.

现在给出一个参数化曲线γ(t吨) = {γx个(t吨),γ(t吨)},我们可以对水平分量独立使用正弦和余弦函数的这种叠加γx个(t吨)以及垂直构件γ(t吨). 对每个分量使用三个正弦函数和三个余弦函数的和,

水平和垂直分量的方程式

已经涵盖了各种形状,包括圆和椭圆。接下来的演示让我们探索可能形状的空间。2D滑块更改余弦函数前面的相应系数和正弦函数前面的系数。(将此帖子作为CDF下载以进行交互)

探索可能形状的空间

如果我们截断曲线的傅里叶展开式,例如,n个条款,我们有4个n个自由参数。在所有可能的曲线空间中,大多数曲线看起来都很无趣,但一些膨胀系数值会给出可识别的形状。然而,膨胀系数的微小变化已经迅速改变了形状。以下示例允许修改曲线的前4×16傅里叶级数系数(对于x个方向,另外16个用于方向)。使用适当的傅里叶系数值,我们可以获得各种可识别的形状。

允许修改曲线的前4×16傅里叶级数系数的示例

如果我们现在采用多条曲线,我们已经具备了构建人脸图像所需的所有成分。下面的演示使用两只眼睛、两只瞳孔、一个鼻子和一张嘴。

使用多条曲线构造面

这里有一个相反的快速演示:我们允许改变组成直线的一组点(蓝色十字)的位置,并绘制这条直线的傅里叶近似值。

允许一组点(蓝色十字)的位置形成一条要更改的线,并绘制该线的傅里叶近似值

旁注:傅里叶级数并不是编码曲线的唯一方法。我们可以使用小波基或样条曲线,或对曲线进行编码分段通过圆段或者,如果有足够的耐心,使用普遍性黎曼-泽塔函数,我们可以在临界带钢(是的,任何可能的[足够平滑的]图像,例如祝酒词上的耶稣,都会出现在黎曼zeta函数ζ的图像中()带材中0≤Re()≤1,但我们没有建设性的方法来搜索它。)

为了演示如何找到简单的、基于傅里叶级数的近似给定形状的公式,我们将从一个示例开始:边界清晰明确的形状——一个简短的公式。更具体地说,我们将使用一个众所周知的公式:毕达哥拉斯定理。

勾股定理类型集=持有形式[a^2+b^2==c^2];传统形式[风格[PythagoreanTheoremTypeset,60]]

a^2+b^2=c^2

光栅化方程式可以得到我们将要使用的起始图像。

光栅化方程式

a^2+b^2=c^2

使用函数很容易获得字符边缘上所有点的列表边缘检测.

EdgeDetect[image]//显示[#,ImageSize?240]&

字符的边缘

edgePoints={#2,-#1}&@@@位置[ImageData[EdgeDetect[image]],1,{2}];

现在我们有了构成边的点,我们想把它们连接成直线(或曲线)段。以下功能点列表到线条执行此操作。我们从一个随机选择的点开始,找到所有附近的点(使用函数最近的要快)。只要我们找到距离不太远的点,我们就继续这一进程。我们还试图继续以“直线”的方式,轻微惩罚急转弯。为了查看曲线构建的进展情况,我们使用监视器.

使用Monitor查看曲线构建进度

对于勾股定理,我们从边缘点获得了11条单独的曲线。

种子随机[22];hLines=点列表到线[edgePoints,6];长度[hLines]

11

将这些点连接起来,并对每个线段进行不同的着色,这表明我们得到了预期的曲线:字母的外部边界,字母的内部边界b条,三个正方形,以及加号和等号。

图形[{ColorData[“DarkRainbow”][RandomReal[]],线条[#]}&/@hLines]

a^2+b^2=c^2

现在,对于每个曲线段,我们想找到一个傅里叶级数(x个组件)近似于段。函数傅里叶系数的典型教科书定义(f)(x个)是函数的积分乘以cos(k个 x个)和罪恶(k个 x个). 但在这一点上,我们有一组点,而不是函数。为了将它们转换为我们可以集成的功能,我们制作了一个B类-每个曲线段的样条曲线。的参数化变量B类-样条曲线将作为积分变量。(使用B类-样条曲线而不是点之间的分段线性插值将具有使锯齿曲线更平滑的额外优势。)

图形[BSplineCurve[#,SplineDegree?6,SplineClosed?True]和/@hLines]

a^2+b^2=c^2

我们可以通过数值积分找到获得傅里叶系数所需的积分。一种更快的方法是使用快速傅里叶变换(快速傅里叶变换)得到傅里叶系数。

为了获得更均匀的曲线,我们再执行一个步骤:通过弧长对给定曲线段的样条插值曲线进行重新参数化。功能四层组件实现B类-样条曲线的绘制,通过弧长重新参数化,并通过FTT计算获得傅里叶系数。我们还考虑了曲线段是否打开或关闭,以避免吉布斯现象-相关振荡。(上面近似五角星的演示很好地显示了在未选中“关闭”复选框的情况下的吉布斯现象。)

按弧长重新参数化曲线

添加选项

fCs=fourierComponents[hLines,“OpenClose”?表[“Closed”,{Length[hLines]}]];

对于连续函数,我们期望平均衰减率为1/k个2对于k个第th个傅立叶级数系数。这就是刚刚计算出的傅里叶级数系数的情况。这意味着,与第一个傅里叶系数相比,第十个傅立叶系数的平均值仅为1%。这种衰减允许我们以不太高的阶数截断傅里叶级数,因为我们不想获得太大的公式。这个表达式给出了傅里叶分量衰减率的指数2+b条2=c(c)2曲线。(略低于2的指数来自B类-样条曲线。)

(平均值[#]±标准偏差[#])和[系数[Fit[Log[Rest[MapIndexed[{1#2[[1]],#1}&,#]]],{1,x},x]&/@Flatten[Abs[Flatten[#[2]],1]&/@分数,1],x,1]]//数字形式[#,3]&

-1.74 ± 0.233

这是前三条曲线的傅里叶级数系数绝对值的对数图。除了傅里叶系数近似二次衰减的一般趋势外,我们还发现,附近系数的幅度经常波动超过一个数量级。

构建前三条曲线的傅里叶级数系数绝对值的对数图

前三条曲线的傅里叶级数系数绝对值的对数图

傅里叶系数乘以cos(k个 t吨)和罪恶(k个 t吨)并且对这些项求和给出了曲线的期望参数化。

将傅里叶系数乘以cos(kt)和sin(kt

功能makeFourierSeriesApproximation操作将生成的曲线近似值可视化为序列截断顺序的函数。

使用函数makeFourierSeriesApproximationManipulate

对于毕达哥拉斯定理,从十几个椭圆开始,我们快速形成了傅里叶级数阶递增的不等式特征。

makeFourierSeries近似操作[fCs,50]

随着傅立叶级数阶数的增加而形成不等式的特征

我们需要整个方程的单一公式,即使公式是由不相交的曲线段组成的。为此,我们使用2π每个段的傅里叶级数的周期性,用于绘制参数范围[0,2的段π], [4π, 6π], [8π, 10π],…,并且在交织间隔(2π,第4页π), (6π, 8π),…,我们将曲线坐标设为纯虚坐标。因此,无法在那里绘制曲线,因此我们获得了不相交的曲线段。这里对两个圆的情况演示了这种结构:

使曲线坐标纯属虚构

绘制两个圆

两个圆的绘图

下一个图分别显示了复值参数化的实部和虚部。红线表示参数区间[2]中的纯虚值π,第4页π].

构建一个图,分别显示复值参数化的实部和虚部

独立显示复值参数化的实部和虚部的图

因为我们希望曲线的最终公式看起来尽可能短和简单,所以我们改变了形式的总和科斯(k个 t吨) +b条罪(k个 t吨)至A类罪(k个 t吨+φ)使用函数正弦振幅形式并将浮点傅里叶级数系数四舍五入到附近的有理数。而不是分段,我们使用UnitStep(单位步进)在最终公式中分离各个曲线段。我们以显式形式列出的实际段,以及所有不应绘制的段都通过θ(罪(t吨/2)(1/2)))术语。

使用函数sinAmplitudeForm

分离单个曲线段

现在我们把所有的东西都放在一起,写下最后的参数化{x个(t吨),(t吨)}毕达哥拉斯定理作为数学公式的排版形式。

finalCurve=合理化[单参数化[fCs,t,12],10^-3];短[最终曲线,12]//传统形式

最终配方

ParametricPlot[Evaluate[finalCurve],{t,0,12 4 Pi}]

参数化绘图

在讨论了参数化的主要构造思想之后,让我们看一个更有趣的示例,比如粉红色豹。查看的图像搜索结果必应Bing搜索引擎,我们很快就会找到一个看起来适合闭合形式“参数化。

搜索粉红豹图像

粉红豹的图像

让我们使用下图:

导入粉红豹图像

粉红色豹

我们应用该函数边缘检测找到黑豹脸上的所有边缘。

使用EdgeDetect

粉红豹图像的边缘

将边连接到曲线段可以产生大约20个线段。(更改的可选第二个和第三个参数点列表到线条,我们获得更少或更多的段。)

edgePoints={#2,-#1}&@@@位置[ImageData[pinkPatherEdgeImage],1,{2}];

种子随机[2];hLines=点列表到线[edgePoints,16];长度[hLines]

19

下面是用不同颜色显示的每个片段。我们看到一些闭合曲线是由两条相连的曲线段产生的;我们可以通过改变点列表到线条。但是为了绘制线条,连接的曲线会很好地工作。

图形〔{ColorData〔“DarkRainbow”〕〔RandomReal〔〕〕,Line〔#〕}和/@hLines〕

边缘显示为彩色

如前所述,通过三角级数近似曲线段很简单。

fCs=fourier组件[hLines];

绘制系列图表明,每段有20个术语,我们可以很好地表示粉红豹。

makeFourierSeries近似操作[fCs]

粉红豹的代表

构建图形网格

粉红豹图像的多个步骤

由于豹脸上的某些部分比其他部分更复杂,我们定义了一个函数makeSegmentOrder操作允许每个段的傅里叶级数的项数变化。这使我们可以进一步减少所产生的参数化的大小。

减小生成的参数化的大小

我们对傅里叶系数的数量使用初始设置,以生成清晰可识别的粉红豹图形。

一幅清晰可辨的粉红豹画

对于简单的情况,我们现在可以将上述所有函数汇总为一个函数。下一个函数制作轮廓四个结果将字符串作为参数。然后函数1)对Bing的图片网站对于此字符串;2) 从算法的角度选择一幅看起来合适的图像;3) 计算傅里叶级数;和4)作为傅里叶级数的结果图返回,并返回一个交互式版本,该版本允许我们更改傅里叶序列的顺序。为了简单起见,我们将程序限制为仅使用单个曲线。(在网络搜索中,我们使用单词“轮廓”来检索仅由一条曲线形成的图像。)由于该函数依赖于外部搜索引擎的结果,因此无法保证该函数始终返回所需的结果。

使用函数makeSilhouetteFourierResult

这里有三个例子展示了它的作用。我们为一只普通蜘蛛、蜘蛛侠蜘蛛、一对跳探戈的情侣和一条美人鱼建立了傅立叶级数。(评估这些函数可能会得到不同的结果,因为搜索引擎的结果可能会随着时间的推移而改变。)

makeSilhouetteFourierResult[“蜘蛛”,120]

蜘蛛

makeSilhouetteFourierResult[“蜘蛛侠标志蜘蛛”,180]

蜘蛛侠标志蜘蛛

makeSilhouetteFourierResult[“探戈”,160]

探戈

makeSilhouetteFourierResult[“美人鱼”,160]

美人鱼

到目前为止,初始线段是从图像中计算出来的。但我们也可以从手工绘制的曲线开始。假设我们想要一个公式艾萨克·牛顿由于我不擅长画脸,所以我有点作弊,用曲线绘制工具在艾萨克爵士的图像上绘制了特征面部和头发曲线。(有关如何从面提取要素线的算法方法,请参阅赵和朱.)这是我们将使用的图像:

导入Isaac Newton的图像

艾萨克·牛顿

幸运的是,手绘曲线中的小随机摆动无关紧要,因为它们将通过在傅里叶级数中省略高阶项来消除。

定义曲线AnnotatedNewtonImage

hLines=反向[SortBy[First/@Cases[curveAnnotatedNewtonImage,_Line,?],Length]];长度[hLines]

16

为了更好地看到手工绘制的曲线,我们将图像和线条分开。

分割图像和线条

Isaac Newton,显示线条

这一次,我们有16个部分。我们建立他们的傅里叶级数。

fCs=fourier组件[hLines];

这里又是生成曲线的各种近似阶数。

构建各种顺序的曲线

曲线的各种顺序

我们对不同的细分市场使用不同的系列订单。对于头发,我们使用相对较高的顺序,而对于眼睛,使用相对较低的顺序。这将确保生成的面方程不会大于所需的值。

makeSegmentOrderManipulate[fCs,newtonOrderList=Last/@{{1,12},{2,100},}3,60},{4,24},◄5,16},}6,16},{7,12},{8

创造艾萨克·牛顿面孔的方程组

以下是一个图形中显示的前50个近似值,曲线的不透明度降低,并且每组相应的曲线段以不同的颜色显示。

编译一张图中显示的前50个近似值

前50个近似值显示在一个图形中

这为艾萨克爵士的肖像画提供了以下最终曲线。

newtonCurve=合理化[单一参数化[fCs,t,newtonOrderList],0.002];样式[newtonCurve,6]//传统形式

艾萨克·牛顿肖像的最终曲线

这是最后一个公式的绘图形式。

ParametricPlot[Evaluate[N[newtonCurve]],{t,0,64 Pi},PlotPoints?240]

艾萨克·牛顿曲线

这就结束了今天关于如何制作与人的脸、虚构人物、动物或其他形状相似的曲线的讨论。下一次,我们将讨论这些公式产生的无尽的图形功能,以及如何在大量图像中使用这些类型的方程。

要与上述示例进行交互,首先,下载WolframCDF播放器.然后,下载这篇文章作为可计算文档格式(CDF)文件.

5条评论

这篇博客帖子太酷了!我无法想象手绘会像艾萨克·牛顿的头发那样复杂。

发布者咪咪·Y。2013年5月17日12:09 pm

太神了。

发布者彼得2013年5月17日下午1:06

接下来创建这样的字体并恢复METAFONT,Knuth会很高兴!

发布者自动_手动2013年5月17日下午6:11

此外,学术界是否有一些关于有损压缩方案的想法(但尚未在现实世界中变得相关)朝着这个方向发展?

发布者自动_手动2013年5月17日下午6:15

图形表示现实的精彩数学可视化!

发布者佩兰德A.Esplana2014年12月5日晚上10:20