Meshmixerで底抜け解消そして  closing up a big gap in the 3D mesh using Meshmixer, and

はじめに

 やっと,大饗石の底抜けを解消することができた。Autodesk Meshmixerはオープンソースである。ありがたい。一昨晩,寝る前の恒例のTV録画鑑賞に入る前に,出会ったのである。Meshmixerというぐらいだから,点群よりもメッシュに対応している。ぼくのイメージでは,これを使えばIllustratorのように穴の周辺のネットを引っ張ってブリッジをどんどん架けて,その隙間は一気に埋められるというような印象があって,実際にやろうとしたが全然そうはならない。
 とはいえ,3Dスキャンで得たオブジェクトのデコボコを滑らかにすると行ったことは手作業でできる。CloudCompareやMeshLabでは到底できないことである。iPhoneLiDARで作成した3Dスキャンオブジェクトのネットが綻びているのは普通のことで,この解消はCloudCompareではできず,MeshLabの役目ではあった。MeshLabでコマンドを実行するにしても,パラメータの役割が説明を読んでも理解できず,無力感が襲うのであるが,Meshmixerを使っていて,そういう感覚は全く生まれず,実行プロセスが目の前に見えて,何とも頼もしい。これを無料で提供しているAutodesk恐るべしである。このアプリの目的は,3Dプリンター用のファイルを作成することにあるが,残り少ない人生,この分野には到底入れない。

1 Autodesk Meshmixer

Meshmixer 3.5 is now available ! https://meshmixer.com/download.html

Japanese Installer Windows 3.5,System Requirements Meshmixer 3.5 Microsoft Windows 7 or later 4GB system RAM Release April 17, 2018.

Wikipedia:  スカルプトモデラー。 Sculptor modeler,いわば彫像や塑像を作るソフトだろうか。メッシュの合成、メッシュの伸長・回転、メッシュ選択のスムース化などの機能を持つ。3Dプリンタ向けに、床面上への複数オブジェクトの詰め込み (Layout/Packing Tool)、効率的な支柱構造を自動的に追加する機能が追加されている。開発終了。

————————————————
Autodesk Meshmixer UI解説 -2つの3DデータをMIXする-

Autodesk Meshmixerは無料で公開されているスカルプ系の3Dモデリングソフト。簡単な操作で加工ブラシを使用して、粘土を扱うようにモデル表面を変形することができ,3Dスキャンデータの修復や3Dオブジェクトデータの合成,3Dプリンターのデータ作成を気軽に行うことが可能。
ここでは、UIの解説と、2つの3DデータをMIXする方法を解説する,とある。

2 3D底抜け解消が実現

当方の,C:/Users/moto/Documents/win_moto_documents/win_3d_scan/大饗石metascan_LiDAR/大饗石from_iPhone/onlyOoaeishi_closeHole.mlp というMeshLabファイルを使う。

 左のメニューアイコンで実行する。上のメニューからでも可能。図1は大饗石objをインポートしたところで,次にメッシュの綻びをチェックすべく,解析 > 検証を選択直後の様子が図2である。大饗石の底抜けの部分には赤い縁取りが見られるが,銀色の表面の部分の穴がチェックされているようだ。図3は「すべて自動修復」ボタンを押した後の画面である。結構の時間がかかったように思う。

図1 大饗石のobjファイルをimportした
図2 解析 > 検証
図3 「すべて自動修復」の実行後 

 図4では,解析 > ソリッド作成,を実行しているところである。かなりの時間を要した。図5は完了した際の画面で,ソリッド作成のパネルが現れて,細かなパラメータの設定ができる。ぼくはこの結果に満足して,下の「適用」のボタンをクリックして,図6の表示を得た。とにかく,永らく切望していた大饗石オブジェクトの頑丈な底ができている。ソリッドの意味がわからない。蓋ができても中味は空っぽだ。

図4 解析 > ソリッド作成
図5 ソリッド作成直後
図6 適用,の直後

 図7は,インポートしたオブジェクトだ。パネルでその選択をしている。図8はソリッド化されたオブジェクトだ。このオブジェクトを選んだ状態で,エキスポートした。図9では,Mesh_step3_obj_mixer2.objとした。この前に,Mesh_step3_obj_mixer2.mixで全体を保存している。

図7 Mesh_step3.obj 表示
図8 Mesh_step3.obj(ソリッド)表示
図9 エキスポート: Mesh_step3_obj_mixer2.obj

以上,0:20,Sep. 23, 2023記。

3 体積をCloudCompareで求めるーMeshmixerで穴埋め,平坦化

 CloudCompareに取り込んで,Edit > Mesh > Measure volume,を実行。V= 37.7436,
mesh has hole。またこのメッセージだ。図10ではwireframe表示して観察したが,穴は見えないなあ。面積も求めた(図11)。

図10 CloudCompareで体積を求めたが
図11 面積も

 図12は,Meshmixerで,解析 > 検証 > すべて自動修復,の実行後。この前に,沢山の穴の表示があったが,撮影を忘れた。ソリッド化を実行した後,改めて,解析 > 検証 > すべて自動修復,を実行する必要があった,ということらしい。今後はそうしたい。

図12 自動修復後
図13 ブラシで北壁をフラット化(途中)
図14 ブラシで北壁をフラット化済

 図13, 14は,スカルプトsculpt(動詞しかないが) > ボリューム選択 > フラット化 flatten,を北壁について実行してゆく過程を示している。繰り返すとどんどんフラット化がすすむ。元々のオブジェクトはフラット化後の雰囲気に似ていたが,作業過程を進めて行く過程でボコボコになったので,この種の作業そのものが体積計算の正確度を下げるものでは無いと感じている。
 他の面のフラット化も記録?のために,鬱陶しいだろうが以下に示す。

図15 南面のフラット化実行前
図16 南面のフラット化実行後
図17 頂面のフラット化実行前
図18 頂面のフラット化実行後
図19 東面のフラット化実行前
図20 東面のフラット化実行後
図21 西面のフラット化実行前
図22 西面のフラット化実行後
図23 底面のフラット化実行前
図24 底面のフラット化実行後
図25 西北西付近のフラット化実行前
図26 西北西付近のフラット化実行後

 以上の作業がholeを埋める効果があるとは思えないが,外から見て穴のように見える部分がほぼ無くなって,実体に近くなっていると感じている。
 もう一度,解析 > 検証 > すべて自動修復。穴なし。終了。
 名前を付けて保存。Mesh_step3_obj_mixer3.mix,エキスポート
Mesh_step3_obj_mixer3.obj だ。

4 体積をCloudCompareで求めるー警告メッセージから回避できた

 Mesh_step3_obj_mixer3.obj をCloudCompareで開いて,図27のDB Treeに見られるようにメッシュを選択して,Edit > Mesh > Measure volume,実行。計算結果は,V=37.6635。警告メッセージが無くなった。成功だ。Edit > Mesh > Measure surface,実行,S=69.7372。図27最下部のコンソールに見える。

図27 objファイルから体積と面積が正しく求められた

 点群verticesをPLYで保存する前が図28である。

図28 objファイルのverticesを選択して

5 OBJファイルの点群verticesから2.5D volume 計算

 上記PLYファイルをCloudCompareで開いてcloudを選択し,bottom view(図29)。点群対象のcompute 2.5D volume分析のために,上下に点群を分割したい。外周の一番の出っ張りをトレースしてsegmentationを実施したいと考えた。segmentationはsegment in or outを実行をしないとオブジェクトの移動などができないので,1回で分割しなければならない,と呆けで決めつけてしまった。それで,図30のように,set bottomにしてその縁辺で切り取るしか,方法はない,と考えたのである。
 図31には,ポリゴンの選択を完了した様子(緑色細線の閉曲線)が見える。

図29 PLYファイルを開いてcloudを選択
図30 set bottomでsegmentationのトライ
図31 ポリゴンツールによる選択完了

 図32はsegment outを実行したところで,図31のポリゴンツールで閉曲線を作成した筈であるが,囲んだ範囲の外側が図32のcloudとなったのである。図33ではconfirmした結果で,DB Treeのremainingとsegmentedの両方が選択されている。図34はこのオブジェクトのleft side viewで,切り口は見えない。まだ事態が掴めない。

図32 segment out 実行
図 33 confirm segmentation
図34 left side view

 図35で見ると,segmentedは欲しいcloudの筈なのだが不要な方がそうなっている。図36, 37はremainingのトップからとボタムから見たcloudだ。

図35 segmentedのtop view
図36 remaining のtop view
図37 remainingのbottom view

 図38のfront viewを見ると,オブジェクトが図35のcloud抜きなので,完全に分離されている。もしこのtopとbottomを使う場合,点群remainingに,上下の点群が一つの点群エンティティーになっているので,分割する必要があるが,それはできないっ,とその時は思ったのである。
 意味ないのだけど,remainingとsegmentedの両cloudを選択して,mergeしようとしているのが図39である。図40にはmergeの結果が見える。赤い点群はsegmentedのcloudである。まあ,全くの失敗なのでdeleted。お試しだ。

図38 remainingは完全に2分割されている
図39 Mergeを実行する直前
図40 mergeの結果

 練習2だ。図41はtop view。図42はsegment in。図43で見ると,remainingだけ表示しているが,不連続で断裂してる。回転などして3D構造を見ると,手前の壁だけでなく,奥の壁も削除されているようにも。bottom viewでみて,連続性を考慮して,もう一度トライしてみよう。deleted。

図41 top view
図42 segment in
図43 confirm, remainingを表示

 また読み込んだ。どうも試行錯誤で,なんかわかったような。図44のようにbottom viewにして,図45のように,適当にsegmentした。そして,segment out(図46)。

図44 bottom view
図45 適当にsegmentする
図46 segment out

 図47のようにポリゴンで選んで,segment outしたら,選んだ範囲以外のcloudが残る形だ。そういえば,そうだよなあ。この結果をキャンセル(ツールの✖️)。

図47 底面も頂面も削除されている
図48 見える範囲で適当に縁辺だけ
図49 segment out どうも奥も切れている

 図50は開始前,図51ではsegment out。図52はconfirm前。

図50  開始前
図51 segment out
図52 confirm前

 図53, 54, 55。試行錯誤。ceilとgroundになる点群の分割を考えている。少しずつ,segment outを繰り返している。

図53 confirm前
図54 confirm前 
図55 こんなものかなあ

 図56で,複数回のsegment outに対して,confirm segmentation実行した。図57は,segmentedだけを表示。図58ではremainingだけを表示した。これがsetment outの結果でsegmented outされた「残り」であって,感覚的には,削除を繰り返してきた点群がいわばメモリー内でマージされていたのである。

図56 confirm segmentation実行
図57 segmentedの表示
図58 remainingの表示

 toolでの点群体積計算で,Ceilがsegmentedで,groundがremainingに対応することになるだろう。図60では両cloudを選んで,Tools > Volume > 2.5Dvolumeを実行することになる。図61を見ると,groundに対応するcloudはremainingで,ceilに対応するcloudはsegmentedになっているので,いい感じだ。ただ,At least one of the cloud is sparse! You should fill the empty cells… という警告が出ている。 step: 0.03(3 cm)。図62との違いはEmpty Cellsをleave emptyにしているかinterpolateにしているかの違いで体積値が変わる。

図60 両cloudを選んで
図61 UpdateでVolume 25.879
図62 UpdateでVolume 21.376

 Calculated volume in 2.5 d changes with grid step size bug? を参照のこと。それで,図63では,両点群のEmpty cells: interpolate,Grid step 0.10(10cm)にした。かなり粗いグリッドだが,Volume 32.205,Surface 18.750,Matching cells: 81.9%,となった。警告が出なくなった。図64のように,Export grid as a cloudのボタンをクリックすると,シーンにカラーによる高度頻度分布図がHeight deiffernce raster(0.1)として出力されている。図64のパネルの最下部でOKを押すと,図65のように,パネルが消えてシーンには高度頻度分布図が配置されている。

図63 Grid step 0.10(10cm)など
図64 Export grid as a cloudを選択
図65 パネルが消えて高度頻度分布図がシーンに配置されているのが見える

 図66に示した結果が最適値である。grid step 0.200,Volume 32.441, Matching cells: 82.4%。gridが粗いのでもちろん警告は出ていない

図66 最適値

6 OBJファイルの体積計算結果にもう少し拘ってみたい

 以上から,メッシュオブジェクトと点群オブジェクトの体積計算値をその限界精度から考えると,メッシュオブジェクトの計算,Edit > Mesh > Measure volume,の結果,V=37.6635を採用するのが,妥当ということになる。点群オブジェクトの計算過程を見ると粗雑になっている。とはいえ,両値は,かけ離れていないし,点群の値はメッシュの計算結果をサポートしているとも考えられる。
 体積計算にもう少し拘りたいと思う。一つは,点群密度の向上であり,もう一つは手作業での四面体分割法での計算である。

以上,0:35,Sep. 24, 2023記。

 ぼくにとっては,このウェブページを書いた当日に寝ながら,考えて,新たな修正原稿をこの月曜日の事務スタッフ出勤前に,Google Driveにアップロードするのが,ベストだと考えた。Meshmixerによるソリッド化の成果を生かすことにした。

 で,このウェブページが完結できていないので,いま,その後片付けをしたいと思う。すでに述べてきたことであるが,点群のメッシュ化,さらに点群への変換を実行する。その手法は,すでに述べてきたことであるが,

点群PLYのエンティティーを選択して,
 ① Edit > Normals > Compute(デフォルト値)を実行すると,Octreeがこの下位に作成される。
 ② 同エンティティーを選択して,Edit > Mesh > Delaunay2.5D(best fitting plane)を実行。この直後にnormalsに関するメッセージが出るが触らずにYes。その結果,対象エンティティの下位でOctreeと同階層に隙間の無いMeshエンティティー(メッシュアイコンが付加されている)が作成される。
 ③ このメッシュエンティティーを選択して,Edit > Mesh > Sample PointsでデフォルトでOK。デフォルトで百万点にしていたので作成されるエンティティーも1,000,000点になる。
 このプロセスを実行する前の筆者が使った点群PLYは2万点であったから,Points数は50倍になっている。なおこのエンティティーは元の点群PLYと同じ階層に生成される。

図67では点群cloud 50,312 pointsである。

図67 Mesh_step3_obj_mixer3.CCvertices-Cloud segmented

図68は②実行後で,Octreeとともに,meshエンティティーが形成されている。

図68 ②の実行後

図69は,③の実行後で,Mesh_step3_obj_mixer3.CCvertices-Cloud segmented.mesh.sampled を表示。点群cloudのpoint数は,百万点になった。

図69 ③の実行後

図70はボタムのremaining対応を表示している。①〜③実行済みで,これも,point数を百万点にしている。

図70 ボタムのremaining top view

図71のように,両cloudを選択している。

図71 両cloudを選択。

Tools > Volume > Compute 2.5D volume,を実行した。自動で,Ground: remaining 底
Ceil: segmented 地上部,Grid step 0.005 5mmだった。警告なし。計算結果は,Volume 31.825,Surface 17.921,Matching cells 81.6。

図72 step: 0.005

Grid step を0.02にしてみよう。Volume 31.865,Surface 18.050,Matching cells 81.7。

図72 step: 0.02

Grid step 0.005 5mmだ。Height difference raster (0.005)北壁のポイント密度が少ない。

図73 パネル表示を外した

 以上の結果を踏まえて,文学論集Vol. 73-3の原稿に反映している。以下,それを次に。

7 フィールド科学のためのアップルLiDAR測量 Part 2 Ⅴ.4 Meshmixerで大饗石の底抜けを解消して体積を求める

 文学論集Vol. 73, No. 3(発行は2023年末ぐらいか)

 Meshmixer 3.5 is now available ![i] からこのアプリをダウンロードできる。筆者が用意していた大饗石オブジェクトだけのMeshLabファイルからobjファイルを抽出してMeshmixerにインポートした。メッシュの綻びをチェックすべく,解析 > 検証,を選んだ。かなりの綻びがシーンに表示される。「すべて自動修復」ボタンを押した。実行にかなりの時間を要した。MeshLabでこの種の作業を実施してきたファイルであったが,Meshmixerからすると今だ綻びがあるようだ。Meshmixerは,ビジュアルに簡便に,この種の作業が実施できる。これは驚きであった。

 その上で,解析 > ソリッド作成,を実行した。これも時間を要したが,図33(a)のように見事に底抜けが解消した。しかもMeshLabでのポアッソン再建の如く異様に膨らむこともなく,しっかりとした薄皮一枚で底抜けが解消されたのである。


[i] https://meshmixer.com/download.html

図33 Meshmixerによるソリッド化とフラット化

 Meshmixerは,編集過程などでの3Dオブジェクトの変形を修復する機能を持っている。ここではブラシのフラット化ツールをつかって修正した結果を図33(b),(c)に示している。(b)は(a)の新たに付加された底面をフラット化ツールを使って滑らかにしたbottom viewの結果である。(c)は大饗石地上部の東壁および周辺をフラット化したもので,これはフラット化前の(a)右手突出部に対応している。

 なお,このような作業を経たファイルはCloudCompareで開く前に,Meshmixerで,解析 > 検証 > すべて自動修復,を改めて実行しなければならない。

Ⅴ.4.a 大饗石objファイルのメッシュ体積計算

 このobjファイルをCloudCompareで開いて,Edit > Mesh > Measure volume及び > Measure surfaceを実行すると,図34(a)のように,V = 37.6635(警告メッセージなし),S = 69.7372を得ることができた。

Ⅴ.4.b 大饗石objファイルの点群verticesから2.5D volume計算

 objメッシュファイルには点群verticesが含まれており,これを使うと点群対応の2.5D volume計算が可能になる。2.5D volume計算は,Ceil(シール,天井面)にあたる点群とGround(底面)にあたる点群の間の3D空間を垂直方向の小さな立方体で構成される正四角柱で分割して,CeilとGroundの間の立方体を数える手法である。

図34 CloudCompareでメッシュ体積面積計算と点群体積計算の準備

 この手法では,objファイルの点群verticesを,3D構造を考慮して,Ceil点群とGround点群に分割する必要があるが,で示した分割ツールを使って,Ceil点群とGround点群として,それぞれsegmented点群とremaining点群を割り当てることになるのである。図34(b)では分割できた両点群を選んで表示しているので,シーンには⋯⋯segmented⋯⋯と⋯⋯remaining⋯⋯の名称が見える。白っぽく広い面は底面の部分であって,Ground点群に対応している。

図35 点群2.5D volume計算

 Ceil点群とGround点群それぞれを構成する点数は,この大饗石の例ではそれぞれ5万点,2万点ほどなので,Ⅲ.4 計算結果の比較,で述べた「点群ファイルPLYからメッシュに変換しさらに点群に変換したエンティティー」(脚注[i]に説明)の手法で,それぞれ百万点ほどに増やして,図34(b)のようにCceilとGgroundの両点群を選択して,Tools >Volume > Compute 2.5D volumeを実行した。実行結果を図35に示している。正四角柱の断面は正方形であるがその一辺をCloudCompareではGridのstepといい,図35のものはstep=0.005mとしている。図35(a)は計算結果のパネルを示していて,この結果の数値がみえるように切り取って拡大している。Volume: 31.825㎥,Surface: 17.921㎡,Matching cells: 81.6%を示している。なお,Compute 2.5D volumeが算出するSurfaceは,前述のようにオブジェクトの(Z軸に垂直な)平面図の面積を示しているようだ。このパネル下部のOKボタンを押すと,パネル表示が消えて,図35(b)が現れる。点群密度は,反射光量を反映して北壁は南壁に比べるとかなり低い。大饗石の標高分布別に赤色と緑色の間で段彩(原図はカラー)されており,最下部付近の緑色の点群の塊はGround cloudに相当するものである。

 なお,上述のように点群の点数を増やさない場合,step: 0.1より小さくすると,赤字でAt least one of the cloud is sparse! You should fill the empty cells..という警告が現れる。Ⅴ.4.aのメッシュの体積は前述のように37.6635㎥であった。点群の体積は31.825㎥である。メッシュの体積は,図34(a)のメッシュ拡大図に見えるようにメッシュエンティティーは三角面triangle facesからなり,適当な原点から三角面それぞれの頂点に側稜が伸びて,オブジェクトは三角錐で埋められる。それぞれの三角錐の体積の総和がメッシュファイルの体積となる。前述のように2.5D volume法はこのメッシュ法に比べると粗雑になっているので,メッシュ法の体積V = 37.6635㎥を採用することになる。土木工事などで工事の前後の土量の移動などの場合は,適用が2.5D volume法に限定されるので,もちろん,使用価値はある。


[i] 点群PLYのエンティティーを選択して,① Edit > Normals > Compute(デフォルト値)を実行すると,Octreeがこの下位に作成される。② 同エンティティーを選択して,Edit > Mesh > Delaunay2.5D(best fitting plane)を実行。この直後にnormalsに関するメッセージが出るが触らずにYes。その結果,対象エンティティの下位でOctreeと同階層に隙間の無いMeshエンティティー(メッシュアイコンが付加されている)が作成される。③ このメッシュエンティティーを選択して,Edit > Mesh > Sample PointsでデフォルトでOK。デフォルトで百万点にしていたので作成されるエンティティーも1,000,000点になる。このプロセスを実行する前の筆者が使った点群PLYは2万点であったから,Points数は50倍になっている。なおこのエンティティーは元の点群PLYと同じ階層に生成される。


図36 Surfaceを構成するセルマップ

 なお,図35(a)のSurface値:17.921の算出法について確認したい。step値は図35(a)では0.005で図で表現しにくいので,step: 0.200として図36に示す。ここでは,V:32.441,S:19.840, Matching cells: 82.4%になる。CeilとGroundの両cloudで算出する場合,Surfaceの計算式にMatching cells(%)値は関与しない。

以上,Sep. 29, 2023記