plotlyによる3Dグラフ描画
概要
pythonのライブラリ plotlyを用いて3Dグラフおよびアニメーションの表示をする方法について記述する
3Dグラフの表示
plotly で3次元の散布図を描画する例を下記に示す。scatter_3dを呼び出し3dxyzの座標を与えればグラフを描画できる。
import plotly.graph_objects as go import plotly.express as px import numpy as np import pandas as pd x = np.arange(20) y = np.random.rand(20) *20 z = np.random.rand(20) *5 # plotly expresを使う場合 # df = pd.DataFrame({ 'x_data' : x, # 'y_data' : y, # 'z_data' : z}) # # # fig = px.scatter_3d(df, x='x_data', y='y_data', z='z_data') # fig.show() # graph objectを使う場合 fig = go.Figure(data=[go.Scatter3d(x=x,y=y,z=z,mode='markers')]) fig.show()
散布図ではなく平面図として描画したい場合には、Surfaceを用いる。 Surfaceではxyzの各辺の成分を代入して3D平面をプロットすることができる。
# -*- coding: utf-8 -*- import plotly import plotly.graph_objects as go z=[ [0.0,0.0,0.0,0.0,0.0] ,[0.0,1.0,2.0,3.0,0.0] ,[0.0,2.0,10.0,6.0,0.0] ,[0.0,1.0,2.0,3.0,0.0] ,[0.0,0.0,0.0,0.0,0.0] ] fig = go.Figure(data=[go.Surface(z=z,x=[-5.0,-2.5,0.0,2.5,5.0],y=[-20,-10.0,0.0,10.0,20.0])]) fig.update_layout( title='Surface' ,scene=dict( xaxis=dict(title='x') ,yaxis=dict(title='y') ,zaxis=dict(title='z') ) ) fig.show()
複数グラフの描画(画像上に散布図を表示)
上記を組み合わせて複数のグラフを同時に描画することができる。 ここで、3DSurfaceのcolormapとして画像データを出力するようにすると、3D空間に平面として画像を表示しその上にデータをプロットすることができる。
# -*- coding: utf-8 -*- import plotly import plotly.graph_objects as go from PIL import Image import numpy as np from PIL import Image img_as_8bit = lambda x: np.array(Image.fromarray(x).convert('P', palette='WEB', dither=None)) dum_img = Image.fromarray(np.ones((3,3,3), dtype='uint8')).convert('P', palette='WEB') idx_to_color = np.array(dum_img.getpalette()).reshape((-1, 3)) colorscale=[[i/255.0, "rgb({}, {}, {})".format(*rgb)] for i, rgb in enumerate(idx_to_color)] im = np.array(Image.open('D:/VS_WS/pytest/image/Mandrill.bmp')) trace=go.Surface( z=np.zeros([256,256])-50, surfacecolor=img_as_8bit(im), cmin=0, cmax=255, hoverinfo= 'none', #画像の各画素にホバーしたときの説明を非表示にする colorscale=colorscale, showscale=False #右のカラーバーを非表示にする ) trace2=go.Scatter3d(x=[0, 10, 50, 100, 200], y=[0, 30, 70, 150, 200], z=[0,-10, 30, -20, 10], mode='markers', marker_color='rgba(0, 255, 0, .8)', ) fig = go.Figure( data=[trace,trace2], layout_title_text="3D Face Mesh", ) fig.show() fig.write_html("3Dtry.html")