🎥

Realsenseで取得したデータをOpen3Dで3次元再構成する方法

2022/07/24に公開
2

3Dスキャン

3Dデータを作る3Dスキャンの方法として、Realsenseを使った方法とPhotogrammetry(フォトグラメトリ)を使った方法を以下の記事で紹介しました。

https://zenn.dev/karaage0703/articles/9bd4ad8604317d

この記事ではRealsenseで取得した複数の画像データとDepthMapから、Open3Dというソフトを使って3次元再構成する方法を紹介します。原理的には最新のiPhoneのLiDARを使った3DスキャンとかSLAMの一歩手前という感じでしょうか(詳細原理までは解説しませんし、私も理解できていません)。

この記事では、とりあえずやってみましたという内容です。この記事で扱うOpen3Dというソフトに関しては、以下のブログ記事参照ください。

https://karaage.hatenadiary.jp/entry/2018/03/12/073000

3Dスキャンの手順

やっていることは、Open3Dの以下のチュートリアルの手順を簡略化・日本語化して紹介しているだけです。より詳しく知りたい人は、以下のチュートリアルを参照してください。
http://www.open3d.org/docs/release/tutorial/reconstruction_system/capture_your_own_dataset.html

環境としてはLinux PCが前提です。Mac(Apple Silicon)では、Realsenseでのデータの取得はできましたが、3次元再構成でlibc++abi: terminating with uncaught exception of type pybind11::stop_iteration:というエラーでこけました。がんばれば直せる気がしますが、やっていません。WindowsではRealsenseでのデータ取得は実施できていませんが、WSL2で3次元再構成はできました。。

以下の手順が必要です。1,2は1回やればOKです。

  1. Realsenseのセットアップ
  2. Open3Dでの3次元構成環境セットアップ
  3. Realsenseでデータ取得
  4. Open3Dで3次元構成
  5. 3Dデータ確認

順に説明していきます。

Realsenseのセットアップ

以下記事を参考にセットアップしてください。

https://zenn.dev/karaage0703/articles/a267aa24a80c44

realsense-viewerで動作確認できる状態になっていればOKです。

Open3Dでの3次元構成環境セットアップ

Python環境は、今回仮想環境としてpyenv/pyenv-virtualenvを使った手順を説明します。他に好きな環境がある場合は、各自読み替えてください。

pyenv/pyenv-virtualenvのインストールは以下参照ください。

https://zenn.dev/karaage0703/articles/5af7ce4b8b1a8a

以下で仮想環境を作って入ります。

$ pyenv global 3.8.12
$ pyenv virtualenv 3.8.12 open3d
$ pyenv global 3.8.12/envs/open3d 

必要なライブラリをインストールします。

$ python -m pip install open3d==0.15.2
$ python -m pip install pyrealsense2
$ python -m pip install opencv-python

Open3Dのコードをダウンロードします。スクリプトをいくつか自分の使いやすいようにカスタムしたものを使用するため、オリジナルのリポジトリでなく、自分がforkしたリポジトリを使用します。

$ cd && git clone --depth 1 -b custom https://github.com/karaage0703/Open3D

ここで--depth 1 -b customのオプションつけているのは、Open3Dのリポジトリのサイズが大きいので、必要な特定のブランチを指定して最新版だけをもってくるようにしています。--depth 1はネットワークや時間に余裕があれば、つけなくてもOKです。

オリジナルのリポジトリを使いたい場合は以下コマンドを実行してください。

$ cd && git clone --depth 1 -b v0.15.1 https://github.com/isl-org/Open3D

これ以降は、ホームディレクトリ直下の~/Open3Dにディレクトリがある想定で説明していきます。

オリジナルのリポジトリを使用する場合は、以下の設定ファイルを作成します(カスタムしたリポジトリを使用する場合は、以下ファイルはすでに用意されているので作成の作業は不要です)。

~/Open3D/examples/python/reconstruction_system/config/realsense_img.json

記載する内容は以下です。

{
    "name": "Realsense image file",
    "path_dataset": "dataset/realsense",
    "path_intrinsic": "dataset/realsense/camera_intrinsic.json",
    "depth_max": 3.0,
    "voxel_size": 0.05,
    "depth_diff_max": 0.07,
    "preference_loop_closure_odometry": 0.1,
    "preference_loop_closure_registration": 5.0,
    "tsdf_cubic_size": 3.0,
    "icp_method": "color",
    "global_registration": "ransac",
    "python_multi_threading": true
}

Realsenseでデータ取得

Realsenseでデータを取得します。以下コマンドを実行すると、ウィンドウが開きRealsenseのプレビュー画面が表示されます。データは起動直後から自動的に取得されます。

$ cd ~/Open3D/examples/python/reconstruction_system/sensors/
$ python realsense_recorder.py --record_imgs

色々な方向にカメラを向けて、データをとりましょう。ウィンドウの上でESCボタンを押すと終了できます。~/Open3D/examples/python/reconstruction_system/dataset/というディレクトリにデータが格納されていればOKです。

オリジナルのスクリプトは、色がRGBでなくBGRだったり、色々使い勝手悪かったりしたので、カスタムしたリポジトリでは、このスクリプトを好みで修正しています。

Open3Dで3次元構成

以下コマンドを実行すると、3次元再構成が開始します。

$ cd ~/Open3D/examples/python/reconstruction_system
$ python run_system.py config/realsense_img.json --make --register --refine --integrate

データ量にもよりますが、数分かかります。

3Dデータ確認

MeshLabというソフトで確認します。入ってなければ、以下コマンドでインストールしてください。

$ sudo apt -y install meshlab

File -> Import Meshで以下にあるファイルを開きます。

dataset/realsense/scene/integrated.ply

以下のように3次元データが表示されたらOKです。

ミクさんでテスト

https://twitter.com/karaage0703/status/1551206359495876608

参考リンク

http://www.open3d.org/docs/release/tutorial/reconstruction_system/capture_your_own_dataset.html

https://github.com/isl-org/Open3D/pull/5219

http://whitewell.sakura.ne.jp/Open3D/

http://whitewell.sakura.ne.jp/Open3D_2018/

http://isl.sist.chukyo-u.ac.jp/wp-content/uploads/2019/05/RSJ-119thSeminar-slides.pdf

https://www.slideshare.net/ttamaki/3open3d3

https://qiita.com/tyori03/items/ce4cb85be7e24ab1f99b

https://github.com/isl-org/Open3D/issues/4809

https://zenn.dev/tasada038/articles/270e074e48d46e

関連記事

https://zenn.dev/karaage0703/articles/8e3e84c0fe45ba

Discussion

makotomakoto

はじめまして。いつも拝見しております。
記事の通りに実行しましたが、デプスカメラからのデータ取り込みは終わり、run_system.pyの実行時に以下のようなエラーになります。
何かヒントをいただけないでしょうか。データを取り直しても同じエラーが出ます。
OSはUbuntu 22.04.4 LTS、Pythonは記事の通り、pyenvで3.8.12を指定しています。

(3.8.12/envs/open3d) xxxxxx@b:~/Open3D/examples/python/reconstruction_system$ python run_system.py config/realsense_img.json --make --register --refine --integrate
====================================
Configuration
====================================
                                    name : Realsense image file
                            path_dataset : dataset/realsense
                          path_intrinsic : dataset/realsense/camera_intrinsic.json
                               depth_max : 0.6
                              voxel_size : 0.05
                          depth_diff_max : 0.07
        preference_loop_closure_odometry : 0.1
    preference_loop_closure_registration : 5.0
                         tsdf_cubic_size : 3.0
                              icp_method : color
                     global_registration : ransac
                  python_multi_threading : True
                          depth_map_type : redwood
                   n_frames_per_fragment : 100
                 n_keyframes_per_n_frame : 5
                               min_depth : 0.3
                               max_depth : 3.0
                          max_depth_diff : 0.07
                             depth_scale : 1000
                          max_iterations : 5
                               sdf_trunc : 0.04
                             block_count : 40000
                      distance_threshold : 0.07
                       fitness_threshold : 0.3
                      regularizer_weight : 1
                                  method : slac
                                  device : cpu:0
                          save_output_as : pointcloud
                             folder_slac : slac/
       template_optimized_posegraph_slac : optimized_posegraph_slac.json
                         folder_fragment : fragments/
                          subfolder_slac : slac/0.050/
             template_fragment_posegraph : fragments/fragment_%03d.json
   template_fragment_posegraph_optimized : fragments/fragment_optimized_%03d.json
            template_fragment_pointcloud : fragments/fragment_%03d.ply
                            folder_scene : scene/
               template_global_posegraph : scene/global_registration.json
     template_global_posegraph_optimized : scene/global_registration_optimized.json
              template_refined_posegraph : scene/refined_registration.json
    template_refined_posegraph_optimized : scene/refined_registration_optimized.json
                    template_global_mesh : scene/integrated.ply
                    template_global_traj : scene/trajectory.log
                              debug_mode : False
OpenCV is detected. Using ORB + 5pt algorithm
making fragments from RGBD sequence.
OpenCV is detected. Using ORB + 5pt algorithm
OpenCV is detected. Using ORB + 5pt algorithm
OpenCV is detected. Using ORB + 5pt algorithm
Fragment 000 / 002 :: RGBD matching between frame : 0 and 1
Fragment 002 / 002 :: RGBD matching between frame : 200 and 201
Fragment 001 / 002 :: RGBD matching between frame : 100 and 101
Fragment 001 / 002 :: RGBD matching between frame : 100 and 105
Fragment 001 / 002 :: RGBD matching between frame : 100 and 110
Fragment 000 / 002 :: RGBD matching between frame : 0 and 5
Fragment 001 / 002 :: RGBD matching between frame : 100 and 115
joblib.externals.loky.process_executor._RemoteTraceback:
"""
Traceback (most recent call last):
  File "/home/xxxxxx/.pyenv/versions/3.8.12/envs/open3d/lib/python3.8/site-packages/joblib/externals/loky/process_executor.py", line 463, in _process_worker
    r = call_item()
  File "/home/xxxxxx/.pyenv/versions/3.8.12/envs/open3d/lib/python3.8/site-packages/joblib/externals/loky/process_executor.py", line 291, in __call__
    return self.fn(*self.args, **self.kwargs)
  File "/home/xxxxxx/.pyenv/versions/3.8.12/envs/open3d/lib/python3.8/site-packages/joblib/parallel.py", line 598, in __call__
    return [func(*args, **kwargs)
  File "/home/xxxxxx/.pyenv/versions/3.8.12/envs/open3d/lib/python3.8/site-packages/joblib/parallel.py", line 598, in <listcomp>
    return [func(*args, **kwargs)
  File "/home/xxxxxx/Open3D/examples/python/reconstruction_system/make_fragments.py", line 186, in process_single_fragment
    make_posegraph_for_fragment(config["path_dataset"], sid, eid, color_files,
  File "/home/xxxxxx/Open3D/examples/python/reconstruction_system/make_fragments.py", line 127, in make_posegraph_for_fragment
    info] = register_one_rgbd_pair(s, t, color_files, depth_files,
  File "/home/xxxxxx/Open3D/examples/python/reconstruction_system/make_fragments.py", line 71, in register_one_rgbd_pair
    success_5pt, odo_init = pose_estimation(source_rgbd_image,
  File "/home/xxxxxx/Open3D/examples/python/reconstruction_system/opencv_pose_estimation.py", line 122, in pose_estimation
    success, trans, inlier_id_vec = estimate_3D_transform_RANSAC(
  File "/home/xxxxxx/Open3D/examples/python/reconstruction_system/opencv_pose_estimation.py", line 200, in estimate_3D_transform_RANSAC
    Transform_good[:3, 3] = [t_approx[0], t_approx[1], t_approx[2]]
ValueError: setting an array element with a sequence. The requested array would exceed the maximum number of dimension of 1.
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "run_system.py", line 118, in <module>
    make_fragments.run(config)
  File "/home/xxxxxx/Open3D/examples/python/reconstruction_system/make_fragments.py", line 210, in run
    Parallel(n_jobs=MAX_THREAD)(delayed(process_single_fragment)(
  File "/home/xxxxxx/.pyenv/versions/3.8.12/envs/open3d/lib/python3.8/site-packages/joblib/parallel.py", line 2007, in __call__
    return output if self.return_generator else list(output)
  File "/home/xxxxxx/.pyenv/versions/3.8.12/envs/open3d/lib/python3.8/site-packages/joblib/parallel.py", line 1650, in _get_outputs
    yield from self._retrieve()
  File "/home/xxxxxx/.pyenv/versions/3.8.12/envs/open3d/lib/python3.8/site-packages/joblib/parallel.py", line 1754, in _retrieve
    self._raise_error_fast()
  File "/home/xxxxxx/.pyenv/versions/3.8.12/envs/open3d/lib/python3.8/site-packages/joblib/parallel.py", line 1789, in _raise_error_fast
    error_job.get_result(self.timeout)
  File "/home/xxxxxx/.pyenv/versions/3.8.12/envs/open3d/lib/python3.8/site-packages/joblib/parallel.py", line 745, in get_result
    return self._return_or_raise()
  File "/home/xxxxxx/.pyenv/versions/3.8.12/envs/open3d/lib/python3.8/site-packages/joblib/parallel.py", line 763, in _return_or_raise
    raise self._result
ValueError: setting an array element with a sequence. The requested array would exceed the maximum number of dimension of 1.
karaage0703karaage0703

コメントありがとうございます。最近は使ってないのですぐ答えられないです。誰かやさしい人が回答してくださることに期待してます。すみません。