介紹如何使用 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
