Пигментная и Numpy анимация - PullRequest
0 голосов
/ 29 января 2019

Предположим, у меня есть массив Numpy myAnimation с типом данных np.uint8, представляющий анимацию (несколько кадров неподвижных 8-битных изображений RGBA) формы (y,x,4,k), где y - высота, x - ширина, 4 - количество каналов (красный, зеленый, синий, альфа), а k - количество кадров в анимации.

Предположим, я хотел бы воспроизвести кадры этого массива NumPy.в PyGame с указанной частотой кадров (скажем, 15 кадров в секунду) и имеют цикл анимации.

Возможно ли это сделать с Pygame?

Если так, как бы вы достигли этого?Можете ли вы привести пример?

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

1 Ответ

0 голосов
/ 01 марта 2019

[...] shape (y,x,4,k), где y - высота, x - ширина, 4 - количество каналов (красный, зеленый, синий, альфа) и * 1005.* - это количество кадров [...]

К сожалению, это невозможно напрямую.

По pygame.surfarray.make_surface массиву (numpy) данныхможет быть преобразовано в pygame.Surface.
Но массив должен быть трехмерным массивом с формами (x, y, 3).

Это означает, что массив должен быть преобразован в формуформа от (y, x, 4, k) до (k, x, y, 4) в первую очередь.Это может быть достигнуто с помощью numpy.moveaxis:

myAnimation = np.moveaxis(myAnimation, 1, 0)
myAnimation = np.moveaxis(myAnimation, 3, 0)

Наконец, альфа-канал каждого кадра должен быть удален с помощью numpy.delete:

*Массив 1033 *

A np.uint8 с формами th (y, x, 4, k) можно преобразовать в список k pygame.Surface es с помощью:

myAnimation = np.moveaxis(myAnimation, 1, 0)
myAnimation = np.moveaxis(myAnimation, 3, 0)
surfL = [pygame.surfarray.make_surface( np.delete(myAnimation[i], 3, 2) ).convert_alpha() \
    for i in range(myAnimation.shape[0])]

Частоту кадров можно установить с помощью pygame.time.Clock.tick().См. Пример:

import pygame
import pygame.font
import numpy as np

size = (400,400)
pygame.init()
screen = pygame.display.set_mode(size)

myAnimation = np.zeros(shape = (80, 80, 4, 20), dtype = "uint8")

imageCpt = pygame.Vector2(myAnimation.shape[0]/2, myAnimation.shape[1]/2)
radius = myAnimation.shape[0]/2
maxI = 20
for x in range(myAnimation.shape[0]): 
    for y in range(myAnimation.shape[1]):
        pos = pygame.math.Vector2(x, y) - imageCpt
        for i in range(myAnimation.shape[3]):
            pos2 = pygame.math.Vector2(pos)
            pos2.x = pos2.x * maxI / max(1,abs(i-maxI/2))
            if pos.length() < radius:
                    myAnimation[x][y][3][i] = 255
                    if pos2.length() < radius:
                        myAnimation[x][y][0][i] = 255
                        if pos.length()*2 > radius:
                            myAnimation[x][y][1][i] = 255
                            myAnimation[x][y][2][i] = 255
                    else:
                        myAnimation[x][y][2][i] = 255 

myAnimation = np.moveaxis(myAnimation, 1, 0)
myAnimation = np.moveaxis(myAnimation, 3, 0)
surfL = [pygame.surfarray.make_surface( np.delete(myAnimation[i], 3, 2) ).convert_alpha() for i in range(myAnimation.shape[0])]

pos = [160, 160]
clock = pygame.time.Clock()
count = 0
done = False
while not done:
    clock.tick(20)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    screen.fill(0)
    screen.blit(surfL[count % len(surfL)], pos)
    pygame.display.flip()
    count += 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...