PyOpenGL3.0について
PyOpenGLはOpenGLをPythonで扱うためのライブラリです。
PyOpenGL3.0のインストール
PyOpenGL3.0の公式サイトhttp://pyopengl.sourceforge.net/documentation/installation.html
Downloads>PyOpenGLからダウンロード。PyOpenGL-3.0.1.win32.exeを起動するとすぐにインストール終了。
PyOpenGLの簡単なサンプル
黒画面に三角形を表示するだけのサンプルです。OpenGLの関数をそのまま利用することができます。
InitGLでOpenGLの初期化、DrawGLSceneで描画を行っています。
from OpenGL.GL import * from OpenGL.GLUT import * from OpenGL.GLU import * def init(): glClearColor(0.0, 0.0, 0.0, 0.0) def display(): glClear(GL_COLOR_BUFFER_BIT) glBegin(GL_TRIANGLE_STRIP) glVertex2d(0.,0.) glVertex2d(0.7,0.7) glVertex2d(0.,0.7) glEnd() #double buffer glutSwapBuffers() def main(): glutInit(sys.argv) glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE) glutInitWindowSize(400, 300) glutInitWindowPosition(0, 0) glutCreateWindow("PyOpenGL") glutDisplayFunc(display) init() glutMainLoop() main()
matplotlibで画像を表示する
matplotlibで画像を表示させるための手順について。
matplotlibはPILを利用して画像の描画を行っているため、PILの機能に準じた処理になります。PILを使って画像の値を配列形式として読み込む作業を、matplotlibを使うと簡単に行うことができます。
画像の読み込みと描画
最も単純なサンプルです。
import matplotlib.pyplot as plt import matplotlib.image as mpimg img=mpimg.imread('test.png') #image to array plt.imshow(img) #array to 2Dfigure plt.show()
matplotlib.imageのimreadで画像を配列に変換します。配列のデータを、pyplotの図にレンダリングする関数がimshowです。
print img
例えば全ての成分が赤であるRGB画像では次のように値が格納されます。
[ [ [ 1. 0. 0.]
[ 1. 0. 0.]
[ 1. 0. 0.]
略
...,
[ 1. 0. 0.]
[ 1. 0. 0.]
[ 1. 0. 0.] ] ]
ヒストグラムの表示
pyplotにヒストグラムを表示する機能としてhist関数が提供されているのでこれ画像処理用のヒストグラムにしてみます。
import matplotlib.pyplot as plt import matplotlib.image as mpimg img=mpimg.imread('test.png') plt.figure(1) #red plt.subplot(311) r_img = img[:,:,0] plt.hist(r_img.flatten(), 256, range=(0.0,1.0), fc='r', ec='k') #green plt.subplot(312) g_img = img[:,:,1] plt.hist(g_img.flatten(), 256, range=(0.0,1.0), fc='g', ec='k') #blue plt.subplot(313) b_img = img[:,:,2] plt.hist(b_img.flatten(), 256, range=(0.0,1.0), fc='b', ec='k') plt.show()
引数のfcは棒グラフの棒の色、ecは棒のエッジ部分の色です。色の情報を0.から1.までの範囲で描画します。
img[:,:,0]で赤の成分を、img[:,:,1],img[:,:,2]で緑と青の成分を抽出した配列を生成します。例えば、全ての成分が赤であるRGB画像に対してimg[:,:,0]は下のような配列を生成します。
plt.subplot(31*)で3つの図を用意して、上からR,G,Bに対応したヒストグラムを描いています。
[ [ 1. 1. 1. ..., 1. 1. 1.]
[ 1. 1. 1. ..., 1. 1. 1.]
[ 1. 1. 1. ..., 1. 1. 1.]
...,
[ 1. 1. 1. ..., 1. 1. 1.]
[ 1. 1. 1. ..., 1. 1. 1.]
[ 1. 1. 1. ..., 1. 1. 1.] ]
scipyと組み合わせる
scipyを使うと画像処理テスト用のレナ画像を読み込めます。読み込んだ画像の形式は、RGBそれぞれの二次元配列のリストです。Rだけ取り出すにはimg[0]だけでよいです。ただし、値はさきほどと違って0.から255.になっているので注意。
from scipy import signal, misc from numpy import * img = misc.lena().astype(float32) print img
[ [ 162. 162. 162. ..., 170. 155. 128.]
[ 162. 162. 162. ..., 170. 155. 128.]
[ 162. 162. 162. ..., 170. 155. 128.]
...,
[ 43. 43. 50. ..., 104. 100. 98.]
[ 44. 44. 55. ..., 104. 105. 108.]
[ 44. 44. 55. ..., 104. 105. 108.] ]
import matplotlib.pyplot as plt import matplotlib.image as mpimg #img=mpimg.imread('test.png') from scipy import signal, misc from numpy import * img = misc.lena().astype(float32) plt.figure(1) #red plt.subplot(311) r_img = img[0] plt.hist(r_img.flatten(), 256, range=(0.,255.), fc='r', ec='k') #green plt.subplot(312) g_img = img[1] plt.hist(g_img.flatten(), 256, range=(0.,255.), fc='g', ec='k') #blue plt.subplot(313) b_img = img[2] plt.hist(b_img.flatten(), 256, range=(0.,255.), fc='b', ec='k') plt.show()
matplotlibをwxPythonで扱う
matplotlibで描いたグラフをwxPythonのパネル上に表示できると、matplotlibの機能を直接利用できるアプリケーションを作成することができます。次のコードは、3次元のグラフをパネル上にプロットさせて表示させた例です。
import matplotlib matplotlib.interactive( True ) matplotlib.use( 'WXAgg' ) import wx class myWxPlot(wx.Panel): def __init__( self, parent): from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg from matplotlib.figure import Figure self.parent = parent wx.Panel.__init__( self, parent) #matplotlib figure self.figure = Figure( None ) self.figure.set_facecolor( (0.7,0.7,1.) ) self.subplot = self.figure.add_subplot( 111 ) #canvas self.canvas = FigureCanvasWxAgg( self, -1, self.figure ) self.canvas.SetBackgroundColour( wx.Color( 100,255,255 ) ) self._SetSize() self.draw() def _SetSize( self ): size = tuple( self.parent.GetClientSize() ) self.SetSize( size ) self.canvas.SetSize( size ) self.figure.set_size_inches( float( size[0] )/self.figure.get_dpi(), float( size[1] )/self.figure.get_dpi() ) def draw(self): from mpl_toolkits.mplot3d import Axes3D import numpy as np x = np.arange(-3, 3, 0.25) y = np.arange(-3, 3, 0.25) X, Y = np.meshgrid(x, y) Z = np.sin(X)+ np.cos(Y) ax = Axes3D(self.figure) ax.plot_wireframe(X,Y,Z) app = wx.App() frame = wx.Frame( None, size=(500,500) ) panel = myWxPlot( frame ) frame.Show() app.MainLoop()
matplotlibがwxPythonを使って描画するように設定するため、下のように 'WXAgg' を指定します。
import matplotlib matplotlib.interactive( True ) matplotlib.use( 'WXAgg' )
myWxPlotクラスにmatplotlib.figureとsubplot,canvas(matplotlibが表示するためのwxPython用キャンバス)をメンバ変数として持たせます。
キャンバスを扱うために、初期化子内で次のモジュールをインポートします。
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
また、グラフを描画する図であるmatplotlib.figureを扱うのでこのモジュールも同時にインポートします。
from matplotlib.figure import Figure
2次元の図を描く場合は、figure上にsubplotを作成してそこに描画することになるので、subplotを一つメンバとして保持させておきます。
matplotlib.figureに背景色を付けるにはset_facecolorでfloatのタプルによって色を指定します。一方canvasの方はint型タプル(0〜255)で色を指定するので注意が必要です。
#matplotlib figure self.figure = Figure( None ) self.figure.set_facecolor( (0.7,0.7,1.) ) self.subplot = self.figure.add_subplot( 111 ) #canvas self.canvas = FigureCanvasWxAgg( self, -1, self.figure ) self.canvas.SetBackgroundColour( wx.Color( 100,255,255 ) )
_SetSizeでfigureとcanvas、パネル自身のサイズを設定しており、drawメソッドで描画の処理を行っています。
2次元のグラフを描画するコードが次の例です。subplotにグラフをplotしています。
def draw(self): import numpy as np theta = np.arange(0,200, 0.1) x = 2*np.cos(theta/7) y = 3*np.sin(theta/3) self.subplot.plot(x,y, '-r') self.subplot.set_title("Sample", fontsize = 12) self.subplot.set_xlabel("x") self.subplot.set_ylabel("y") self.subplot.set_xlim([-4, 4]) self.subplot.set_ylim([-4, 4])
また下の例では、mpl_toolkits.mplot3dを利用してfigureに3次元のグラフをplotしています。
def draw(self): from mpl_toolkits.mplot3d import Axes3D import numpy as np x = np.arange(-3, 3, 0.25) y = np.arange(-3, 3, 0.25) X, Y = np.meshgrid(x, y) Z = np.sin(X)+ np.cos(Y) ax = Axes3D(self.figure) ax.plot_wireframe(X,Y,Z)
可変個数の引数について
pythonでは、*argsという書式を使うと関数へ可変個数の引数を渡すことができます。
def function(arg1, arg2, *args): print "arg1:", arg1 print "arg2:", arg2 for arg in args: print "arg:", arg function(0, 1, 2 , "aaa", "bbb")
arg1: 0
arg2: 1
arg: 2
arg: aaa
arg: bbb
キーワード引数
関数にキーワード = 値という書式の引数を渡すことも可能です。
def eat(price, food='potato', mode='quickly'): print "price:",price,"yen" print "food:",food print "mode:",mode eat(10000, food='tofu', mode='deliciously')
price: 10000 yen
food: tofu
mode: deliciously
可変個のキーワード引数を関数に渡すには、**keyworgsという書式を利用します。
def function(arg1, **keywords): print "arg1:", arg1 for key in keywords: print "keywords:", key, keywords[key] function(arg1=1, arg2="aaa", arg3=9)
arg1: 1
keywords: arg2 aaa
keywords: arg3 9
matplotlibで3Dグラフを描画する
準備
データ処理用にnumpy、プロット用にpyplot、3次元なのでmpl_toolkits.mplot3dをインポートします。
from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np
描画するデータの作成
3次元で描画するにはメッシュ(2次元の網目)を作成するために2次元の配列を用意する必要があります。
まずarangeメソッドでx,yそれぞれを1次元領域で分割します。
x = np.arange(-3, 3, 0.25) y = np.arange(-3, 3, 0.25)
2次元メッシュを作成するにはmeshgridメソッドを利用します。この関数の戻り値はX,Yに対応する行列で、Xは行にxの配列を、Yは列にyの配列を入れたものになっています。
X, Y = np.meshgrid(x, y) print "x=" , x print "X=" , X print "y=" , y print "Y=" , Y
このXYを直接利用してzを計算します。計算結果も2次元配列になります。
x= [-3. -2. -1. 0. 1. 2.]
X= [ [-3. -2. -1. 0. 1. 2.]
[-3. -2. -1. 0. 1. 2.]
[-3. -2. -1. 0. 1. 2.]
[-3. -2. -1. 0. 1. 2.]
[-3. -2. -1. 0. 1. 2.] ]
y= [-1. 0. 1. 2. 3.]
Y= [ [-1. -1. -1. -1. -1. -1.]
[ 0. 0. 0. 0. 0. 0.]
[ 1. 1. 1. 1. 1. 1.]
[ 2. 2. 2. 2. 2. 2.]
[ 3. 3. 3. 3. 3. 3.] ]
x = np.arange(-3, 3, 0.25) y = np.arange(-3, 3, 0.25) X, Y = np.meshgrid(x, y) Z = np.sin(X)+ np.cos(Y)
Z= [[ 0.3991823 -0.36899512 -0.30116868 0.54030231 1.38177329 1.44959973]
[ 0.85887999 0.09070257 0.15852902 1. 1.84147098 1.90929743]
[ 0.3991823 -0.36899512 -0.30116868 0.54030231 1.38177329 1.44959973]
[-0.55726684 -1.32544426 -1.25761782 -0.41614684 0.42532415 0.49315059]
[-1.1311125 -1.89928992 -1.83146348 -0.9899925 -0.14852151 -0.08069507]]
グラフの作成
figureメソッドでまず2次元の図を生成します。そのあとAxes3D関数で3次元版に変換します。
あとは、予め計算させておいた3次元の点列X,Y,Zをplotなどの3次元プロット関数に渡せばOKです。
fig = plt.figure() ax = Axes3D(fig) ax.plot_wireframe(X,Y,Z)
ここまでの処理をまとめると下のようになります。
from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np x = np.arange(-3, 3, 0.25) y = np.arange(-3, 3, 0.25) X, Y = np.meshgrid(x, y) Z = np.sin(X)+ np.cos(Y) fig = plt.figure() ax = Axes3D(fig) ax.plot_wireframe(X,Y,Z) #<---ここでplot plt.show()
ワイヤーフレーム
ax.plot_wireframe(X,Y,Z)
3次元プロット
plot3Dは単に与えられた1次元配列を3次元プロットする関数です。X,Y,Zは2次元配列なので、numpy.ravel関数で2次元配列を1次元配列に変換してから引数として渡します。図を描くと全て直線でつながっていることが分かります。
ax.plot3D(np.ravel(X),np.ravel(Y),np.ravel(Z))
matplotlibを使う
matplotlibはpythonでグラフを描くためのライブラリです。numpyなどと組み合わせると簡易matlabのような環境を整えることができます。
インストール
公式サイト→http://matplotlib.sourceforge.net/index.html
matplotlib 0.99.1 is available for downloadのところからダウンロードできます。Windows用の簡易インストーラmatplotlib-0.99.1.win32-py2.6.exeをダウンロードします。インストールはこれで簡単にできます。
グラフを描く
plotコマンドでプロットする点のxy座標を定めます。下の例では、x=0,1,2,y=2,3,4のグラフを、x軸0-5,y軸0-8の範囲で描画します。grid()メソッドでグリッドを表示することができます。
import matplotlib.pyplot as plt plt.plot([0,1,2][2,3,4]) plt.axis([0,5,0,8]) plt.grid() plt.title('sample') plt.xlabel('x') plt.ylabel('y') plt.show()
Arrayによる入力
numpyをインポートし、arrayを生成してプロットすることもできます。
from matplotlib.pyplot import* from numpy import * x = arange(0., 7., 0.1) #form 0.0 to 7.0, interval = 0.1 plot(x,cos(x)) show()
プロットのデザイン
点の形を指定するには、'--','^','s'などを引数に指定します。
import matplotlib.pyplot as plt import numpy t = numpy.arange(0., 5., 1.) plt.plot(t, t/3, #line t, t/2,'--' #dotted line ,t, t*1, '^' #triangle ,t, t*1.5, 'v' #triangle , t, t*2, '<' #triangle , t, t*2.5, '>'#triangle ,t, t*3, 's' #square , t, t*3.5, 'd'#square(dice) , t, t*4, 'p' #pentagon , t, t*5, 'h' #hexagon , t, t*6, 'o' #circle , t, t*7, '+' #cross , t, t*8, '*' #star , t, t*9, 'x' #cross , t, t*10, '.' #big dot , t, t*11, ',' #small dot ) plt.show()
色を設定するには、'r','g','b'などの接頭辞を付けます。
import matplotlib.pyplot as plt import numpy t = numpy.arange(0., 5., 1.) plt.plot(t, t*2, 'r--' #red line ,t, t*3,'g--' #green ,t, t*4, 'b--' #blue ,t, t*5, 'y--' #yellow ,t, t*6, 'c--' #cyan ,t, t*7, 'm--' #magenta ,t, t*8, 'w--' #white ,t, t*9, 'k--' #black ) plt.show()
線のカスタマイズ
plotメソッドの引数に直接指定すると下のようになります。
plt.plot(t, t*2,color = '#cccfff', linewidth=3)
plotが返すlineインスタンスのsetupメソッドにより指定する方法もあります。
import matplotlib.pyplot as plt import numpy t = numpy.arange(0., 5., 1.) plt.grid() #lines = plt.plot(t, t*2,color = '#cccfff', linewidth=3) plt.setp(lines, color='#cccfff', linewidth=2.0) plt.setp(lines, 'color', 'r', 'linewidth', 3.0) plt.show()
複数のグラフを表示する
別のウインドウで複数のグラフを表示するには、figure(番号)と記述します。同じfigure内で複数のグラフを描きたい場合は、subplotメソッドを使います。描画領域の行数,描画領域の列数,グラフ番号を3ケタの数にして引数にします。例えば2*2の領域のうち3つ目の領域に描くなら、plt.subplot(223)で現在のグラフの位置を指定してplotを呼び出すとよいです。
import numpy as np import matplotlib.pyplot as plt x1 = np.arange(0.0, 2*np.pi, 0.1) x2 = np.arange(0.0, 2*np.pi, 0.1) plt.figure(1) plt.subplot(221) plt.plot(x1, np.sin(x1), 'r--', x2, np.sin(x2), 'k') plt.subplot(224) plt.plot(x2, np.sin(2*np.pi*x2), 'r--') plt.figure(2) plt.plot(x1, np.cos(x1), 'r--') plt.show()