Лекция Стивена Вольфрама

ВНИМАНИЕ!!!

БЛОГ ПЕРЕЕХАЛ НА НОВЫЙ АДРЕС https://blog.wolframmathematica.ru

Онлайн машина вычисления знаний Wolfram|Alpha ®

Онлайн машина вычисления знаний Wolfram|Alpha ®

вторник, 13 ноября 2012 г.

Создание GIF-анимации, видео и множественный экспорт иллюстраций в Wolfram Mathematica
Создание GIF-анимации, видео и множественный экспорт иллюстраций в Wolfram Mathematica
Общее количество использованных в посте встроенных функций или символов: 59

Список имен используемых встроенных функций и символов в порядке их появления в коде:
Plot3D | Times (*, ×) | Cos | Plus (+) | Power (^) | E (e) | List ({...}) | Rule (->, ->) | ImageSize | PlotRange | BoxRatios | Mesh | False | PlotPoints | AxesLabel | Map (/@) | Function (&) | Style | Slot (#) | Bold | Italic | AxesOrigin | Lighting | Orange | Show | Graphics3D | Sphere | PlotStyle | Specularity | White | Manipulate | Sin | Dashed | Thick | Red | Line | Table | Pi (π) | ViewPoint | SphericalRegion | True | ImagePadding | Axes | Boxed | CompoundExpression (;) | Set (=) | Block | ParallelTable | Export | StringJoin (<>) | FileByteCount | N | Apply (@@) | Divide (/, ÷) | Out (%) | CreateDirectory | ToString | Part ([[…]]) | Length
Часто появляется необходимость сохранить результаты расчета, которые являются некоторой изменяющейся в зависимости от параметра поверхностью, или графиком функции, вообще любой графической информацией в виде готовой GIF-анимации (скажем, чтобы вставить в свой сайт или презентацию, созданную в MS PowerPoint) или видео (например, чтобы выложить затем на YouTube), а может быть даже в виде большого количества  картинок для вставки в отчет о работе или научную статью.
Для этих в Mathematica предусмотрено много возможностей. Рассмотрим некоторые из них.
Создание графического объекта для последующего экспорта
Начнем с того, что создадим, собственно, некоторый динамический манипулятор, который будет представлять собой по сути то, что мы получим на выходе в виде, скажем, GIF-анимации (видео или набора картинок).
Построим некоторую поверхность, задаваемую, например, функцией f(x, y) = e^(-x/2 - y/2) cos(x^2 + y^2) на множестве x∈[-1.5; 2], y∈[-1.5; 2]. Для этого воспользуемся функцией Plot3D:
In[1]:=
Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}]
Out[1]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_1.gif
С помощью опции ImageSize зададим максимальный размер графика 500px:
In[2]:=
Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, ImageSize->500]
Out[2]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_2.gif
Зафиксируем диапазон построения
x∈[-1.5; 2], y∈[-1.5; 2], z∈[-4; 2]
с помощью опции PlotRange:
In[3]:=
Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, ImageSize->500, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}]
Out[3]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_3.gif
Изменим соотношение сторон прямоугольного параллелепипеда внутри которого происходит построение так, чтобы масштабы по осям были одинаковыми. Это можно сделать с помощью опции BoxRatios. Ясно, что соотношения сторон должны быть при этом такими:
{2 - (-1.5), 2 - (-1.5), 2 - (-4)} = {3.5, 3.5, 6}
In[4]:=
Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, ImageSize->500, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, BoxRatios-> {3.5, 3.5, 6}]
Out[4]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_4.gif
Уберем сетку, которая отображена на поверхности с помощью опции Mesh, присвоив ей значение False:
In[5]:=
Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, ImageSize->500, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, BoxRatios-> {3.5, 3.5, 6}, Mesh->False]
Out[5]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_5.gif
Чтобы улучшить качество отображения поверхности и избавиться от рудиментов интерполяции, увеличим количество начальных точек построения с помощью опции PlotPoints:
In[6]:=
Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, ImageSize->500, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, BoxRatios-> {3.5, 3.5, 6}, Mesh->False, PlotPoints->80]
Out[6]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_6.gif
С помощью опции AxesLabel добавим подписи к координатным осям:
In[7]:=
Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, ImageSize->500, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, BoxRatios-> {3.5, 3.5, 6}, Mesh->False, PlotPoints->80, AxesLabel-> {"x", "y", "z"}]
Out[7]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_7.gif
Изменим их стиль. Для этого используем функцию Style, и созданную на ее основе чистую функцию
Style[#, 20, Bold, Italic] & .
Кратко напомню о используемом здесь синтаксисе:
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_8.gif
In[8]:=
Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, ImageSize->500, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, BoxRatios-> {3.5, 3.5, 6}, Mesh->False, PlotPoints->80, AxesLabel-> (Style[#, 20, Bold, Italic] &/@{"x", "y", "z"})]
Out[8]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_9.gif
Зафиксируем начало координат в точке {2, 2, 2} с помощью опции  AxesOrigin:
In[9]:=
Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, ImageSize->500, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, BoxRatios-> {3.5, 3.5, 6}, Mesh->False, PlotPoints->80, AxesLabel-> (Style[#, 20, Bold, Italic] &/@{"x", "y", "z"}), AxesOrigin-> {2, 2, 2}]
Out[9]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_10.gif
Добавим точечный источник света цвета  Orange (в модели RGB — 255, 128, 0) в точке {1, 1, 1} c помощью опции Lighting:
In[10]:=
Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, ImageSize->500, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, BoxRatios-> {3.5, 3.5, 6}, Mesh->False, PlotPoints->80, AxesLabel-> (Style[#, 20, Bold, Italic] &/@{"x", "y", "z"}), AxesOrigin-> {2, 2, 2}, Lighting-> {{"Point", Orange, {1, -1, 1}}}]
Out[10]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_11.gif
Пометим этот точечный источник, чтобы видеть где он находится, сферой радиуса 1/20.
Для этого соединим графический трехмерный примитив - сферу, задаваемую конструкцией:
Graphics3D[Sphere[{1, -1, 1}, 1/20]]
вместе с полученным ранее графиком через функцию  Show:
In[11]:=
Show[{Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, ImageSize->500, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, BoxRatios-> {3.5, 3.5, 6}, Mesh->False, PlotPoints->80, AxesLabel-> (Style[#, 20, Bold, Italic] &/@{"x", "y", "z"}), AxesOrigin-> {2, 2, 2}, Lighting-> {{"Point", Orange, {1, -1, 1}}}], Graphics3D[Sphere[{1, -1, 1}, 1/20]]}]
Out[11]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_12.gif
Вынесем настройки освещения и диапазона построения из тела функции Plot3D в тело функции Show. Это стоит сделать ввиду того, что объединяются графические объекты, у которых эти настройки различны. После этого, у нового графического объекта эти настройки будут едины.
In[12]:=
Show[{Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, Mesh->False, PlotPoints->80], Graphics3D[Sphere[{1, -1, 1}, 1/20]]}, BoxRatios-> {3.5, 3.5, 6}, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, ImageSize->500, AxesLabel-> (Style[#, 20, Bold, Italic] &/@{"x", "y", "z"}), AxesOrigin-> {2, 2, 2}, Lighting-> {{"Point", Orange, {1, -1, 1}}}]
Out[12]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_13.gif
Добавим настройки “зеркальности” (отражения) к построенной нами поверхности с помощью опции PlotStyle и функции Specularity:
In[13]:=
Show[{Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, Mesh->False, PlotPoints->80, PlotStyle-> {Specularity[White, 50]}], Graphics3D[Sphere[{1, -1, 1}, 1/20]]}, BoxRatios-> {3.5, 3.5, 6}, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, ImageSize->500, AxesLabel-> (Style[#, 20, Bold, Italic] &/@{"x", "y", "z"}), AxesOrigin-> {2, 2, 2}, Lighting-> {{"Point", Orange, {1, -1, 1}}}]
Out[13]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_14.gif
Теперь, сделаем так, чтобы источник света двигался по круговой траектории и визуализируем эту траекторию.
К сфере добавим графический примитив Line - который задаст линию, проходящую через набор точек, сделаем эту линию пунктирной (Dashed), жирной (Thick) и красной  (Red).
Координаты источника света будут определяться соотношением:
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_15.gif
Изменив стационарные координаты источника света на новые, и добавив траекторию движения источника света, создадим динамический манипулятор с помощью функции Manipulate:
In[14]:=
Manipulate[Show[{Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, Mesh->False, PlotPoints->80, PlotStyle-> {Specularity[White, 50]}], Graphics3D[{Sphere[3/2 {Cos[angle], Sin[angle], 1}, 1/20], {Dashed, Thick, Red, Line[Table[3/2 {Cos[angle], Sin[angle], 1}, {angle, 0, 2Pi, Pi/20}]]}}]}, BoxRatios-> {3.5, 3.5, 6}, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, ImageSize->500, AxesLabel-> (Style[#, 20, Bold, Italic] &/@{"x", "y", "z"}), AxesOrigin-> {2, 2, 2}, Lighting-> {{"Point", Orange, 3/2 {Cos[angle], Sin[angle], 1}}}], {{angle, 0, "Угол падения освещения:"}, 0, 2Pi}]
Out[14]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_16.gif
Добавим возможность контролировать направление обзора поверхности с помощью еще одного слайдера, для этого зададим через опцию ViewPoint точку, из которой мы будем смотреть на поверхность и добавим новый параметр к созданному ранее манипулятору:
In[15]:=
Manipulate[Show[{Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, Mesh->False, PlotPoints->80, PlotStyle-> {Specularity[White, 50]}], Graphics3D[{Sphere[3/2 {Cos[angle], Sin[angle], 1}, 1/20], {Dashed, Thick, Red, Line[Table[3/2 {Cos[angle], Sin[angle], 1}, {angle, 0, 2Pi, Pi/20}]]}}]}, BoxRatios-> {3.5, 3.5, 6}, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, ImageSize->500, AxesLabel-> (Style[#, 20, Bold, Italic] &/@{"x", "y", "z"}), AxesOrigin-> {2, 2, 2}, Lighting-> {{"Point", Orange, 3/2 {Cos[angle], Sin[angle], 1}}}, ViewPoint->3/2 {Cos[angle2], Sin[angle2], 1/2}], {{angle, 0, "Угол падения освещения:"}, 0, 2Pi}, {{angle2, 5Pi/3, "Направление обзора поверхности:"}, 0, 2Pi}]
Out[15]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_17.gif
Поместим наш объект в сферу для того, чтобы предотвратить изменение размеров диапазона отображения при вращении, сделать это можно с помощью опции SphericalRegion, а также добавим рамку к изображению с помощью опции ImagePadding для того, чтобы ограничивающий параллелепипед не выходил за диапазон отображения объекта.
In[16]:=
Manipulate[Show[{Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, Mesh->False, PlotPoints->80, PlotStyle-> {Specularity[White, 50]}], Graphics3D[{Sphere[3/2 {Cos[angle], Sin[angle], 1}, 1/20], {Dashed, Thick, Red, Line[Table[3/2 {Cos[angle], Sin[angle], 1}, {angle, 0, 2Pi, Pi/20}]]}}]}, BoxRatios-> {3.5, 3.5, 6}, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, ImageSize->500, AxesLabel-> (Style[#, 20, Bold, Italic] &/@{"x", "y", "z"}), AxesOrigin-> {2, 2, 2}, Lighting-> {{"Point", Orange, 3/2 {Cos[angle], Sin[angle], 1}}}, ViewPoint->3/2 {Cos[angle2], Sin[angle2], 1/2}, SphericalRegion->True, ImagePadding->50], {{angle, 0, "Угол падения освещения:"}, 0, 2Pi}, {{angle2, 5Pi/3, "Направление обзора поверхности:"}, 0, 2Pi}]
Out[16]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_18.gif
Добавим к манипулятору возможность убирать оси и ограничивающий параллелепипед (опции Axes и  Boxed), сделаем так, чтобы по умолчанию оси и параллелепипед не показывались:
In[17]:=
Manipulate[Show[{Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, Mesh->False, PlotPoints->80, PlotStyle-> {Specularity[White, 50]}], Graphics3D[{Sphere[3/2 {Cos[angle], Sin[angle], 1}, 1/20], {Dashed, Thick, Red, Line[Table[3/2 {Cos[angle], Sin[angle], 1}, {angle, 0, 2Pi, Pi/20}]]}}]}, BoxRatios-> {3.5, 3.5, 6}, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, ImageSize->500, AxesLabel-> (Style[#, 20, Bold, Italic] &/@{"x", "y", "z"}), AxesOrigin-> {2, 2, 2}, Lighting-> {{"Point", Orange, 3/2 {Cos[angle], Sin[angle], 1}}}, ViewPoint->3/2 {Cos[angle2], Sin[angle2], 1/2}, SphericalRegion->True, ImagePadding->50, Axes->axesTF, Boxed->boxTF], {{angle, 0, "Угол падения освещения:"}, 0, 2Pi}, {{angle2, 5Pi/3, "Направление обзора поверхности:"}, 0, 2Pi}, {{axesTF, False, "Показывать оси поординат?"}, {True, False}}, {{boxTF, False, "Показывать ограничивающий параллелепипед?"}, {True, False}}]
Out[17]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_19.gif
Создание GIF-анимации
Возьмем созданный выше динамический манипулятор, который является по сути интерактивным приближением к тому объекту, что мы получим в виде GIF-анимации немного позже.
Получим на его основе набор картинок, которые затем выгрузим в виде GIF-анимации, показывающей, как меняется освещение поверхности при движении точечного источника света (т. е. при изменении параметра angle), при этом значения параметров angle2, axesTF, boxTF возьмем равными их значениям по умолчанию в манипуляторе, для этого заменим Manipulate на  ParallelTable (функция, аналогичная Table, но распараллеливающая вычисления на все ядра процессора, что способно ускорить выполнение кода в несколько раз) и используем ограничивающую конструкцию  Block. Для того, чтобы GIF-анимация была плавной, возьмем значения переменной angle с шагом, например, π/50. Полученному набору изображений присвоим имя graphicsData1 и предотвратим вывод результатов с помощью функции CompoundExpresiion (;).
In[18]:=
graphicsData1 = Block[{angle2 = 5Pi/3, axesTF = False, boxTF = False}, ParallelTable[Show[{Plot3D[Cos[x^2 + y^2] E^(-x/2 - y/2), {x, -1.5, 2}, {y, -1.5, 2}, Mesh->False, PlotPoints->80, PlotStyle-> {Specularity[White, 50]}], Graphics3D[{Sphere[3/2 {Cos[angle], Sin[angle], 1}, 1/20], {Dashed, Thick, Red, Line[Table[3/2 {Cos[angle], Sin[angle], 1}, {angle, 0, 2Pi, Pi/20}]]}}]}, BoxRatios-> {3.5, 3.5, 6}, PlotRange-> {{-1.5, 2}, {-1.5, 2}, {-4, 2}}, ImageSize->500, AxesLabel-> (Style[#, 20, Bold, Italic] &/@{"x", "y", "z"}), AxesOrigin-> {2, 2, 2}, Lighting-> {{"Point", Orange, 3/2 {Cos[angle], Sin[angle], 1}}}, ViewPoint->3/2 {Cos[angle2], Sin[angle2], 1/2}, SphericalRegion->True, ImagePadding->50, Axes->axesTF, Boxed->boxTF], {angle, 0, 2Pi, Pi/50}]] ;
Экспортируем полученный набор картинок в виде GIF-анимации с помощью функции Export:
In[19]:=
Export["C:\\Users\\Roman\\Desktop\\myNotFirstAnimation.gif", graphicsData1]
Out[19]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_20.gif
После расчета, в указанной вами директории будет создан файл с указанным вами именем - ваша готовая GIF-анимация:
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_21.gif
Теперь, вы можете использовать ее где угодно, например вставить в веб-страницу, как это сделано ниже:
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_22.gif
Создание видео
Создание видео полностью аналогично.
Создадим несколько видео-файлов, например, в формате .flv и .avi:
In[20]:=
Export["C:\\Users\\Roman\\Desktop\\myNotFirstVideo."<>#, graphicsData1] &/@{"avi", "flv"}
Out[20]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_23.gif
После расчета, в указанной вами директории будут созданы файлы с указанными вами именами:
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_24.gif
Теперь, вы можете использовать видео где угодно, например вставить в веб-страницу, предварительно загрузив его на свой канал YouTube:
ВАЖНО ПОМНИТЬ, что сохранять видео в формате flv часто более целесообразно, так как файлы в формате avi часто получаются крайне “тяжелыми”.
Скажем, в данном случае размеры полученных файлов таковы:
In[21]:=
FileByteCount["C:\\Users\\Roman\\Desktop\\myNotFirstVideo."<>#] &/@{"avi", "flv"}
Out[21]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_25.gif
Т. е. Они отличаются более чем в 34 раза:
In[22]:=
N[Divide @@ %]
Out[22]=
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_26.gif
Множественный экспорт иллюстраций
Настроим автоматический экспорт изображений с разными именами в некоторую директорию.
Для этого изменим код, осуществлявший экспорт данных в виде GIF-анимации следующим образом:
In[23]:=
newDirectory = "C:\\Users\\Roman\\Desktop\\IMAGES\\" ; CreateDirectory[newDirectory] ; ParallelTable[Export[newDirectory<>"myImage-"<>ToString[i] <>".png", graphicsData1[[i]]], {i, Length[graphicsData1]}] ;
После расчета, в указанной вами директории, которая была создана с помощью функции CreateDirectory, будут созданы файлы с указанными вами именами:
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_27.gif
Sozdanie_GIF-animacii_video_v_Wolfram_Mathematica_28.gif

Блог принадлежит “Русскоязычной поддержке Wolfram Mathematica
При любом использовании материалов блога, ссылка на блог обязательна.
SpikeyСоздано с помощью Wolfram Mathematica 8

3 комментария:

  1. Спасибо большое, очень полезная статья. Пол года назад :) выступал на конференции, всю анимацию пришлось делать вручную через спец. программки тогда очень долго маялся и качество получилось ужасное. А оказывается это все Mathematica может.

    ОтветитьУдалить
  2. Спасибо. Ну очень подробно расписано ;-) Не самая интересная задача, но для начинающих, думаю, будет очень полезно.

    ОтветитьУдалить
  3. большое спасибо, изучаю "математику" сама и Ваш блог ОЧЕНЬ помогает!

    ОтветитьУдалить