Open3DでMesh Deformationを行ってみる

以下の動画のように、3次元メッシュモデルの一部をつまんで変形をさせる場合の代表的な手法としてAs-Rigid-As-Possible(ARAP)という制約を用いた方法がある。
As-Rigid-As-Possible Surface Modeling, EUROGRAPHICS/ACM SIGGRAPH Symposium on Geometry Processing 2007
この方法では、変形の前後で局所的な構造(各頂点の相対的な位置関係)を保つような制約を用いた最適化によって変形後の各頂点位置の算出を行っている。ARAPを用いた変形に関しては、CGALlibiglにも実装がされているが、Open3Dにも0.9.0から実装がされているのでこちらを試してみた。
#include <iostream>
#include <string>

#include <open3d/Open3D.h>

int main(int argc, char** argv) {
  // モデルの読み込み
  open3d::geometry::TriangleMesh input_mesh;
  open3d::io::ReadTriangleMeshFromOBJ("../model/elefante.obj", input_mesh,
                                      true);
  // 変形後のモデル
  std::shared_ptr<open3d::geometry::TriangleMesh> output_mesh;

  // 制約を付加する点のIDと頂点位置
  std::vector<int> constraint_idx;
  std::vector<Eigen::Vector3d> constraint_pos;

  int count = 0;
  for (size_t i = 0; i < input_mesh.vertices_.size(); ++i) {
    Eigen::Vector3d vtx = input_mesh.vertices_[i];
    if (vtx.z() < 2.0) {
      // 固定する頂点を追加(移動させないので元の座標値を格納)
      constraint_idx.push_back(i);
      constraint_pos.push_back(vtx);
    } else if (vtx.y() < -1.23 && vtx.z() > 3.8) {
      // 移動させる点を追加(元の座標値にオフセット(0, 0.3, 0.3)を付加)
      constraint_idx.push_back(i);
      Eigen::Vector3d target_pos;
      target_pos = vtx + Eigen::Vector3d(0.0, 0.3, 0.3);
      constraint_pos.push_back(target_pos);
    }
  }
  output_mesh = input_mesh.DeformAsRigidAsPossible(
      constraint_idx, constraint_pos, 200,
      open3d::geometry::TriangleMesh::DeformAsRigidAsPossibleEnergy::Spokes);

  open3d::io::WriteTriangleMeshToPLY("../output/elephant.ply", *output_mesh,
                                     true, false, true, false, false, true);

  return 0;
}
メッシュを変形させるにはDeformAsRigidAsPossibleを用いる。入力は制約に用いる点のIDとその座標値、最適化の繰り返し回数、変形手法、となっている。変形手法にはSpokesとSmoothedがあり、後者は近傍点との相対関係のみでなく変形に用いる回転行列の類似性も制約として用いるようになっている。

実行結果は以下の通り。この例では鼻の先端付近にオフセットをのせ、胴体の後ろ半分を固定するようにしている。青色がオリジナルのメッシュモデル、赤色が変形後のメッシュもでるとなっている。

このように鼻の先端部分にのみオフセットをのせているが、これに応じて頭部もわずかに持ち上がっているのが分かる。また、固定した胴体部分に関しては変形の前後で(ほぼ)変化していないことが分かる。
変形には、数秒の処理時間がかかるので、リアルタイムアニメーションでOpen3DのARAP Deformationを利用することは難しいが、オフラインのコンピュータビジョンタスクには利用できるかもしれない。
ちなみに、Pythonを用いた実装例に関しては、Open3Dの公式ページに載っている。


コメント

このブログの人気の投稿

COLMAPでキャリブレーション済みのデータを使う

5点アルゴリズムによるカメラ位置・姿勢の推定

2D-3D対応からのカメラ位置・姿勢の推定