そのPython言語の、Pillowという画像ライブラリを使ったスクリプトです。
Pythonをインストールして、Pillowのライブラリをpipでインストールしておく必要があります。
記事を書いている時点のPythonは3.8です。
前回のトイカメラ風に加工するスクリプトを、TkinterというGUIライブラリを使って、
画面で操作できるようにしました。
GUI化することで、効果を確認しながらパラメータを決められるのが良いですが、
何枚も同じ加工を連続して行うのは向きません。
以下にスクリプトのコードを書きます。
"""
トイカメラ風に周辺減光させる
tkinterを使ったGUI版
Usage : コマンドラインから以下のコマンドで起動
python toycamera_gui.py
"""
import os
from PIL import Image, ImageDraw, ImageFilter, ImageTk
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog, messagebox
class FormClass:
"""
Toycamera風に加工する画面のフォームを作成するクラス
"""
def __init__(self, root):
# インスタンス変数に初期値設定
self.root = root # Windowオブジェクト
self.readimg = None # 入力画像
self.dst_img = None # 加工結果画像
rowno = 0 # 表示位置(行番号)
# ラベルを作成
tk.Label(root, text='入力ファイルPATH'
).grid(column=0, row=rowno)
# 入力ファイル名
self.src_path = tk.StringVar()
# テキストボックスを作成
tb_widget = tk.Entry(root,
width=120,
textvariable=self.src_path)
tb_widget.grid(column=1, row=rowno)
# 入力ファイル選択ボタンを作成
btn_widget = tk.Button(root,
text='入力ファイル選択',
command=self.select_file)
btn_widget.grid(column=2, row=rowno)
rowno += 1
# 塗り残す範囲の比率 スケールの作成
tk.Label(root, text='塗り残す範囲の比率(%)'
).grid(column=0, row=rowno)
self.rate = tk.DoubleVar()
rate_sc = tk.Scale(
root,
variable=self.rate,
orient=tk.HORIZONTAL,
from_=0.0,
to=100,
command=self.draw_effect)
rate_sc.grid(column=1,
row=rowno,
sticky=(tk.N, tk.E, tk.S, tk.W))
self.rate.set(40)
rowno += 1
# ぼかし半径 スケールの作成
tk.Label(root, text='ぼかし半径'
).grid(column=0, row=rowno)
self.blur_radius = tk.IntVar()
blur_sc = tk.Scale(
root,
variable=self.blur_radius,
orient=tk.HORIZONTAL,
from_=0,
to=40.0,
command=self.draw_effect)
blur_sc.grid(column=1,
row=rowno,
sticky=(tk.N, tk.E, tk.S, tk.W))
self.blur_radius.set(20)
rowno += 1
# 効果の強さ スケールの作成
tk.Label(root, text='効果の強さ'
).grid(column=0, row=rowno)
self.strength = tk.IntVar()
strength_sc = tk.Scale(
root,
variable=self.strength,
orient=tk.HORIZONTAL,
from_=0,
to=255,
command=self.draw_effect)
strength_sc.grid(column=1,
row=rowno,
sticky=(tk.N, tk.E, tk.S, tk.W))
self.strength.set(80)
rowno += 1
# 塗りつぶし色 コンボボックスの作成
tk.Label(root, text='塗りつぶし色'
).grid(column=0, row=rowno)
self.select_color = tk.StringVar()
color_combo = ttk.Combobox(
root,
textvariable=self.select_color)
color_combo.grid(column=1,
row=rowno,
sticky=(tk.N, tk.W))
color_combo['values'] = ('白', '黒')
color_combo.current(1)
color_combo.bind("<>", self.draw_effect)
rowno += 1
# ファイル保存ボタンを作成
savebtn_widget = tk.Button(root,
text='ファイル保存',
command=self.show_save_dialog)
savebtn_widget.grid(column=0, row=rowno,
sticky=(tk.N))
self.CANVAS_WIDTH = 800
self.CANVAS_HEIGHT = 600
# 画像を表示するためのキャンバスの作成
self.canvas = tk.Canvas(self.root,
width=self.CANVAS_WIDTH,
height=self.CANVAS_HEIGHT)
self.canvas.grid(column=1, row=rowno, columnspan=2)
# 入力ファイル選択ボタン押下イベント
def select_file(self):
# ファイル選択ダイアログを表示
ftypes = [("All Files", ".*"),
("JPEG Image Files", ".jpg .jpeg"),
("PNG Image Files", ".png")]
filepath = self.src_path.get()
if len(filepath) == 0:
idir = os.path.abspath(os.path.dirname(__file__))
else:
idir = os.path.dirname(filepath)
filepath = filedialog.askopenfilename(filetypes = ftypes,
initialdir = idir)
if len(filepath) == 0 :
return
self.src_path.set(filepath)
# 画像を読み取り
self.readimg = Image.open(filepath)
# 加工した画像を表示
self.draw_effect()
# 加工した画像を表示する
def draw_effect(self,val=0):
if self.readimg is None :
return
# 塗りつぶし色
fill_color = None
if self.select_color.get() == '白' :
fill_color = (255, 255, 255)
else :
# 黒く塗りつぶす場合
fill_color = (0, 0, 0)
# 円を描画する開始位置、終了位置を計算する
w,h = self.readimg.size
radius = max(w,h) * self.rate.get() / 100.0
w_start = (w / 2) - radius
w_end = (w / 2) + radius
h_start = (h / 2) - radius
h_end = (h / 2) + radius
# マスク画像を描画する
mask = Image.new("L", (w, h), 255-self.strength.get())
draw = ImageDraw.Draw(mask)
draw.ellipse((w_start, h_start, w_end, h_end), fill=255)
mask_blur = mask.filter(
ImageFilter.GaussianBlur(
self.blur_radius.get()))
# 塗りつぶし画像を作成する
plane = Image.new("RGB", (w, h), fill_color)
# 元の画像と、塗りつぶし画像を合成する
self.dst_img = Image.composite(self.readimg, plane, mask_blur)
# 画像の表示倍率を計算する
rate = min(1.0,
self.CANVAS_WIDTH / self.readimg.width,
self.CANVAS_HEIGHT / self.readimg.height)
# 表示用に画像を縮小する
new_w = int(self.readimg.width * rate)
new_h = int(self.readimg.height * rate)
small_resized = self.dst_img.resize((new_w, new_h))
# キャンバスに画像を表示する。
self.im = ImageTk.PhotoImage(image=small_resized)
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.im)
# ファイル保存ボタンイベント
def show_save_dialog(self):
if self.dst_img is not None :
ftypes = [("All Files", ".*"),
("JPEG Image Files", ".jpg .jpeg"),
("PNG Image Files", ".png")]
ini_fname = os.path.basename(self.src_path.get())
filename = filedialog.asksaveasfilename(filetypes=ftypes,
initialfile=ini_fname)
if filename:
# 保存先ファイルが指定されたら、加工した画像を保存
self.dst_img.save(filename, quality=100)
else :
tk.messagebox.showerror(title="エラー",
message="入力ファイルを指定してください")
# windowを描画
window = tk.Tk()
# windowサイズを変更
window.geometry("1000x800")
# windowタイトルを設定
window.title("Toycamera effect")
# フォームを作成、表示
FormClass(window)
# 画面を操作されるのを待つ
window.mainloop()
上のスクリプトをUTF-8のエンコーディングで、toycamera_gui.py というファイルに保存します。
Windowsだとコマンドプロンプト等を開いて、スクリプトを保存したフォルダにcdコマンドで移動して、
python toycamera_gui.py
で実行します。 実行すると、
このような画面を表示します。
入力ファイル選択ボタンで、ファイル選択ダイアログを開きます。
そこでファイルを選択すると、
このように画像のプレビューを表示します。
「塗り残す範囲の比率」を大きくすると、塗りつぶしする面積が狭くなります。
「ぼかし半径」を大きくすると、塗りつぶしの境界がぼけます。
「効果の強さ」を大きくすると、塗りつぶしがはっきりします。
「塗りつぶし色」を白にすると、周辺を白く塗りつぶしします。
「ファイル保存ボタン」をクリックすると、保存先選択ダイアログを開きます。
塗りつぶしを白に変更した例
0 件のコメント:
コメントを投稿