介紹如何在 Python 中使用 PyVista 高階 VTK 繪圖工具繪製各種 3D 資料圖形,適合用於簡報與論文。
VTK 是一套功能強大的繪圖工具,而在 Python 中亦可直接使用 VTK 進行各種圖形的繪製,但是 Python 的 VTK 使用方式幾乎跟 C++ 版本相同,在開發上需要撰寫大量的程式碼,而 PyVista 則是以 VTK 為基礎所開發的 API,讓使用者可以更方便使用 VTK 進行繪圖。
安裝 PyVista
PyVista 可以使用 pip 安裝:
# 安裝 PyVista 模組
sudo pip3 install pyvista
其他有一些選擇性的套件,安裝之後可以提供一些額外的功能:
matplotlib
:使用顏色對應表(colormaps)。itkwidgets
:互動式 3D 繪圖顯示。ipyvtk_simple
:互動式 3D 繪圖顯示。sphinx_gallery
:將 PyVista 輸出轉為文件。colorcet
:使用顏色對應表(colormaps)。cmocean
:使用顏色對應表(colormaps)。imageio-ffmpeg
:儲存影片檔。tqdm
:顯示進度。trimesh
、rtree
、pyembree
:像量化光線追蹤。
無顯示伺服器環境
正常模式的 PyVista 會需要 XWindow 的環境來進行繪圖,但如果是在無顯示(headless)的伺服器環境,就要改用 mesa 配合 xvfb 的方式以 CPU 來繪圖。
首先安裝 mesa 與 xvfb 套件:
# 安裝 mesa 與 xvfb 套件
sudo apt-get install libgl1-mesa-dev xvfb
接著建立一個 start.sh
指令稿,內容如下:
#!/bin/bash set -x export DISPLAY=:99.0 export PYVISTA_OFF_SCREEN=true export PYVISTA_USE_IPYVTK=true which Xvfb Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & sleep 3 set +x exec "$@"
以此指令稿執行含有 PyVista 繪圖的程式時,就會以 CPU 的方式進行繪圖,例如啟動 JupyterLab 環境:
# 安裝 mesa 與 xvfb 套件
./start.sh jupyter-lab
無顯示 GPU 伺服器環境
若在配備有 GPU 設備的伺服器環境,PyVista 可以透過 VTK 以 EGL 的方式用 GPU 進行 off-screen 繪圖,不過預先編譯好的 VTK 並沒有納入 EGL,需要自行編譯,以下是編譯的方式:
# 下載 VTK 原始碼 git clone https://github.com/Kitware/VTK # 編譯 VTK cd VTK mkdir build cd build PYBIN=/usr/bin/python3.9 cmake -GNinja \ -DVTK_BUILD_TESTING=OFF \ -DVTK_WHEEL_BUILD=ON \ -DVTK_PYTHON_VERSION=3 \ -DVTK_WRAP_PYTHON=ON \ -DVTK_OPENGL_HAS_EGL=True \ -DVTK_USE_X=False \ -DPython3_EXECUTABLE=$PYBIN \ ../ ninja $PYBIN setup.py bdist_wheel # 安裝 VTK $PYBIN -m pip install dist/vtk-*.whl
這裡在編譯時選擇搭配 Python 3.9 版,亦可更換為其他版本。
這樣編譯出來的 VTK 只能用於無顯示的 GPU 伺服器,繪圖結果只能儲存於檔案或是透過串流傳送至 client 端顯示(使用 use_ipyvtk=True
與 JupyterLab)。
官方範例
安裝好 PyVista 之後,可以先用官方提供的範例進行測試,這是顯示網格的範例。
from pyvista import examples # 載入網格範例資料 mesh = examples.download_bunny_coarse() # 顯示網格資料 mesh.plot()
這是顯示法向量的範例。
from pyvista import examples import pyvista as pv # 含有法向量的資料 mesh = examples.load_random_hills() # 使用 Glyph 產生法向量箭頭 arrows = mesh.glyph(scale="Normals", orient="Normals", tolerance=0.05) # 繪製圖形 p = pv.Plotter() p.add_mesh(arrows, color="black") p.add_mesh(mesh, scalars="Elevation", cmap="terrain") p.show()
這是顯示 volume 影像的範例。
from pyvista import examples # 下載 Volume 影像 vol = examples.download_knee_full() # 繪製 Volume 影像 vol.plot(volume=True, cmap="bone")
更多的範例可以從 PyVista 官方網站以及其他專案網站查看。