РЕДАКТИРОВАННАЯ ВЕРСИЯ НА ДНЕ
У меня есть отснятый материал с камеры 360, который я хотел бы нанести на сферу.Сцена сохраняется в виде прямоугольной проекции в файле MP4.
Я нашел этот пример , объясняющий, как отобразить изображение на сферу, и смог обернуть код из примера с помощью декоратора mayavi.animate, считывать последовательные кадры из файла MP4и отобразить текстуры на сферу, как и предполагалось (используя код, отрыванный из примера раздела mayavi, который преобразует массивы numpy в объекты tvtk.ImageData).
Однако я столкнулся с одной проблемой, которая заставляет меня подозревать, что я могу использовать это совершенно неправильно ... Странные круговые артефакты: Кадр фильма на сфере
Когда я использую связанный пример со снимком JPG из фильма, проекция выглядит так, как должна быть (верхняя часть выглядит неправильно, но это часть видеозаписи): Изображение на сфере
Вот код:
'''
Altered version of Andras Deak's
on https://stackoverflow.com/questions/53074908/map-an-image-onto-a-sphere-and-plot-3d-trajectories
'''
import imageio
from mayavi import mlab
from tvtk.api import tvtk # python wrappers for the C++ vtk ecosystem
from tvtk.tools import visual
from tvtk.common import configure_input_data, is_old_pipeline
def image_from_array(ary):
""" Create a VTK image object that references the data in ary.
The array is either 2D or 3D with. The last dimension
is always the number of channels. It is only tested
with 3 (RGB) or 4 (RGBA) channel images.
Note: This works no matter what the ary type is (accept
probably complex...). uint8 gives results that make since
to me. Int32 and Float types give colors that I am not
so sure about. Need to look into this...
"""
sz = ary.shape
dims = len(sz)
# create the vtk image data
img = tvtk.ImageData()
if dims == 2:
# 1D array of pixels.
img.whole_extent = (0, sz[0]-1, 0, 0, 0, 0)
img.dimensions = sz[0], 1, 1
img.point_data.scalars = ary
elif dims == 3:
# 2D array of pixels.
if is_old_pipeline():
img.whole_extent = (0, sz[0]-1, 0, sz[1]-1, 0, 0)
else:
img.extent = (0, sz[0]-1, 0, sz[1]-1, 0, 0)
img.dimensions = sz[0], sz[1], 1
# create a 2d view of the array
ary_2d = ary[:]
ary_2d.shape = sz[0]*sz[1],sz[2]
img.point_data.scalars = ary_2d
else:
raise ValueError("ary must be 3 dimensional.")
return img
# create a figure window (and scene)
fig = mlab.figure(size=(600, 600))
visual.set_viewer(fig)
# load video
vid = imageio.get_reader('movie.mp4', 'ffmpeg')
# use a TexturedSphereSource, a.k.a. getting our hands dirty
R = 1
Nrad = 180
# create the sphere source with a given radius and angular resolution
sphere = tvtk.TexturedSphereSource(radius=R, theta_resolution=Nrad, phi_resolution=Nrad)
# assemble rest of the pipeline, assign texture
sphere_mapper = tvtk.PolyDataMapper(input_connection=sphere.output_port)
sphere_actor = tvtk.Actor(mapper=sphere_mapper)
@mlab.show
@mlab.animate(delay=50)
def auto_sphere():
for i in range(1,600):
image = vid.get_data(i)
img = image_from_array(image)
texture = tvtk.Texture(interpolate=1)
configure_input_data(texture, img)
sphere_actor.texture = texture
fig.scene.add_actor(sphere_actor)
yield
auto_sphere()
Я совершенно новичок в этой теме.Как это можно сделать правильно?
РЕДАКТИРОВАТЬ:
Так что я думаю, что мне удалось определить реальную проблему.Но я пока не знаю, как это решить. Проблема, похоже, заключается в том, как читается файл MP4. В этой модифицированной версии - которая использует файлы JPEG отдельных кадров из mp4 - конвейер vtk и получающийся в результате отрендеренный фильм выглядит правильно:
from mayavi import mlab
from tvtk.api import tvtk # python wrappers for the C++ vtk ecosystem
# create a figure
fig = mlab.figure(size=(600, 600))
# sphere source
R = 1
Nrad = 180
sphere = tvtk.TexturedSphereSource(radius=R, theta_resolution=Nrad, phi_resolution=Nrad)
# sphere mapper
sphere_mapper = tvtk.PolyDataMapper(input_connection=sphere.output_port)
# actor
sphere_actor = tvtk.Actor(mapper=sphere_mapper)
# image reader
image = tvtk.JPEGReader()
image.file_name = 'testdata/frame001.jpg'
# texture
texture = tvtk.Texture(input_connection=image.output_port, interpolate=1)
sphere_actor.texture = texture
# add actor to scene
fig.scene.add_actor(sphere_actor)
@mlab.show
@mlab.animate(delay=50)
def auto_sphere():
for i in range(2,101):
num = str(i)
filepath = 'testdata/frame%s.jpg' % num.zfill(3)
image.file_name = filepath
# render current texture
fig.scene.render()
yield
auto_sphere()
Наверное, теперь мой новый вопрос: Могу ли я реализовать собственный класс vtkImageReader2 или что-то подобное в python, которое позволяет мне читать в последовательных кадрах mp4?И если так, то как это можно сделать правильно?К сожалению, мне не удалось найти какой-либо учебник о том, как это сделать.