新着情報
1-1-(a) GUI画像表示プログラムの補足説明
(1a) GUI画像表示プログラム(showGUIimage.py)の補足説明
ここで showGUIimage.py の各部分について補足説明を行う。
① まず、Pythonプログラムに必要な各種のライブラリ・モジュールのimport宣言を行う。
tkinter のライブラリ・モジュールを全てimportする。
次に、tkinterから対話的に対象とする画像ファイルを選択するために必要なfiledialogと
ブログラム終了の時に確認するメッセージを提示する時に必要なmessageboxを明示的にimportする。
Python3用の画像ライブラリPillowからImageとImageTkをimportする。
しかし、この場合もPilow Image Libraryの頭文字はPILなので、Python2の時と同様に
from PIL import Image, ImageTk と記述することに注意する。
今後において、GUI画像処理システム開発を想定しているので、画像処理ライブラリ・モジュールOpenCV
バージョン3をimportする。
OpenCVのバージョン3をimportするのに、import cv3ではなくて、バージョン2の時と同様にimport cv2 と記述することにも注意する。
必要なライブラリのimport宣言は以下の通りである。
from tkinter import * from tkinter import filedialog, messagebox from PIL import Image, ImageTk import cv2
② 画像を表示する画面枠としてクラスWindowを定義し、その引数にtkinterモジュールのクラスFrame Widgetを取る。即ち、FrameクラスはWindowクラスの上位クラスとなる。
Frame Widgetはtkinterモジュールが提供するGUI部品のLabel WidgetやButton Widgetなど
他のWidgetをまとめて配置可能である。
ここでは、クラスWindowのコンストラクタ定義(初期値化) def __init__ 中で、
上位のクラスFrameを明示的にコンストラクタ定義することにより、
WindowクラスはFrameクラスをすべて継承してることになる。
また、Windowクラスの窓枠全体のタイトルや窓枠の最低サイズ(500,500)画素を定義している。
class Window(Frame):# クラス Window(Frame)の定義 def __init__(self,master=None):# クラス Window()のコン # ストラクタ #フレーム Frame.__init__(self, master)# 上位クラス Frame の # コンストラクタ self.master.title('画像表示') self.master.minsize(500,500)
③ menu_barをクラスWindowに関連付け、親メニューファイル(F)と、’開く’, ‘保存’、’終了’の3通りの
子メニューを想定し、これら子メニューとイベント関数def quit( ), def open( ), def save( )とを関係づける。
#メニューバー self.menu_bar = Menu(self.master) self.master.config(menu=self.menu_bar) self.menu_file = Menu(self.menu_bar,tearoff = 0) self.menu_file.add_command(label='開く', command=self.open, underline=3, accelerator = 'Ctrl-O') self.menu_file.add_command(label='保存', command=self.save, underline=5, accelerator = 'Ctrl-S') self.menu_file.add_command(label='終了', command=self.quit, underline=5, accelerator = 'Ctrl-Q') self.menu_bar.add_cascade(label='ファイル(F)', menu=self.menu_file, underline=5) #終了 def quit(self): if messagebox.askokcancel('Confirm Closing', 'Are you sure you want to close?'): self.master.destroy() #開く def open(self): global filename global size size=300,300 filename = filedialog.askopenfilename() if filename != "": im = Image.open(filename) im.thumbnail(size, Image.ANTIALIAS) if im.mode == '1': # bitmap image self.image = ImageTk.BitmapImage(im) else: # photo image self.image = ImageTk.PhotoImage(im) self.la.config(text='Original Image',image=self.image, width=self.image.width(), height=self.image.height(),compound='top') #保存 def save(self): global filename global filename2 cv2.imwrite('result.jpg',filename2)
④ クラスLabel Widget のインスタンス変数self.la を定義する[行23-24]。クラスWindow枠内の左上から横へ100画素、下へ100画素の場所にLabel Widgetを配置する。Label Widget内に画像表示の領域として(300,300)画素サイズを準備する。画像はまだ選択されていないので、bg=バックグランドカラー(#44aaaa)が貼り付けられた状態である。
self.image1 = PhotoImage() #ラベル1 self.la = Label(self,image=self.image1,bg="#44aaaa",width=300, height=300) self.la.pack(side=LEFT,padx=100, pady=100)
⑤ イベント関数 def open (self)に関して[行43~58]、filename=filedialog.askopenfilename( )によって、ファイル選択のためのダイアログ画面が表示され、表示したい画像ファイル名を対話的に選択可能となる。対象画像ファイルは白黒ビットマップ画像の場合はBitmapImage( )関数によって、また、カラー画像の場合はPhotoImage( )関数によってLabel ,Text, Button, Canvas Widgetに添付可能なImageクラスに変換する必要がある。このImageクラス変数の値はインスタンス変数(self.image)に代入する必要がある。これをしないと、関数から出る時、変数のメモリーが 回収されるため、画像が消えてしまう。これが、文中で self.image1=ImageTk.Bitmap(im)、或いは self.image1=ImageTk.PhotoImage(im) 等としている理由である。
#開く def open(self): global filename global size size=300,300 filename = filedialog.askopenfilename() if filename != "": im = Image.open(filename) im.thumbnail(size, Image.ANTIALIAS)#画像サイズを縮小する print(im.mode) if im.mode == '1': # 白黒bitmap imageの場合 self.image1 = ImageTk.BitmapImage(im) else: # photo image .png,.jpgなどの拡張子の場合 self.image1 = ImageTk.PhotoImage(im) self.la.config(text='Original Image',image=self.image1, width=self.image1.width(), height=self.image1.height(),compound='top')
⑥ 最後の部分[行65~68]についての説明である。プログラムが実行されると、__name__
の値は__main__になるので、if __name__ == ‘__main__’: は成立し、以下の3つの文が実行される。
root = Window( ) により、Windowクラスのインスタンスrootが作られ、root.pack( )により画面上にインスタンスrootが配置される。そして、root.mainloop( )により、次のイベントまで待機が続くことになる。
if __name__ == '__main__': root = Window() root.pack() root.mainloop()
参考文献:
http://www.shido.info/py/tkinter_a1.html