Date Редакция Категория sci Теги matlab

Пример 1: пошаговое построение анимированной картинки

1. Нарисуем картинку

x = 0:0.01:1;
y = x;
plot(x,y)

2. Захватим кадр

f = getframe;

3. Преобразуем полноцветное изображение в палитровое

Полноцветное изображение хранится в f.cdata. Оно имеет размер NxMx3. Вместо него получаем палитровое изображение im размера NxM, цвет каждого пиксела которого определяется цветовой картой (палитрой) map. 256 — ограничение на количество цветов в палитре (больше нам не нужно).

[im,map] = rgb2ind(f.cdata,256);

4. Задаем массив, в котором будем хранить кадры анимации

im(1,1,1,10) = 0;

Результатом работы rgb2ind может быть двумерный или четырехмерный массив. Так что введение дополнительного (третьего) измерения — дело вынужденное. Значение индекса четвертого измерения (10) — количество кадров будущей анимации. Таким образом мы заранее резервируем место под массив im.

5. Цикл рисования и запоминания кадров

Рисуем очередной кадр, захватываем его (getframe) и добавляем в массив im.

for k = 1:10
  y = x.^k;
  plot(x,y)
  f = getframe;
  im(:,:,1,k) = rgb2ind(f.cdata,map);
end

6. Записываем полученную анимацию в файл

(:source lang=scilab:) imwrite(im,map,'test.gif','DelayTime',0,'LoopCount',inf)

`DelayTime`  определяет время задержки между кадрами анимации, `LoopCount` задает число повторений. Один раз анимация воспроизводится всегда, так что `LoopCount=0` означает, что анимация будет воспроизведена один раз, при `LoopCount=1` анимация выполняется дважды и т.д. `LoopCount=inf` зацикливает анимацию (повторяет ее бесконечное число раз).

**Теперь все вместе:**

```matlab
x = 0:0.01:1;
y = x;
plot(x,y)
f = getframe;
[im,map] = rgb2ind(f.cdata,256);
im(1,1,1,10) = 0;
for k = 1:10
  y = x.^k;
  plot(x,y)
  f = getframe;
  im(:,:,1,k) = rgb2ind(f.cdata,map);
end
imwrite(im,map,'test.gif','DelayTime',0,'LoopCount',inf)

Получаем:

Пример gif-анимации, выполненной в MATLAB

Пример 2: еще один способ создания анимации

Если нам понадобится дробные показатели степени, нужно будет ввести еще один индекс для элементов массива im, вместо k. Другой вариант — создать первый кадр изображения и постепенно добавлять к нему новые кадры.

x = 0:0.01:1;
y = x;
plot(x,y)
f = getframe;
[im,map] = rgb2ind(f.cdata,256);
filename = 'test.gif';
imwrite(im,map,filename,'DelayTime',0,'Loopcount',inf);
for k = 1:0.5:5
  y = x.^k;
  plot(x,y)
  drawnow
  f = getframe;
  [im,map] = rgb2ind(f.cdata,256);
  imwrite(im,map,filename,'DelayTime',0,'WriteMode','Append');
end

Gif-анимация функции из примера 1, выполненная другим способом

Можно поместить оба imwrite в цикл, проверяя номер итерации: для первой итерации создается графический файл, для остальных в него добавляются кадры:

outfile = 'out.gif';

for i = 1:50

    plot;

    ...

    frame = getframe(1);
    im = frame2im(frame);
    [imind,cm] = rgb2ind(im,256);

    % На первой итерации создается файл, на остальных добавляются кадры.
    if i == 1
        imwrite(imind,cm,outfile,'gif','DelayTime',0,'LoopCount',inf);
    else
        imwrite(imind,cm,outfile,'gif','DelayTime',0,'WriteMode','append');
    end

end

С помощью такого подхода реализована анимация простых методов сортировки.

Пример 3: анимация поверхности

Основная идея — та же, что и в примере 1.

Z = peaks;
surf(Z)
axis tight
set(gca,'nextplot','replacechildren')
f = getframe;
[im,map] = rgb2ind(f.cdata,256);
im(:,:,1,20) = im;
for k = 1:20
  surf(cos(2*pi*k/20)*Z,Z)
  f = getframe;
  im(:,:,1,k) = rgb2ind(f.cdata,map);
end
imwrite(im,map,'test.gif','DelayTime',0,'LoopCount',inf)

Самое интересное в этом примере находится в строках:

axis tight
set(gca,'nextplot','replacechildren')

Первая не позволяет изменится размеру кадра. Вторая — стирает изображение в текущих координатных осях, не изменяя при этом остальных свойств осей (принятое по умолчанию для nextplot значение replace "сбрасывает" все свойства осей в их значения по умолчанию).

Анимация поверхности

Пример 4: анимация нескольких графиков в разных координатных осях

x=0:pi/10:4*pi; % х-координата
y1=sin(x);      % функция для одной анимации
y2=cos(x);      % функция для другой анимации

fig = figure();
% создание первого пустого кадра
set(fig,'Position',[350,200,700,300]);
frame = getframe(fig);
[im,map] = rgb2ind(frame.cdata,4);
imwrite(im,map,'animation1.gif','DelayTime',0,'Loopcount',0);

% цикл анимации
for i=1:length(x)  
    subplot(2,1,1);
    plot(x(i),y1(i),'.');
    xlim([0, 4*pi]);
    ylim([-1, 1]);        
    hold on;

    subplot(2,1,2);
    plot(x(i),y2(i),'.');
    xlim([0, 4*pi]);
    ylim([-1, 1]);        
    hold on;

    frame = getframe(fig);
    [im,map] = rgb2ind(frame.cdata,4);
    imwrite(im,map,'animation1.gif','DelayTime',0.1,'WriteMode','Append');
end;

Анимация нескольких графиков в разных координатных осях

Пример 5: анимация нескольких графиков в общих координатных осях

x=0:pi/10:4*pi; % х-координата
y1=sin(x);      % функция для одной анимации
y2=cos(x);      % функция для другой анимации

fig = figure();
% создание первого пустого кадра
set(fig,'Position',[350,200,700,300]);
axes('xlim',[0 4*pi],'ylim',[-1 1],'NextPlot','add','Parent',fig);
frame = getframe(fig);
[im,map] = rgb2ind(frame.cdata,4);
imwrite(im,map,'animation2.gif','DelayTime',0,'Loopcount',0);

% цикл анимации
for i=1:length(x)  
    plot(x(i),y1(i),'.');
    plot(x(i),y2(i),'r.');

    frame = getframe(fig);
    [im,map] = rgb2ind(frame.cdata,4);
    imwrite(im,map,'animation2.gif','DelayTime',0.1,'WriteMode','Append');
end;

Анимация нескольких графиков в общих координатных осях

Пример 6: анимация нескольких поверхностей

Объединим результаты примеров 3 и 4.

fig = figure();
% создание первого пустого кадра
set(fig,'Position',[350,200,700,700]);
frame = getframe(fig);
[im,map] = rgb2ind(frame.cdata,4);
imwrite(im,map,'animation3.gif','DelayTime',0,'Loopcount',0);

% создание тестовой поверхности
Z = peaks;

% цикл анимации
for i=1:100
    subplot(2,1,1);
    surf(cos(pi*i/20)*Z,Z)
    xlim([0, 50]);
    ylim([0, 50]);
    zlim([-10, 10]);
    hold on;

    subplot(2,1,2);
    surf((sin(pi*i/20)-cos(pi*i))*Z,Z)
    xlim([0, 50]);
    ylim([0, 50]);            
    zlim([-20, 20]);
    hold on;

    frame = getframe(fig);
    [im,map] = rgb2ind(frame.cdata,4);
    imwrite(im,map,'animation3.gif','DelayTime',0.1,'WriteMode','Append');
end;

Обратите внимание, что здесь Loopcount=0, так что анимация будет выполняться один раз.

Здесь может возникнуть следующая проблема: некоторое программы просмотра графических файлов, например, IrfanView, сами по умолчанию зацикливают анимацию. Так что если в результате выполнения этого примера вы получите зацикленную анимацию, то просто смените программу просмотра, например, на браузер.*

Анимация нескольких поверхностей в различных осях



Комментарии

comments powered by Disqus