Python tkinter / リアルタイム2値化アプリを作ってみた

画像処理をする際に、2値化がうまくできていないと好ましい結果になりません。このため、2値化のスレッショルドの値を変更して、画像を確認して、ちょっと違うなと思ったら、また値を変えて画像を確認して、、、というのを繰り返し行うのが非効率だと思っていたのです。

先日作成した「Python OpenCV / 2値化トラックバー 大津の方法との比較」と若干かぶるのですが、今回はPythonのGUI作成ライブラリ「tkinter」を使用して2値化GUIアプリを作成してみました。


いつものウインドウを使用しています。

左側のフレームにある「ファイル選択」を押すと、tkinterのファイルダイアログが立ち上がるので、そこから任意の画像ファイルを選択します。

画像はグレースケールで読み込まれ、右側に表示されます。


下部のスライダーが2値化のスレッショルドです。動かすとリアルタイムで2値化処理が実施されます。80くらいなら全体的に白くなってます。


160くらいまで上げてみると、黒くなりすぎ。


117、これくらいがちょうどよさそうですね。


サイズは、デフォルトでは600にリサイズされたものが表示されます。サイズが合わない場合は、左側の数値を変更すると画像の大きさも変更されます。サイズを200に変更すると画像が小さくなりました。

以下がサンプルプログラムとなります。(Pythonは学習中のため無駄な記述などがある場合があることご了承ください)

サンプルプログラム

#ライブラリのインポート
import tkinter as tk
import tkinter.filedialog
import cv2
from PIL import Image, ImageTk

#フォーマット変換の関数
def format(image_bgr):
    image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
    image_pil = Image.fromarray(image_rgb)
    image_tk  = ImageTk.PhotoImage(image_pil)
    return image_tk

#リサイズ関数
def resize(img):
    size = int(en.get())
    h, w = img.shape[:2]
    cvh = size*h/w
    image_bgr = cv2.resize(img, (size,int(cvh)))
    return image_bgr

#画像選択、表示する関数
def getfile():
    global image_tk
    global img
    global image_bgr
    f_path = tk.filedialog.askopenfilename(title="ファイル選択", initialdir="ディレクトリを入力", filetypes=[("Image file", ".png .jpg .jpeg")])
    str_file_path = str(f_path)
    #OpenCVで画像を読み込む
    img = cv2.imread(str_file_path,0)
    image_bgr = resize(img)
    image_tk = format(image_bgr)
    canvas.create_image(0, 0, image=image_tk, anchor=tk.NW)

#2値化関数    
def scale(event=None):
    global image_tk
    global image_th
    th  = val1.get()
    ret, image_th = cv2.threshold(img, th, 255, cv2.THRESH_BINARY)
    image_bgr = resize(image_th)
    image_tk = format(image_bgr)
    canvas.create_image(0, 0, image=image_tk, anchor=tk.NW)

#オリジナル画像表示
def org():
    global image_tk
    image_bgr = resize(img)
    image_tk = format(image_bgr)
    canvas.create_image(0, 0, image=image_tk, anchor=tk.NW)

#画像保存    
def save():
    cv2.imwrite("image_th.jpg", image_th)

#ウインドウの作成
root = tk.Tk()
#ウインドウのタイトル
root.title("2値化アプリ")
#ウインドウサイズと位置指定 幅,高さ,x座標,y座標 
root.geometry("800x600+50+50")

#フレームの作成
frame = tk.Frame(root, width=780, height=570, padx=10, pady=10, bg="#D9D9D9")
frame.place(x=10, y=10)

frame_menu = tk.Frame(frame, relief=tk.FLAT, bg="#E6E6E6", bd=2)
frame_menu.place(x=10, y=10, width=150, height=450)

frame_img = tk.Frame(frame, relief=tk.FLAT, bg="#E6E6E6", bd=2)
frame_img.place(x=170, y=10, width=580, height=450)

frame_scale = tk.Frame(frame, relief=tk.FLAT, bg="#E6E6E6", bd=2)
frame_scale.place(x=10, y=480, width=740, height=60)

#テキストボックスの作成
en = tk.Entry(frame_menu)
en.insert(0, int(400))
en.place(x=10, y=80, width = 80)

#ボタン作成
button = tk.Button(frame_menu, text="ファイル選択", command=getfile)
button.place(x=10,y=10)

button_org = tk.Button(frame_menu, text="オリジナル", command=org)
button_org.place(x=10, y=120)

button_save = tk.Button(frame_menu, text="保存", command=save)
button_save.place(x=10, y=160)

#Scaleの値格納用変数
val1 = tk.IntVar()
val1.set(0)

#Labelの生成
l = tk.Label(frame_menu,text="サイズ", relief="flat")
l.place(x=10, y=50)

#スケールの作成
sc = tk.Scale(frame_scale, variable=val1, orient='horizontal',length=720, from_=0, to=255, resolution=0.1, command=scale)
sc.place(x=10, y=7)

#キャンバス作成・配置
canvas = tk.Canvas(frame_img, width=550, height=420)
canvas.place(x=10, y=10)

#イベントループ
root.mainloop()
「initialdir」にはディレクトリを入力してください。
Python tkinter / リアルタイムエッジ検出アプリを作ってみた Canny法
先日作成した「2値化GUIアプリ」のCanny法エッジ検出Verです。PythonのGUI作成ライブラリ「tkinter」を使用して、リアルタイムでエッジ検出ができるGUIアプリを作成してみました。 今回もいつものフレームを使用し...
タイトルとURLをコピーしました