介紹如何使用 ITK 與 OpenVDB 將三維立體影像轉換為 VDB 格式。
ITK 與 OpenVDB
若要將一般的三維立體影像(volume image)轉換為 VDB 格式,可以使用 ITK 函式庫讀取各種三維立體影像,然後再使用 OpenVDB 函式庫轉為 VDB 的檔案格式,以下是基本的實作程式碼。
#include <itkImage.h> #include <itkImageFileReader.h> #include <itkImageRegionIteratorWithIndex.h> #include <openvdb/openvdb.h> #include <iostream> int main(int argc, char *argv[]) { // ----------------------- // // 以 ITK 讀取三維立體影像 // // ----------------------- // constexpr unsigned int Dimension = 3; using PixelType = unsigned char; using ImageType = itk::Image<PixelType, Dimension>; using ReaderType = itk::ImageFileReader<ImageType>; using IteratorType = itk::ImageRegionIteratorWithIndex<ImageType>; // 讀取影像 ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(argv[1]); reader->Update(); ImageType::Pointer image = reader->GetOutput(); // 查看影像大小 ImageType::RegionType region = image->GetLargestPossibleRegion(); ImageType::SizeType size = region.GetSize(); std::cout << size << std::endl; // -------------------------------------- // // 以 OpenVDB 將三維立體影像轉為 VDB 格式 // // -------------------------------------- // // 初始化 OpenVDB 函式庫(至少必須執行一次,執行多次無妨) openvdb::initialize(); // 建立一個 grid,預設值皆為背景值 0 openvdb::FloatGrid::Ptr grid = openvdb::FloatGrid::create(); // 設定 grid 名稱 grid->setName("density"); // 取得以座標為基礎的 Accessor openvdb::FloatGrid::Accessor accessor = grid->getAccessor(); // 以有號索引定義座標 openvdb::Coord xyz; // 以 iterator 讀取影像資料 IteratorType imageIter(image, image->GetRequestedRegion()); for (imageIter.GoToBegin(); !imageIter.IsAtEnd(); ++imageIter) { ImageType::IndexType index = imageIter.GetIndex(); // 取得 ITK 影像索引 PixelType value = imageIter.Get(); // 取得 ITK 影像值 xyz.reset(index[0], index[1], index[2]); // 設定 OpenVDB 影像座標 accessor.setValue(xyz, value); // 設定 OpenVDB 影像值 std::cout << "Grid" << xyz << " = " << accessor.getValue(xyz) << std::endl; } // 建立 grid 容器 openvdb::GridPtrVec grids; grids.push_back(grid); // 輸出 VDB 檔案 openvdb::io::File file(argv[2]); file.write(grids); file.close(); return EXIT_SUCCESS; }
將以上的 C++ 程式碼儲存為 vdb_conv.cpp
之後,還要配合以下的 CMakeLists.txt
設定檔才能編譯。
CMakeLists.txt
設定檔
由於這個程式需要同時使用到 ITK 與 OpenVDB,因此在 CMakeLists.txt
設定檔中就要引入這兩套函式庫,基本的設定內容如下:
cmake_minimum_required(VERSION 3.10.2) set(CMAKE_VERBOSE_MAKEFILE ON) # 設定專案名稱 project(VDBConv) # 尋找並引入 ITK 函式庫 find_package(ITK REQUIRED) include(${ITK_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 ${ITK_LIBRARIES} OpenVDB::openvdb)
編譯與執行
準備好 vdb_conv.cpp
這個 C++ 原始碼與 CMakeLists.txt
設定檔之後,按照一般 CMake 專案的方式編譯:
# 建立編譯目錄 mkdir build # 編譯專案 cd build cmake .. make
編譯完成之後,即可使用此程式將一般的三維立體影像轉為 VDB 檔案了:
# 執行程式
./VDBConv image.tiff output.vdb