С учетом маскированного NumPy массива размерности (frames, points, 2)
, представляющего видео с frames
кадрами, где в каждом кадре отслеживаются points
(x, y)
точек.
Я хотел бы интерполировать это видео от frames
кадров до любого количества кадров, очень быстрое, надеюсь, со сплайном cubi c, но любая другая непрерывная интерполяция тоже будет работать нормально.
Наивное решение, которое я реализовал разбивает массив на 2 массива измерений (frames, points)
для массива X
и массива Y
. Затем я перемещаю массив в (points, frames)
. Для каждой строки (одной точки в течение определенного времени) я сопоставляю ее с индексом и значением, поэтому массив [5, 6, --, 7]
становится:
[{"x": 0, "y": 5}, {"x": 1, "y": 6}, {"x": 3, "y": 7}]
Я передаю это scipy.interp1d
и запустить мой новый массив, например, [0, 0.5, 1, 1.5, 2, 2.5, 3]
, и получить новый массив x, y
, который я затем преобразую обратно в NumPy.
. Этот процесс удаляет маски для прерывистых кадров (что нормально со мной).
Текущая производительность: небольшой массив формы (9 frames, 140 points, 2)
до (24 frames, 140 points, 2)
- Кубический c интерполяция 0,115 секунд
- Линейная интерполяция 0,112 секунд
Примечание!
Это замаскированный массив, например [5, 6, --, 7]
. поэтому важно включить маски в интерполяцию, чтобы не иметь нулевых значений (массив данных выглядит как [5, 6, 0, 7]
!
Вот пример игрушки с данными о желаемом и нежелательном поведении:
import numpy as np
import numpy.ma as ma
from scipy.interpolate import interp1d
points = np.array([1, 2, 3, 4, 0, 6])
mask = [0, 0, 0, 0, 1, 0]
points = ma.array(points, mask=mask)
print(points) # [1 2 3 4 -- 6]
lin = np.linspace(0, 1, 6)
# Undesired behavior
f = interp1d(lin, points, axis=0, kind='cubic')
print(f(lin)) # [1 2 3 4 -8.8817842e-16 6]
# Desired behavior
compressed_lin = [0, 0.2, 0.4, 0.6, 1]
compressed_points = np.array([1,2,3,4,6])
f = interp1d(compressed_lin, compressed_points, axis=0, kind='cubic')
print(f(lin)) # [1 2 3 4 5 6]