C/C++

使用 VTK 與 OpenVDB 將影像轉為 VDB 格式教學與範例

介紹如何使用 VTK 與 OpenVDB 將 VTK ImageData 格式的三維立體影像轉換為 VDB 格式。

VTK 與 OpenVDB

若要將 VTK ImageData 格式(*.vti 檔案)的三維立體影像(volume image)轉換為 VDB 格式,使用 VTK 函式庫讀取影像之後,然後再使用 OpenVDB 函式庫轉為 VDB 的檔案格式,以下是基本的實作程式碼。

#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkPointData.h>
#include <vtkXMLImageDataReader.h>
#include <vtkFloatArray.h>
#include <openvdb/openvdb.h>
#include <string>
#include <iostream>
int main(int argc, char* argv[]) {

  std::string input = argv[1];
  std::string output = argv[2];

  // ----------------------- //
  // 以 VTK 讀取三維立體影像 //
  // ----------------------- //

  // 讀取影像
  auto reader = vtkSmartPointer<vtkXMLImageDataReader>::New();
  reader->SetFileName(input.data());
  reader->Update();
  vtkSmartPointer<vtkImageData> vtkImage = reader->GetOutput();

  // 基本影像資訊
  auto dims = vtkImage->GetDimensions();
  std::cout << "Dimensions = " << dims[0] << " " << dims[1] << " " << dims[2] << std::endl;
  std::cout << "Scalar Type = " << vtkImage->GetScalarTypeAsString() << std::endl;
  std::cout << "Number Of Scalar Components = " << vtkImage->GetNumberOfScalarComponents() << std::endl;
  
  // -------------------------------------- //
  // 以 OpenVDB 將三維立體影像轉為 VDB 格式 //
  // -------------------------------------- //
  
  // 初始化 OpenVDB 函式庫(至少必須執行一次,執行多次無妨)
  openvdb::initialize();
  
  // 建立一個 grid,預設值皆為背景值 0
  openvdb::FloatGrid::Ptr grid = openvdb::FloatGrid::create();
  
  // 設定 grid 的 class 為水平集
  grid->setGridClass(openvdb::GRID_LEVEL_SET);

  // 設定 grid 名稱
  grid->setName("density");

  // 取得以座標為基礎的 Accessor
  openvdb::FloatGrid::Accessor accessor = grid->getAccessor();

  // 以有號索引定義座標
  openvdb::Coord xyz;

  // 從 VTK 影像轉換至 VDB grid
  int &x = xyz[0], &y = xyz[1], &z = xyz[2];
  for (z = 0; z < dims[2]; ++z) {
    for (y = 0; y < dims[1]; ++y) {
      for (x = 0; x < dims[0]; ++x) {
        float value = vtkImage->GetScalarComponentAsFloat(x, y, z, 0);
        accessor.setValue(xyz, value);
      }
    }
  }

  // 輸出 VDB 檔案
  openvdb::io::File(output.data()).write({grid});

  return EXIT_SUCCESS;
}

將以上的 C++ 程式碼儲存為 vdb_conv.cpp 之後,還要配合以下的 CMakeLists.txt 設定檔才能編譯。

CMakeLists.txt 設定檔

由於這個程式需要同時使用到 VTK 與 OpenVDB,因此在 CMakeLists.txt 設定檔中就要引入這兩套函式庫,基本的設定內容如下:

cmake_minimum_required(VERSION 3.10.2)

# 設定專案名稱
project (VDBConv)

# 尋找並引入 VTK 函式庫
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})

# 尋找並引入 OpenVDB 函式庫
list(APPEND CMAKE_MODULE_PATH "/usr/local/lib/cmake/OpenVDB")
find_package(OpenVDB REQUIRED)

# 增加一個執行檔
add_executable(VDBConv vdb_conv.cpp)

# 定義執行檔連結方式
target_link_libraries(VDBConv ${VTK_LIBRARIES} OpenVDB::openvdb)

編譯與執行

準備好 vdb_conv.cpp 這個 C++ 原始碼與 CMakeLists.txt 設定檔之後,按照一般 CMake 專案的方式編譯:

# 建立編譯目錄
mkdir build

# 編譯專案
cd build
cmake ..
make

編譯完成之後,即可使用此程式將 VTK 格式的三維立體影像轉為 VDB 檔案了:

# 執行程式
./VDBConv input.vti output.vdb

參考資料:Blender Artists

Share
Published by
Office Guide

Recent Posts

Python 使用 PyAutoGUI 自動操作滑鼠與鍵盤

本篇介紹如何在 Python ...

1 年 ago

Ubuntu Linux 以 WireGuard 架設 VPN 伺服器教學與範例

本篇介紹如何在 Ubuntu ...

1 年 ago

Linux 網路設定 ip 指令用法教學與範例

本篇介紹如何在 Linux 系...

1 年 ago

Linux 以 Cryptsetup、LUKS 加密 USB 隨身碟教學與範例

介紹如何在 Linux 系統中...

1 年 ago