2017-01-29 17 views
0

Я хочу, чтобы моя функция возвращала один < class 'matplotlib.image.AxesImage' > тип объекта после показа двух < class 'matplotlib.image.AxesImage' > с imshow:Python imshow: как получить слияние двух <class 'matplotlib.image.AxesImage'> в один?

def merge_class(array1,array2): 
    plt.imshow(array1) 
    plt.imshow(array2) 
    return ? 

Как я могу это сделать?

Я слышал, что могу сохранить всю фигуру, а затем вызвать файл в своей программе, но я хочу этого избежать.

Я также видел, что я мог бы объединить эти объекты, но я не понимаю, что они делают: Python : How to "merge" two class

EDIT 1: Я хочу знать, потому что я делаю анимацию и для одного кадра есть два слоя: изображение и над массивом.

movie.append([plt.imshow(merge_class(array1,array2), animated=True, interpolation='none', origin='lower')]) 

Объект в списке фильмов должен быть < class 'matplotlib.image.AxesImage' > и если я только вернуться plt.show() в моей функции он будет возвращать None.

EDIT 2: Я имитирую лесной пожар.

В массиве forest и forest_fire:

  • ни дерева = 0,0
  • негорючий дерево = 1,0
  • горения дерева = 2,0

set_on_fire функция возвращает новый лес , в котором дерево в координатах (i, j) горит.

Функция check_fire возвращает значение True, если может сжечь хотя бы одно дерево без обжига.

Функция spreading_fire возвращает новый лес, в котором горят деревья, которые могут гореть.

Вот часть кода:

# maido is the name of a mountain and a forest 

def img_maido(img_file,forest): 
    fig, axes = plt.subplots() 

    # 1) Opening the picture as an array 
    img_array = plt.imread(img_file) 
    img = np.copy(img_array[::-1,:,:]) # I flip it because it is upside down 

    # 2) Hiding all the 'no tree' values (0.0) 
    forest = np.ma.masked_where(forest == 0.0, forest) # The array is transparent at each one of the 'no tree' values position (0.0) 

    # 3) The 'non-burning tree' values (1.0) are green and the 'burning tree' values (2.0) are red 
    cmap = ListedColormap(['green','red'], 'indexed') 

    # 4) Displaying the array 'img' of the mountain and the array 'forest' of the forest above it 
    plt.imshow(forest,zorder=1, cmap=cmap, origin='lower') 
    plt.imshow(img,zorder=0, origin='lower') 

    return ? # Here is my issue 


def fire_animation(img_file,forest,i,j,wind): 
    fig, axes = plt.subplots() 
    movie = []  

    # 1) Initialization 
    forest_fire = set_on_fire(forest,i,j) # I put a 'burning tree' value (2.0) in the array 'forest' at the coordinates (i,j) 
    movie.append([plt.imshow(img_maido(img_file,forest_fire), animated=True, cmap=cmap, interpolation='none', origin='lower')]) 
    plt.draw() 

    # 2) Spread of fire 
    while check_fire(foret,wind): 
     forest_fire = spreading_fire(forest_fire,wind) 
     movie.append([plt.imshow(img_maido(img_file,forest_fire), animated=True, interpolation='none', origin='lower')]) 
     plt.draw() 

    # 3) Animation 
    ani = animation.ArtistAnimation(fig, movie, interval=100, blit=True, repeat_delay=100) 

    plt.draw() 
    plt.show() 
+0

Слияние двух 'AxesImage' невозможно. Однако это также не нужно. Если вы сообщите нам, почему вы хотите, и что вы ожидаете, что результат будет выглядеть, обязательно будет решение. – ImportanceOfBeingErnest

+0

Создание фильма не должно быть проблемой даже с большим количеством художников. Можете ли вы показать, как вы снимаете фильм ?. Лучше всего показать [MCVE], который работает для одного изображения, и не удается выполнить два изображения с комментариями в коде, где у вас проблемы. – ImportanceOfBeingErnest

+0

Я отредактировал вопрос. Надеюсь, мой английский достаточно хорош. –

ответ

0

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

В приведенном ниже примере мы создаем фигуру и оси и накладываем на них два массива. Каждое изображение сохраняется в переменной.

Затем мы создаем анимацию, которая повторно вызывает функцию burn. Внутри этой функции мы манипулируем одним из массивов и устанавливаем новые данные на одно из изображений, оставляя другое нетронутым. Измененное изображение является возвращаемым значением этой функции. Обратите внимание: , после возвращаемого значения. Эта запятая делает возвращаемое значение последовательностью, а это значит, что мы также можем изменить оба изображения и вернуть их, если хотим. Однако это не обязательно, поскольку фон в нашем случае не меняется.

import matplotlib.pyplot as plt 
import matplotlib.animation 
import numpy as np 

x = np.linspace(0,40) 
X,Y = np.meshgrid(x,x) 

static_array = (X/40.)**2+(Y/30.)**2 

dynamic_array = np.floor(np.random.random(X.shape)*1.1) 
masked_dynamic_array = np.ma.masked_where(dynamic_array <=0.7 , dynamic_array) 

fig, ax = plt.subplots() 

static_image = ax.imshow(static_array, cmap="terrain") 
dynamic_image = ax.imshow(dynamic_array, cmap="magma") 

def burn(i): 
    rand = (np.random.random(X.shape)-0.3) 
    new = dynamic_array + 0.1*rand 
    dynamic_array[:,:] = new/new.max() 
    masked_dynamic_array = np.ma.masked_where(dynamic_array <=0.7 , dynamic_array) 
    dynamic_image.set_data(masked_dynamic_array) 
    return dynamic_image, 

ani = matplotlib.animation.FuncAnimation(fig, burn, interval=100, blit=True) 

plt.show() 

enter image description here


Если число итераций неизвестно, вы можете сначала запустить симуляцию, хранить полученные массивы в списке. Как только это будет закончено, используйте длину этого списка как количество кадров для анимации.

import matplotlib.pyplot as plt 
import matplotlib.animation 
import numpy as np 

x = np.linspace(0,40) 
X,Y = np.meshgrid(x,x) 

static_array = (X/40.)**2+(Y/30.)**2 
dynamic_array = np.floor(np.random.random(X.shape)*1.1) 


fig, ax = plt.subplots(figsize=(4,4)) 


static_image = ax.imshow(static_array, cmap="terrain") 
dynamic_image = ax.imshow(dynamic_array, cmap="magma", vmin=0., vmax=4.) 

ims = [] 
while dynamic_array.mean() < 1.5: 
    rand = (np.random.random(X.shape)-0.4) 
    new = dynamic_array + 0.085*rand 
    new[new > 4] = 4. 
    dynamic_array[:,:] = new 
    masked_dynamic_array = np.ma.masked_where(dynamic_array <=0.7 , dynamic_array) 
    ims.append(masked_dynamic_array) 

def burn(i): 
    dynamic_image.set_data(ims[i]) 
    return dynamic_image, 

plt.tight_layout()  
ani = matplotlib.animation.FuncAnimation(fig, burn, frames=len(ims), interval=100, blit=True) 
ani.save(__file__+'.gif', writer='imagemagick', fps=10) 
plt.show() 
+0

Но если я хочу сохранить анимацию, будет ли фон еще отображаться в файле GIF или MP4? –

+0

Конечно, почему бы и нет? Просто используйте что-то вроде 'ani.save (__ file __ + '. Gif', writer = 'imagemagick', fps = 10)' Но не забудьте указать количество кадров в вызове FuncAnimation, например. 'кадров = 30'. В противном случае файл будет бесконечно большим. – ImportanceOfBeingErnest

+0

Хорошо, спасибо. Я попробую завтра, потому что мне нужно немного поспать (10:30 вечера здесь;)), и я покажу вам, что я получу. –

 Смежные вопросы

  • Нет связанных вопросов^_^