3次元二値画像解析

このチュートリアルでは3次元の画像解析を行ないます。基本的な考え方は2Dの二値画像解析と同じなので、まずそちらのチュートリアルを終わらせてからこちらにトライしてください。

ここでは50x50x50のサイズの画像を解析します。3次元画像の表現方法は色々ありますが、ここでは各層ごとの断面画像を用います。 つまり50x50の画像を50個用意します。 data/ ディレクトリにファイルが置かれています。ファイル名は断面の順に付けておきます。

データファイルの読み込み

まずはこの 50x50x50 の画像を読み込んで 50x50x50 の白黒配列を作ります。

3次元配列を作る前に 0000.png を読み込んでどんな画像か確認しましょう。

これは50x50の配列で、0 から255の値を持っています。つまりこの画像はグレイスケール画像のようです。中身を見てから実際に表示してみましょう。

では50個の画像を読み込んで積み重ねます。

50x50x50の画像が完成しました。ではこれを3次元可視化しましょう。homcloud.paraview_interface モジュールを使います。 詳しくはAPIドキュメントを見てください。 VoxelData クラスを主に使います。「Apply」ボタンを押すと3次元的に表示されます。Opacityを変えるなどして中まで見てください。

パーシステント図の計算

パーシステント図を計算します。hc.PDList.from_bitmap_distance_functionを使います。 2Dの場合と同じです。

以下のようにしてファイルを読み込むこともできます。

パーシステント図の解析(1次)

1次のパーシステント図を調べていきましょう。

(-4, 4) の所に2つbirth-death pairがあるようです。これを確認しましょう

確かに2つあります。

逆解析(1次)

この2つのペアがどのような穴を表現しているのか見てみましょう。1次のパーシステントホモロジーを見ているわけですから、 何らかのリング構造を見ているはずです。それを計算しましょう。

ここでは optimal cycle というものを使います。ポイントクラウドの解析ではoptimal volumeやvolume-optimal cycleというものを用いましたが、 それと似たものです(ちょっと違います)。Pair.optimal_1_cycleで計算します。

まずはこれを可視化しましょう。元のボクセルデータを重ねあわせて表示します。

Paraviewを色々操作して見てください。ボクセルデータのOpacityを色々変えてみる、optimal 1-cyclesの線の太さを太くする、などして 見やすい設定をさぐってください。ボクセルデータの場合には1次のbirth-death pairに対応するのはトンネル構造である、というのが この可視化を見るとわかると思います。

次にこのリング構造がどういうパスを通っているのかを見ます。Optimal1CycleForBitmap.pathを使います。通過点のピクセルの座標が得られます。

パーシステント図の解析(0次)とその逆解析

次に0次のパーシステント図を解析していきましょう。

まず0次のパーシステント図をプロットします。

(-16.0, -10.0), (-15.0, -10.0) という2のbirth-death pairを詳しく調べていきましょう。 ボクセルデータの0次と2次の逆解析にはBitmapPHTrees というクラスを使います(1次には使えないので、上で説明した optimal_1_cycle を代わりに使いました)。 BitmapPHTrees.for_bitmap_distance_functionPDList.from_bitmap_distance_functionと似たインターフェースで 逆解析用の情報を計算します。

この PHTrees という名前は、ここで計算されるものが木構造であることを意味しています。 n次元のビットマップデータに対して0次とn-1次の2つの情報を同時に計算して、2つの木構造を持っています。 この木構造を取りだすためには PDList.bitmap_phtrees というメソッドを使います。

以下のようにして計算したデータを読み込みます。

0次の情報を取り出すのは bitmap_phtrees(0) を使います。

(-16.0, -10.0), (-15.0, -10.0)という2つのbirth-death pairの情報を取り出すのには pair_nodes_in_rectangleを使いましょう。これは指定した範囲内にある birth-death pair (に対応する木構造のnode)をすべて取り出します。

取り出したデータは BitmapPHTrees.Node というクラスのインスタンスです。次にこれらの情報を可視化しましょう。

Paraviewをうまく使って(Opacityを変えるなど)可視化された情報をうまく観察してください。0次のPHなので、ボクセルの内側の領域に 対応しています。実はこの2つのbirth-death pairは木構造上の親子関係にあり、一方が他方の部分集合になっています。

パーシステント図の解析(2次)とその逆解析

最後に2次のパーシステント図を解析していきましょう。

2次のパーシステント図をプロットします。

(4, 6)というbirth-death pairを調べます。逆解析には bitmap_ph_trees(2)を使います。2が次数です.

(4, 6) という birth-death pairを調べましょう。まず pair_nodes_in_rectangle で (4, 6) という birth-death pair (に対応した tree の node) をすべて取り出します。

2個の 以下が可視化した結果です。くりぬかれた領域の奥のほうがこのbirth-death pairに対応していることがわかると思います。

volumeメソッドを使うことでこの領域の各座標を得ることもできます。