TkinterとPillowで画像変換器を作る
目次
画像変換器を作る
Pythonには標準ライブラリに「Tkinter(キンター)」と呼ばれるGUIライブラリがあります。
Tkinterを使うと標準ライブラリのみでGUIアプリを作ることが可能です。
それから外部ライブラリに「Pillow(ピロウ)」と呼ばれる画像処理ライブラリがあります。
PillowはPythonでは人気のある外部ライブラリで、画像の読み込みや表示、加工などを簡単に行うことが出来ます。
今回はこれら2つのライブラリとPythonを使って簡易的な画像変換器を作ってみました。
ウィンドウの中に画像とボタンを表示して、ボタンをクリックしたら画像にエフェクトが加わるGUIアプリです。
この画像変換器について具体的には↓を見ていきます。
アプリの外観
コード全文
Pillowのインストール
ウィンドウの表示
レイアウトの設定
画像のリセット
ネガポジ反転
グレイスケール変換
アプリの外観
今回作ったアプリの外観を最初に紹介します。
↓のような外観になります。
表示されている画像はオリジナルの画像です。
この画像を右に配置されているボタンで加工する感じです。
動作風景は↓です。
ボタンにはリセットボタン、ネガポジ反転ボタン、モノクロ変換ボタンがあります。
これらのボタンをクリックすると↑のように左に表示されている画像が変化します。
画像は読み込みなどは行えず、1つの画像を決め打ちで表示しています。
この辺を自由に読み込みが出来るようにするには改造が必要ですが、今回は対応しません。
それではまずはPillowのインストールから始めます。
コード全文
↓が今回制作したGUIアプリのコード全文です。
import tkinter as tk from tkinter import ttk from PIL import Image, ImageTk, ImageOps class App(tk.Tk): def __init__(self): super().__init__() self.title('Image convertor') # ウィンドウの左側のエリア self.left_frame = ttk.Frame(self) self.left_frame.pack(side=tk.LEFT, expand=True, fill=tk.BOTH) # 元画像をPillowで開く # 今回はimg/e.pngを開いている self.src_pl_img = Image.open('img/e.png') self.dst_pl_img = self.src_pl_img # ラベルに画像を設定して配置する self.dst_photo_img = ImageTk.PhotoImage(self.src_pl_img) self.img_label = ttk.Label(self.left_frame, image=self.dst_photo_img) self.img_label.pack(expand=True, fill=tk.BOTH) # ウィンドウの右側のエリア self.right_frame = ttk.Frame(self) self.right_frame.pack(side=tk.LEFT, expand=True, fill=tk.BOTH) # リセットボタン self.reset_btn = ttk.Button(self.right_frame, text='Reset', command=self.reset) self.reset_btn.pack(side=tk.TOP) # ネガポジ反転ボタン self.invert_btn = ttk.Button(self.right_frame, text='Invert', command=self.invert) self.invert_btn.pack(side=tk.TOP) # グレイスケール変換ボタン self.gray_btn = ttk.Button(self.right_frame, text='Gray', command=self.gray) self.gray_btn.pack(side=tk.TOP) def reset(self): """ 画像をリセットする """ self.dst_pl_img = self.src_pl_img self.dst_photo_img = ImageTk.PhotoImage(self.src_pl_img) self.img_label.config(image=self.dst_photo_img) def invert(self): """ 画像をネガポジ反転する """ self.dst_pl_img = ImageOps.invert(self.dst_pl_img) self.dst_photo_img = ImageTk.PhotoImage(self.dst_pl_img) self.img_label.config(image=self.dst_photo_img) def gray(self): """ 画像をグレイスケール変換する """ self.dst_pl_img = self.dst_pl_img.convert('L') self.dst_photo_img = ImageTk.PhotoImage(self.dst_pl_img) self.img_label.config(image=self.dst_photo_img) def main(): app = App() app.mainloop() main()
GUIアプリにしては短いコードになっています。
これはTkinterとPillowのおかげです。
Tkinterを使うと↑のように短いコードでGUIアプリを作ることが出来ます。
Pillowによる画像の加工も同様です。
Pillowのインストール
今回、画像処理に使うライブラリであるPillowは外部ライブラリです。
そのためpipなどのパッケージマネージャでこの外部ライブラリをインストールしておく必要があります。
pipでPillowをインストールするには↓のようにコマンドを実行します。
> pip install Pillow
ウィンドウの表示
最初にTkinterでウィンドウを表示します。
タイトルの付いたウィンドウの表示自体は↓のコードで行えます。
import tkinter as tk from tkinter import ttk class App(tk.Tk): def __init__(self): super().__init__() self.title('Image convertor') def main(): app = App() app.mainloop() main()
tkinter
やttk
などの必要モジュールをインポートします。
それからApp
というクラスを作ってtk.Tk
クラスを継承します。
tk.Tk
はTkinterのルートウィンドウになるクラスです。
App
の__init__()
メソッド内では親の__init__()
の呼び出しを行います。
それからtitle()
メソッドを使ってウィンドウのタイトルを設定します。
今回のGUIアプリのタイトルは「Image convertor(画像変換器)」にしておきます。
(^ _ ^) | 英語にするとかっちょいいね |
main()
関数内でApp
クラスをオブジェクトにしてmainloop()
メソッドを呼び出し、ウィンドウを表示します。
main()
関数はコードの下の方で適当に呼んでおきます。
レイアウトの設定
__init__()
メソッド内でレイアウトを設定します。
今回はウィンドウを左のエリアと右のエリアに分けて、左のエリアに画像を表示して、右のエリアに変換ボタンを配置します。
そのため左のエリアと右のエリアを表すフレームを2つつくります。
そしてそれぞれのフレームに画像のラベル、それから変換ボタンを配置します。
def __init__(self): super().__init__() self.title('Image convertor') # ウィンドウの左側のエリア self.left_frame = ttk.Frame(self) self.left_frame.pack(side=tk.LEFT, expand=True, fill=tk.BOTH) # 元画像をPillowで開く # 今回はimg/e.pngを開いている self.src_pl_img = Image.open('img/e.png') self.dst_pl_img = self.src_pl_img # ラベルに画像を設定して配置する self.dst_photo_img = ImageTk.PhotoImage(self.src_pl_img) self.img_label = ttk.Label(self.left_frame, image=self.dst_photo_img) self.img_label.pack(expand=True, fill=tk.BOTH) # ウィンドウの右側のエリア self.right_frame = ttk.Frame(self) self.right_frame.pack(side=tk.LEFT, expand=True, fill=tk.BOTH) # リセットボタン self.reset_btn = ttk.Button(self.right_frame, text='Reset', command=self.reset) self.reset_btn.pack(side=tk.TOP) # ネガポジ反転ボタン self.invert_btn = ttk.Button(self.right_frame, text='Invert', command=self.invert) self.invert_btn.pack(side=tk.TOP) # グレイスケール変換ボタン self.gray_btn = ttk.Button(self.right_frame, text='Gray', command=self.gray) self.gray_btn.pack(side=tk.TOP)
左のエリアを表すフレームをleft_frame
, 右のエリアを表すフレームをright_frame
で作成しておきます。
初期状態でsrc_pl_img
に画像を読み込んでおきます。
画像の読み込みはPillowのImage.open()
で行うことが出来ます。
Image.open()
の引数に画像のパスを指定すると、そのパスの画像を読み込むことが出来ます。
src_pl_img
はリセット処理などに使います。そのため読み込んだ直後の状態で保持しておきます。
src_pl_img
はdst_pl_img
に代入しておきます。
実際の変換処理にはこちらのdst_pl_img
を使います。
読み込んだPillowの画像はImageTk.PhotoImage
でTkinterの画像(dst_photo_img
)に変換しておきます。
その画像をimg_label
に設定します。img_label
の親ウィジェットにはleft_frame
を設定しておきます。
このimg_label
をウィンドウの左側に配置しておきます。
right_frame
にはreset_btn
やinvert_btn
, gray_btn
などのボタンを配置しておきます。
これらのボタンにはそれぞれ「Reset(リセット)」、「Invert(反転)」、「Gray(グレイスケール)」というテキストを設定します。
また、それぞれのボタンにはクリックしたときのイベントとして、reset
, invert
, gray
メソッドを渡しておきます。
ボタンの配置はside=tk.TOP
にして上から順に詰めていきます。こうすることで上から下に並ぶボタンを配置できます。
画像のリセット
画像のリセット処理はreset
メソッドで行います。
これはsrc_pl_img
をdst_pl_img
に代入し、src_pl_img
からImageTk.PhotoImage
を使ってdst_photo_img
を作成します。
そしてdst_photo_img
をラベルに再設定するだけです。
こうすることで加工された画像がリセットされます。
ImageTk
モジュールはインポートしておく必要があります。
このリセット処理のためにsrc_pl_img
は読み込んだ直後の状態で保持しておく必要があります。
これを加工してしまうとこのメソッドで行うリセット処理が機能しなくなるためです。
そのため主な加工にはdst_pl_img
を使います。
def reset(self): """ 画像をリセットする """ self.dst_pl_img = self.src_pl_img self.dst_photo_img = ImageTk.PhotoImage(self.src_pl_img) self.img_label.config(image=self.dst_photo_img)
ネガポジ反転
画像のネガポジを反転する処理はinvert()
メソッドで行います。
ImageOps
モジュールのinvert()
メソッドにPillowのImage
を渡すと、ネガポジを反転することが出来ます。
反転した画像(dst_pl_img
)はImageTk.PhotoImage
でTkinterの画像に変換して、それをimg_label
に設定します。
ImageOps
モジュールはインポートしておく必要があります。
Pillowを使うと↓のようにネガポジの反転処理が1行で書くことが出来ます。
Pillowにはネガポジの反転意外にもさまざまなエフェクトが用意されています。これらのエフェクトを使えばこのGUIアプリの加工ボタンを自由に増やすことが出来るでしょう。
def invert(self): """ 画像をネガポジ反転する """ self.dst_pl_img = ImageOps.invert(self.dst_pl_img) self.dst_photo_img = ImageTk.PhotoImage(self.dst_pl_img) self.img_label.config(image=self.dst_photo_img)
グレイスケール変換
画像のグレイスケールへの変換はgray()
メソッドで行います。
Image
のconvert()
メソッドにL
モードを指定すると画像をグレイスケールに変換することが出来ます。
グレイスケール画像に変換したらImageTk.PhotoImage
でTkinterの画像に変換し、ラベルに設定します。
def gray(self): """ 画像をグレイスケール変換する """ self.dst_pl_img = self.dst_pl_img.convert('L') self.dst_photo_img = ImageTk.PhotoImage(self.dst_pl_img) self.img_label.config(image=self.dst_photo_img)
L
モードは8ビットのモノクロ画像のモードです。
モードについては↓を参照してください。
おわりに
TkinterとPillowを使うと簡単に画像変換器を作ることが出来ました。
画像を保存できるように改造するなど、いろいろ改善案はあるかと思います。
コードのライセンスはMITです。改造などは自由におこなってください。
(^ _ ^) | 画像変換処理はおもしろい |