wxpythonとvtkでビデオプレーヤー作ってみる。その1。C++のJpeg表示サンプルをPythonに翻訳。
目次
- その0。wxpythonのウィンドウ内部にvtkを表示するパネルを作ってみた
- その1。C++のJpeg表示サンプルをPythonに翻訳。
- その2。numpyアレイで用意した2Dテクスチャを四角ポリゴンに貼る。
- その3。vtkImageViewerでjpeg表示。
- その4。vtkImageViewerでnumpyアレイ表示。
- その5。完成。opencvとvtkImageViewerで読み込み・表示。
Visualization Toolkit (vtk)は研究開発用途で使われる、3Dなデータのビジュアリゼーションライブラリーです。C++ですがPython用のバインディングがあり、スクリプトでいろいろ試しながらデータの可視化ができます。内部的にはOpenGLなので描画も滑らかです。
ま、vtkをwxpythonで作ったGUIのなかに埋め込んでなんかする練習ということでビデオプレーヤーなら2Dだし、簡単だろうということでやってみます。
ビデオプレーヤーを作る他のオプション
Pythonでビデオプレーヤー作るだけならpygletで作ると何もしなくてもOpenGLでスムーズな描画が簡単にできておすすめですし、別にwxだけでも十分なものが作れます。ただし、pygletではAVbin経由でビデオを処理することになって、AVbinは最初から最後まで再生とかは大丈夫だけど、シークがかなり適当な位置に来るので任意のフレームに正確にジャンプするとかできません。なので、正確性が必要な場合、opencvがお勧めです。opencvのhighguiをつかえばOpenGLのウィンドウが簡単に持てますし、ビデオファイルの読み書きもPythonのライブラリーではOpenCVが一番だとおもいます。ffmpegのバイナリーとパイプでやり取りする方法もある。(ちなみにpygletはPython2.6まではバイナリーのインストーラーが使えますが、Python2.7だと怒られるのでソースからpython setup.py installする必要があります。)
画像ファイルを読んで、そのテクスチャーを四角いポリゴンに貼ってみる
前回書いたwxのウィンドウ内部にvtkを表示するパネルを作ってみたではとりあえずwxのパネルにvtkオブジェクトを表示してみたというとこまで行きました。ビデオプレーヤーが目標なので、今回は画像ファイルを読んで、そのテクスチャーを四角いポリゴンに貼ってみることにします。
VTKのウィキにあったTextureMapQuadというC++のサンプルコードをPythonに翻訳します。VTKはC++のコードサンプルが豊富にあるので、これができたらかなりでかい。
うへーC++怖い~とか恐れていたのだけど、翻訳は意外に簡単だった。例えば最初の
vtkSmartPointer<vtkJPEGReader> jPEGReader = vtkSmartPointer<vtkJPEGReader>::New();
は
jPEGReader = vtk.vtkJPEGReader()
のようにSmartPointerのところは無視して、<>で囲まれてるのはvtkのネームスペースの下にあるのでvtk.を挿入する。Newは省いて()だけでOK。
以後もクラス内のメソッドの呼び出しが->の代わりにドットにする程度で同様にやれば大丈夫。
サンプルコードではpointsとtextureCoordinatesの4つめの座標がなぜか(0.0, 2.0, 0.0)なんだけどちゃんと四角にしたいので(0.0, 1.0, 0.0)と変更した。アスペクト比無視で全部真四角になりますが。
import vtk
from vtk.wx.wxVTKRenderWindow import wxVTKRenderWindow
import wx
class Test(wx.Frame):
def __init__ (self, fp):
wx.Frame.__init__(self, None, title='TextureMapQuad')
self.fp = fp
canvas = wx.Panel(self, size=(640,480))
rwi = wxVTKRenderWindow(canvas, -1)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(rwi, 1, wx.EXPAND)
self.SetSizer(sizer)
self.Layout()
rwi.Enable(True)
self.SetupRender()
rwi.GetRenderWindow().AddRenderer(self.ren)
self.Show()
def SetupRender(self):
jpegreader = vtk.vtkJPEGReader()
jpegreader.SetFileName(self.fp)
points = vtk.vtkPoints()
points.InsertNextPoint(0.0,0.0,0.0);
points.InsertNextPoint(1.0,0.0,0.0);
points.InsertNextPoint(1.0,1.0,0.0);
points.InsertNextPoint(0.0,1.0,0.0);
polygon = vtk.vtkPolygon()
polygon.GetPointIds().SetNumberOfIds(4);
polygon.GetPointIds().SetId(0,0);
polygon.GetPointIds().SetId(1,1);
polygon.GetPointIds().SetId(2,2);
polygon.GetPointIds().SetId(3,3);
polygons = vtk.vtkCellArray()
polygons.InsertNextCell(polygon);
quad = vtk.vtkPolyData()
quad.SetPoints(points);
quad.SetPolys(polygons);
textureCoordinates = vtk.vtkFloatArray()
textureCoordinates.SetNumberOfComponents(3);
textureCoordinates.SetName("TextureCoordinates");
textureCoordinates.InsertNextTuple( (0.0, 0.0, 0.0) )
textureCoordinates.InsertNextTuple( (1.0, 0.0, 0.0) )
textureCoordinates.InsertNextTuple( (1.0, 1.0, 0.0) )
textureCoordinates.InsertNextTuple( (0.0, 1.0, 0.0) )
quad.GetPointData().SetTCoords(textureCoordinates);
texture = vtk.vtkTexture()
texture.SetInputConnection( jpegreader.GetOutputPort() );
mapper = vtk.vtkPolyDataMapper();
mapper.SetInput(quad); # vtk 5.10.1
texturedQuad = vtk.vtkActor()
texturedQuad.SetMapper(mapper);
texturedQuad.SetTexture(texture);
renderer = vtk.vtkRenderer()
renderer.AddActor(texturedQuad)
renderer.SetBackground(1,1,1);
renderer.ResetCamera();
self.ren = renderer
if __name__ == '__main__':
app = wx.App(0)
frame = Test( r"C:\path\to\your\image.jpg" )
app.MainLoop()
« wxpythonのウィンドウ内部にvtkを表示するパネルを作ってみた | トップページ | wxpythonとvtkでビデオプレーヤー作ってみる。その2。numpyアレイで用意した2Dテクスチャを四角ポリゴンに貼る。 »
「Python」カテゴリの記事
- Noteの記事をPythonでバックアップしといた。(2021.05.05)
- JupyterLabでも好きな外部エディターを使いたい!(2018.05.02)
- ローカルエリア内のJupyterLabサーバーにLAN経由で接続する。(2018.05.02)
- Juliaやってみよう。五日目。Pythonと速度比較。(2017.08.01)
- Juliaやってみよう。四日目。@timeでプロファイリング(2017.07.16)
« wxpythonのウィンドウ内部にvtkを表示するパネルを作ってみた | トップページ | wxpythonとvtkでビデオプレーヤー作ってみる。その2。numpyアレイで用意した2Dテクスチャを四角ポリゴンに貼る。 »
コメント