Сопоставьте фильм 360 на сфере / реализуйте класс vtkMPEGReader - PullRequest
1 голос
/ 17 мая 2019

РЕДАКТИРОВАННАЯ ВЕРСИЯ НА ДНЕ

У меня есть отснятый материал с камеры 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?И если так, то как это можно сделать правильно?К сожалению, мне не удалось найти какой-либо учебник о том, как это сделать.

...