wxpythonとvtkでビデオプレーヤー作ってみる。その2。numpyアレイで用意した2Dテクスチャを四角ポリゴンに貼る。
目次
- その0。wxpythonのウィンドウ内部にvtkを表示するパネルを作ってみた
- その1。C++のJpeg表示サンプルをPythonに翻訳。
- その2。numpyアレイで用意した2Dテクスチャを四角ポリゴンに貼る。
- その3。vtkImageViewerでjpeg表示。
- その4。vtkImageViewerでnumpyアレイ表示。
- その5。完成。opencvとvtkImageViewerで読み込み・表示。
前置き
vtk使い始めなので、とりあえずなんか作ってみるという意味でビデオプレーヤーを作っていく企画の第二弾です。
numpyアレイをテクスチャーとして表示する
(追記。vtkImageCanvasSource2Dというクラスが用意されているので、この辺のサンプルを参考して、このクラスを使ってやったほうがいいかと思われます。更にvtkImageViewerというハイレベルな便利クラスも用意されているので、これでいけるならこれで、さらにカスタマイズが必要なときにvtkImageCanvasSource2Dを使うんだと思われます。vtkImageViewerの例を次にやる予定。)
あ゛ー、どっから手をつけていいかすらわからん。というわけでグーグル先生に”numpy texture vtk”とお伺いを立てる。
ふむふむ、一番上の検索結果になにやら参考になりそうな話題が。
まずは、8ビットの符号なし整数型でグレースケールの画像をテケトーに作って
h,w = 48,64 data_matrix = np.random.randint(0,255,(h,w)).astype(np.uint8)
これを
dataImporter = vtk.vtkImageImport() dataImporter.CopyImportVoidPointer(data_matrix, data_matrix.nbytes)
のようにvtkImageImportオブジェクトを使って変換する。vtkImageImportはnumpy対応らしいので、tostringとかしなくていいらしい。
あとはデータタイプを8ビットの符号なし整数型と指定する。
dataImporter.SetDataScalarTypeToUnsignedChar() dataImporter.SetNumberOfScalarComponents(1)
これをやらないとたぶん32ビットと解釈されるっぽく、ドットが連続じゃなくて3ピクセルくらいのギャップができてしまった。
その上でデータの範囲を指定
dataImporter.SetDataExtent(0, h-1, 0, w-1, 0, 0) dataImporter.SetWholeExtent(0, h-1, 0, w-1, 0, 0)
SetDataExtentの方はバッファーされる実際に表示される領域で、SetWholeExtentの方は全体のことらしい。
こうしてできたdataImporterオブジェクトをテクスチャーとして指定する。
texture = vtk.vtkTexture() texture.SetInputConnection( dataImporter.GetOutputPort() )
あとは前回のコードそのままで表示された。
ふーむ。なんとかなってきた。カメラがいつも引いたままなのでぴったりズームするようにしたい。
メーリングリストの方にSetParallelScaleを高さにすると書いてあるが、
renderer.GetActiveCamera().SetParallelScale(h)
と、やってみたが、なんか違う。。。
と思って調べてみたらvtkImageViewerという便利なクラスがあるらしいのを今更発見。多分これでいいじゃん。
一応今回のコードも全部載せておきます。vtkImageViewerつかった方がスマートでしょうけど、ローレベルにはどうやるかという意味でまったく無駄ではなかった・・・と思いたい。いやいやnumpyアレイの変換とかいづれ必要だし、いいのだ。
from __future__ import division
import numpy as np
import vtk
from vtk.wx.wxVTKRenderWindow import wxVTKRenderWindow
import wx
class Test(wx.Frame):
def __init__ (self, imgsize):
h,w = imgsize # data array dimension (h,w)
self.imgsize = imgsize
wx.Frame.__init__(self, None, title='TextureMapQuad')
canvas = wx.Panel(self, size=(w,h))
rwi = wxVTKRenderWindow(canvas, -1)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(canvas, 1, wx.EXPAND)
self.SetSizerAndFit(sizer)
rwi.Enable(True)
self.SetupRender()
rwi.GetRenderWindow().AddRenderer(self.ren)
self.Layout()
self.Show()
def SetupRender(self):
h,w = self.imgsize
points = vtk.vtkPoints()
points.InsertNextPoint(0.0,0.0,0.0)
points.InsertNextPoint(w/h,0.0,0.0)
points.InsertNextPoint(w/h,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( (w/h, 0.0, 0.0) )
textureCoordinates.InsertNextTuple( (w/h, 1.0, 0.0) )
textureCoordinates.InsertNextTuple( (0.0, 1.0, 0.0) )
quad.GetPointData().SetTCoords(textureCoordinates)
# set a numpy array up and import it to vtk
data_matrix = np.random.randint(0,255,(h,w)).astype(np.uint8)
dataImporter = vtk.vtkImageImport()
dataImporter.CopyImportVoidPointer(data_matrix, data_matrix.nbytes)
dataImporter.SetDataScalarTypeToUnsignedChar()
dataImporter.SetNumberOfScalarComponents(1)
dataImporter.SetDataExtent(0, h-1, 0, w-1, 0, 0)
dataImporter.SetWholeExtent(0, h-1, 0, w-1, 0, 0)
# set the imported array as texture
texture = vtk.vtkTexture()
texture.SetInputConnection( dataImporter.GetOutputPort() )
mapper = vtk.vtkPolyDataMapper()
mapper.SetInput(quad) # vtk 5.1.0
texturedQuad = vtk.vtkActor()
texturedQuad.SetMapper(mapper)
texturedQuad.SetTexture(texture)
renderer = vtk.vtkRenderer()
renderer.AddActor(texturedQuad)
renderer.SetBackground(1,1,1)
self.ren = renderer
if __name__ == '__main__':
app = wx.App(0)
size = 48*3, 64*3
frame = Test(size)
app.MainLoop()
« wxpythonとvtkでビデオプレーヤー作ってみる。その1。C++のJpeg表示サンプルをPythonに翻訳。 | トップページ | wxpythonとvtkでビデオプレーヤー作ってみる。その3。vtkImageViewerでjpeg表示。 »
「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でビデオプレーヤー作ってみる。その1。C++のJpeg表示サンプルをPythonに翻訳。 | トップページ | wxpythonとvtkでビデオプレーヤー作ってみる。その3。vtkImageViewerでjpeg表示。 »
コメント