表面形状をあつかうファイル形式に、.ply形式のファイルがあります。
これはPolygon File Formatといって3次元データを値付きで保存している形式になります。
PLYファイルは3Dスキャンしたデータなどに用いられていますが、3次元データに色をつけて可視化できるという点で、様々な形態解析に用いることができます。
- PLYファイルの構造を知る
- 自分でデータを入れてPLYファイルを作成する
1 PLYファイルの構造を見てみる
PLYファイルは
- ヘッダー
- 点情報と値(色、Quality)
- 面を構成する点情報と値(色、Quality)
の順に記載されている。
まずはPLYファイルがどのような構造になっているか見てみます。
例えば、手首の骨を見た時に、骨1(bone1)と骨2(bone2)の距離を図り、骨1に色付けしたとします。
赤はより近い部分、青はより遠い部分になるように色付けされています。
このとき、実際に骨1の表面データには
「距離という値」
が入っています。
これが色で図示されているわけです。
このファイルの距離の情報はSTLでは保存されませんが、PLYというファイル形式であれば保存されます。
ここではPLY形式のASCII形式で保存して、テキストファイルで開いてみます。
format ascii 1.0
comment VCGLIB generated
element vertex 23866
property float x
property float y
property float z
property uchar red
property uchar green
property uchar blue
property uchar alpha
property float quality
element face 23802
property list uchar int vertex_indices
property uchar red
property uchar green
property uchar blue
property uchar alpha
end_header
-126.7488 -31.52647 -816.0538 0 0 255 255 120.3788
-126.4972 -31.27693 -815.8904 0 0 255 255 120.3788
-126.4011 -31.52209 -816.0673 0 0 255 255 120.3788
-127.0804 -31.64915 -816.0208 0 0 255 255 120.3788
-127.0749 -31.37141 -815.8459 0 0 255 255 120.3788
-127.4964 -31.62467 -815.8231 0 0 255 255 120.3788
-123.8012 -32.81599 -816.433 0 0 255 255 120.3788
・
・
・
3 13771 13847 13851 255 255 255 255
3 13776 13771 13851 255 255 255 255
3 13777 13776 13852 255 255 255 255
3 13776 13851 13852 255 255 255 255
3 13853 13852 13854 255 255 255 255
3 13853 13778 13852 255 255 255 255
3 13778 13777 13852 255 255 255 255
3 13778 13853 13780 255 255 255 255
・
・
・
・
謎の英語のあとに数字の羅列がみられます。
よくみると数字は2つの部分からできています。
element vertexというのが点の数、
element faceというのが面の数ですね
始めの数字の1行目をとってみると、
-126.7488 -31.52647 -816.0538 0 0 255 255 120.3788
となります。
これが
property float x
property float y
property float z
property uchar red
property uchar green
property uchar blue
property uchar alpha
property float quality
の部分に対応します。
つまり、
-126.7488 -31.52647 -816.0538
が点の x, y, z座標
0 0 255 255
は色(赤 緑 青 透明度)
120.3788
が値(この場合は距離)
です。
この
float qualityに値を入れているのがポイントです。
3 13771 13847 13851 255 255 255 255
3 13776 13771 13851 255 255 255 255
3 13777 13776 13852 255 255 255 255
3 13776 13851 13852 255 255 255 255
3 13853 13852 13854 255 255 255 255
3 13853 13778 13852 255 255 255 255
3 13778 13777 13852 255 255 255 255
3 13778 13853 13780 255 255 255 255
は
property list uchar int vertex_indices
property uchar red
property uchar green
property uchar blue
property uchar alpha
に対応しています。
始めの
3
は、3つの点から面が構成されていることを示します。
13771 13847 13851
は3点を表します。
ここで、点は始めの数字列の中で出てきた番号を示しています。
255 255 255 255
は色(赤 緑 青 透明度)です。
このモデルはすべて255なので、面自体には色付けされていないことがわかります。
Meshlab上でもColorの欄をVertからFaceに切り替えると真っ白になります。
Vert(頂点)だと色がついています
Face(面)にすると真っ白です
2 PLYデータの作成
形式を知ると、自分で計算した結果をplyファイルで表示できるようになります。
結果を可視化できるという面で、いろいろな解析に使用できます。
順序としては
stlファイルから点情報と面情報を取り出す
↓
stlで計算を行う
↓
値をstlから得た点にひも付けする。
↓
ply形式で書き出す。
という流れです。
(1)stlデータから点と面データの抽出
例として、犬の形をしたstlのデータを使用します。
stlデータの抽出にはnumpy-stlを用います。
import numpy as np
from stl import mesh
surface = mesh.Mesh.from_file('dog.stl')
point_list = surface.points.reshape([-1, 3])
print(len(point_list))
# 298272
print(point_list)
[[-2.6301 6.9699 15.6182]
[-2.6115 7.205 15.5955]
[-2.7722 7.1841 15.4071]
…
[ 2.8899 -9.5252 24.7799]
[ 2.8352 -9.4917 24.8507]
[ 2.8318 -9.478 24.8437]]
これは三角形を構成する点同士がたくさんならんでいる状態です。
三角形1の点1のx,y,z
三角形1の点2のx,y,z
三角形1の点3のx,y,z
三角形2の点1のx,y,z
三角形2の点2のx,y,z
三角形2の点3のx,y,z
三角形3の点1のx,y,z
・
・
という状態なので、plyの形式どおり、
- 点のデータ
- 三角形の頂点の番号
にわけたいと思います。
重複を削除するために
「numpy.unique」
を使用します。
vertices, vertex_indices = np.unique(point_list, return_inverse=True, axis=0)
point_listの中で重複を削除したリストがverticesに入り、
それぞれの点のverticesのインデックス番号がvertex_indicesに入ります。
print(len(vertices))
# 49714
print(vertices)
#[[-5.7769 16.6657 0.4585]
# [-5.7701 16.8729 0.5121]
# [-5.7679 16.8331 0.6828]
# ...
print(vertex_indices)
# [12173 12257 11565 ... 38652 38419 38407]
# 重複をリストにし、verticesに対応するリストのインデックスを返す
3つずつくくってやると、三角形のインデックス番号が並びます。
index_triangle = vertex_indices.reshape([-1, 3])
print(index_triangle)
[[12173 12257 11565]
[12173 11565 11472]
[12062 12173 11472]
…
[38875 38669 38652]
[38652 38669 38419]
[38652 38419 38407]]
(2)plyに書き込む
plyファイルはヘッダーで指定してやれば点の座標値とqualityだけでも成立します。
ここではテストとして、犬のstlのデータの
qualityにy座標の値を指定
して.plyファイルを作成してみます。
構造は以下の通りです。
ply
format ascii 1.0
element vertex “点の数”
property float x
property float y
property float z
property float quality
element face “三角形の数”
property list uchar int vertex_indices
end_header
点1のx, y, z, quality
点2のx, y, z, quality
・
・
3, 三角形1の点1のインデックス,点2のインデックス, 点3のインデックス,
3, 三角形2の点1のインデックス,点2のインデックス, 点3のインデックス,
・
・
・
これをPythonで記載します。
座標データとqualityデータの結合にはnumpy.concatenateを使用しています。
import numpy as np
from stl import mesh
"""Extract point and face data from .stl file"""
file_name =('dog_test.ply')
dog_stl = mesh.Mesh.from_file('dog.stl')
points = dog_stl.points.reshape([-1, 3])
vertices, vertex_indices = np.unique(points, return_inverse=True, axis=0)
#点の重複を削除し、それぞれのインデックスを取得
index_triangle = vertex_indices.reshape([-1, 3])
#三角形を構成する点のインデックス一覧を取得
"""write header"""
header = (
'ply\n\
format ascii 1.0\n\
element vertex {}\n\
property float x\n\
property float y\n\
property float z\n\
property float quality\n\
element face {}\n\
property list uchar int vertex_indices\n\
end_header\n').format(len(vertices),len(index_triangle)
)
# element vertexとelement faceの部分はstlからの値を代入
with open(file_name, 'w') as f:
f.write(header)
"""write text for point data"""
qualities = np.array([vertices[:, 1]]).T
# y座標をqualityに設定し、縦1列の行列にする
vertices_text = np.concatenate([vertices, qualities], axis=1)
# x,y,z座標の後ろにqualityを付け加える
with open(file_name, 'a') as f:
np.savetxt(f, vertices_text, fmt='%.5f')
# 'a'モードで点情報を上書き追記する
"""write text for face data"""
first_indices = np.full([len(index_triangle), 1], 3)
face_txt =np.concatenate([first_indices, index_triangle], axis=1)
# 三角形である'3'を先頭に記載してから三角形の点インデックスを記載する
with open(file_name, 'a') as f:
np.savetxt(f, face_txt, fmt='%i')
#上書きで三角形の情報を追記する
“dog_test.ply”というplyデータが作成されました。
3 PLYデータの確認
“dog_test.ply”をテキストファイルで開くと
ply
format ascii 1.0
element vertex 49714
property float x
property float y
property float z
property float quality
element face 99424
property list uchar int vertex_indices
end_header
-5.77690 16.66570 0.45850 16.66570
-5.77010 16.87290 0.51210 16.87290
-5.76790 16.83310 0.68280 16.83310
・
・
3 12173 12257 11565
3 12173 11565 11472
3 12062 12173 11472
3 12062 11472 11382
3 12173 12062 12870
3 12173 12870 12997
・
・
・
qualityの欄にy座標の値が入っています。
これをMeshlabで開きます。
右上のカラフルなうさぎのボタンをおすと、「QualityMapperDialog」というウィンドウが開きます。
これは、Qualityにカラーマップを付けくれるダイアログです。
「Apply」を押すとMapperが適応されて、plyに色がつきます。
Y軸の大きいほうがQualityの大きい赤色になっていることがわかります。
Qualityの範囲の点だけ選ぶこともできます。
「Filters」 ⇒ 「Quality Measure and Computation」⇒ 「Select by Vertex Quality」を選びます。
Previewをクリックしてから、Qualityの範囲を選ぶと、範囲内のQualityをもった点が選択されます。