"""
画像を表示するためのシンプルなTkinterアプリケーション
Tkinter、Pillow、OpenCV、Matplotlibを使用して画像ファイルを開き、表示するビューアです。
コマンドライン引数で初期画像と表示サイズを指定できます。
:doc:`image_view_usage`
"""
import sys
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
import cv2
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
infile = None
width = 800
height = 800
if __name__ == "__main__":
nargv = len(sys.argv)
if nargv >= 2: infile = sys.argv[1]
if nargv >= 3: width = int(sys.argv[2])
if nargv >= 4: height = int(sys.argv[3])
[ドキュメント]
class ImageViewer:
"""
画像表示機能を備えたTkinterアプリケーションクラス
画像ファイルを開き、指定されたサイズで表示するUIを提供します。
PillowまたはOpenCVで画像を読み込み、Tkinter CanvasまたはMatplotlibで表示します。
"""
def __init__(self, root, file_path = None, width = 800, height = 800):
"""
ImageViewer クラスのコンストラクタ
Tkinterウィンドウを初期化し、画像を開くボタン、幅/高さ入力フィールド、
および画像表示領域を設定します。指定されたファイルパスがあれば、起動時に画像を表示します。
:param root: tk.Tk Tkinterのルートウィンドウオブジェクト。
:param file_path: str | None 初期表示する画像のパス。省略可能。
:param width: int 画像の初期表示幅。
:param height: int 画像の初期表示高さ。
"""
self.root = root
self.file_path = infile
self.root.title("Image Viewer")
self.root_frame = tk.Frame(root)
frame = self.root_frame
frame.pack(expand = True, fill = tk.BOTH)
self.btn_open = tk.Button(frame, text = "Open Image", command = self.open_image)
self.btn_open.pack()
# 幅と高さの入力フィールド
var_width = tk.IntVar(value = width)
var_height = tk.IntVar(value = height)
entry_frame = tk.Frame(frame)
entry_frame.pack(expand = True, fill = tk.BOTH)
self.label_width = tk.Label(entry_frame, text = "Width:")
self.label_width.pack(side = tk.LEFT)
self.entry_width = tk.Entry(entry_frame, textvariable = var_width)
self.entry_width.pack(side = tk.LEFT)
self.label_height = tk.Label(entry_frame, text="Height:")
self.label_height.pack(side = tk.LEFT)
self.entry_height = tk.Entry(entry_frame, textvariable = var_height)
self.entry_height.pack(side = tk.LEFT)
if file_path:
img = self.read_image(file_path)
self.display_image(img)
[ドキュメント]
def open_image(self):
"""
ファイルダイアログを開き、選択された画像を表示する
ファイル選択ダイアログを表示し、ユーザーが画像ファイルを選択すると、
その画像を読み込んでビューアに表示します。
"""
file_path = filedialog.askopenfilename()
if file_path:
img = self.read_image(file_path)
self.display_image(img)
[ドキュメント]
def read_image(self, file_path):
"""
指定されたパスから画像を読み込む
現在はPillow (PIL) を使用して画像を読み込みます。
コメントアウトされた行を解除することでOpenCVでの読み込みに切り替えることも可能です。
:param file_path: str 読み込む画像ファイルのパス。
:returns: PIL.Image.Image 読み込まれた画像データ(Pillow Imageオブジェクト)。
"""
# return self.read_image_cv2(file_path)
return self.read_image_pil(file_path)
[ドキュメント]
def display_image(self, img):
"""
読み込んだ画像を指定された方法で表示する
現在はMatplotlibを使用して画像をGUIに表示します。
コメントアウトされた行を解除することでTkinter Canvasでの表示に切り替えることも可能です。
:param img: PIL.Image.Image 表示する画像データ(Pillow Imageオブジェクト)。
"""
# self.display_image_canvas(img)
self.display_image_mpl(img)
[ドキュメント]
def read_image_cv2(self, file_path):
"""
OpenCVを使って画像を読み込む
指定されたパスの画像をOpenCV (`cv2.imread`) で読み込み、
BGRからRGBに変換後、PillowのImageオブジェクトに変換して返します。
:param file_path: str 読み込む画像ファイルのパス。
:returns: PIL.Image.Image 読み込まれた画像データ(Pillow Imageオブジェクト)。
"""
img = cv2.imread(file_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = Image.fromarray(img)
return img
[ドキュメント]
def read_image_pil(self, file_path):
"""
Pillow (PIL) を使って画像を読み込む
指定されたパスの画像をPillow (`Image.open`) で読み込み、
PillowのImageオブジェクトとして返します。
:param file_path: str 読み込む画像ファイルのパス。
:returns: PIL.Image.Image 読み込まれた画像データ(Pillow Imageオブジェクト)。
"""
img = Image.open(file_path)
return img
[ドキュメント]
def display_image_canvas(self, img):
"""
TkinterのCanvasウィジェットに画像を表示する
入力フィールドから取得した幅と高さに合わせて画像をリサイズし、
TkinterのCanvasウィジェットに表示します。
:param img: PIL.Image.Image 表示する画像データ(Pillow Imageオブジェクト)。
"""
width = int(self.entry_width.get())
height = int(self.entry_height.get())
img_resized = img.resize((width, height))
self.img_tk = ImageTk.PhotoImage(img_resized)
self.canvas = tk.Canvas(self.root_frame)
self.canvas.pack()
self.canvas.config(width = width, height = height)
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.img_tk)
[ドキュメント]
def display_image_mpl(self, img):
"""
Matplotlibを使って画像をTkinterウィンドウに表示する
入力フィールドから取得した幅と高さに合わせて画像をリサイズし、
MatplotlibのFigureとAxesを作成して画像を表示します。
このFigureは `FigureCanvasTkAgg` を使ってTkinterウィジェットとして埋め込まれます。
:param img: PIL.Image.Image 表示する画像データ(Pillow Imageオブジェクト)。
"""
width = int(self.entry_width.get())
height = int(self.entry_height.get())
img_resized = img.resize((width, height))
fig = Figure(figsize = (width / 100, height / 100))
ax = fig.add_subplot(111)
ax.imshow(img_resized)
ax.axis('off')
self.canvas = FigureCanvasTkAgg(fig, master = self.root)
self.canvas.draw()
self.canvas.get_tk_widget().pack()
if __name__ == "__main__":
root = tk.Tk()
app = ImageViewer(root, infile, width, height)
root.mainloop()