サブウィンドウに画像を表示させる

Posted at 2023 年 06 月 25 日

前回の記事で画像の判定結果をサブウィンドウで表示させましたが、追加で結果画面に撮影画像を入れてみました。

環境は下記になります。

Hardware:Raspberry pi4B
OS:Raspbian 10/buster
Python:3.7.3

PythonではCanvasを作成・設定してCanvas上に画像を表示するという手順になります。

画像処理ライブラリPillow(PIL)を利用します。
from PIL import Image, ImageTk

まずキャンバス上で表示させる画像を読み込ませます。
lastimage = ImageTk.PhotoImage(img)

次にキャンバスを作成し表示させます。

img_width, img_height = img.size #画像サイズ(縦横)を取得
canvas = tk.Canvas(subwindow, bg="#f0f8ff", width=img_width, height=img_height)
canvas.pack(padx=30, pady=30)
canvas.create_image(0 , 0 ,anchor = tk.NW,image=lastimage)


全体のソースコードは以下になります。

import tkinter as tk
import os
import time
import datetime
import picamera
import cv2
import glob
from tkinter import *
from PIL import Image, ImageTk

#ウィンドウの作成
base = tk.Tk()
base.geometry("500x300")
base.title("画像撮影")
camera = picamera.PiCamera()

# 保存先path
image_path = "./images/"

def clk():  #---クリックイベント画像撮影
     
    #現在時間を取得
    now = datetime.datetime.now()
     
    #画像撮影
    camera.resolution = (1024, 768)
    camera.capture(now.strftime(image_path + '%Y%m%d_%H%M%S') + 'cap.jpg')
     
    #プレビュー
    camera.start_preview()
    time.sleep(5)
    camera.stop_preview()
     
def com():  #---クリックイベント比較
        
    # 最新ファイルの取得
    AllList = glob.glob('./images/*')
    latest_file = max(AllList, key=os.path.getctime)
     
    # 結果で表示するために画像を読み込む
    img = Image.open(latest_file)
    img_width, img_height = img.size #画像サイズ(縦横)を取得
    lastimage = ImageTk.PhotoImage(img) #サブウィンドウ用画像の読み込み
    print(latest_file)
       
    # 撮影した画像を読み込む
    img1 = cv2.imread(latest_file)
    color = ('b','g','r')
       
    # ヒストグラム計算
    for i , col in enumerate(color):
      histr1 = cv2.calcHist([img1],[i],None,[256],[0,256])
         
    # 比較元画像を読み込む
    img2 = cv2.imread('Originalcap.jpg')
    color = ('b','g','r')
       
    # ヒストグラム計算
    for i , col in enumerate(color):
      histr2 = cv2.calcHist([img2],[i],None,[256],[0,256])
       
    # ヒストグラムの比較。
    comphist = cv2.compareHist(histr1, histr2, cv2.HISTCMP_CORREL) 
    print(comphist)
         
    # 判定
    num = 0.8
    if num < comphist:
       
      # サブウィンドウ
      subwindow = tk.Toplevel()
      subwindow.title("成否判定") # ウィンドウタイトル
      subwindow.geometry("1200x800")  # ウィンドウサイズ(幅x高さ)     
       
      # ラベルの作成
      labelt = tk.Label(subwindow,text='○',font=("MSゴシック", "20", "bold"),foreground='#000fff000')
      labelt.pack(padx=30, pady=10)
      labeltc = tk.Label(subwindow,text='画像の一致率は' + str(round(comphist * 100,2)) + '%です')
      labeltc.pack(padx=30, pady=20)
       
      # キャンバス作成
      canvas = tk.Canvas(subwindow, bg="#f0f8ff", width=img_width, height=img_height)
      canvas.pack(padx=30, pady=30)
      canvas.create_image(0 , 0 ,anchor = tk.NW,image=lastimage)
       
      # モーダルにする設定
      subwindow.grab_set()    # モーダルにする
      subwindow.focus_set()    # フォーカスを新しいウィンドウをへ移す
      base.wait_window(subwindow)

    else:
       
      # サブウィンドウ
      subwindow = tk.Toplevel()
      subwindow.title("成否判定") # ウィンドウタイトル
      subwindow.geometry("1200x800")  # ウィンドウサイズ(幅x高さ)
       
      # ラベル設定
      labelf = tk.Label(subwindow,text='☓',font=("MSゴシック", "20", "bold"),foreground='#ff0000')
      labelf.pack(padx=30, pady=10)
      labeltc = tk.Label(subwindow,text='画像の一致率は' + str(round(comphist * 100,2)) + '%です')
      labeltc.pack(padx=30, pady=20)
       
      # キャンバス作成
      canvas = tk.Canvas(subwindow, bg="#f0f8ff", width=img_width, height=img_height)
      canvas.pack(padx=30, pady=30)
      canvas.create_image(0 , 0 ,anchor = tk.NW,image=lastimage)

      # モーダルにする設定
      subwindow.grab_set()    # モーダルにする
      subwindow.focus_set()    # フォーカスを新しいウィンドウをへ移す
      base.wait_window(subwindow)

#ウィジェットの作成
label = tk.Label(text = "ボタンを押して撮影する")
button1 = tk.Button(base, text='開始', width=20, command=clk)
button2 = tk.Button(base, text='比較', width=20, command=com)

# 配置
label.pack()
button1.pack(fill = 'x',padx=20, side = 'left')
button2.pack(fill = 'x',padx=20, side = 'left')

base.mainloop()


以下のように表示されます。


今回は撮影した画像のフォーカスがあっていないのと、ウィンドウサイズの関係で見切れているのでリサイズするとか対応が必要かなと思います。