実現したいこと
main.pyのGUIボタンから別ファイルのcolorMatch.pyを実行したいです。
main.pyから色判断をするプログラムcolorMatch.pyをGUIのボタンで呼び出しています。
colorMatch.pyの構成は
①cv2で画像を取得し、canvasにリアルタイム表示するクラス Application
②取得した画像を画像処理をして結果を出すクラス match
になっています。
colorMatch.pyは単体で実行すると思った通りの動きをしますが、
別ファイルのGUIのボタンで呼び出すと、①のmainloop()が抜けられず、②クラスに行けません。
ですが、main.pyのGUI画面を閉じるとmainloop()を抜けて②が実行されます。
main.pyの画面を閉じないでmainloop()を抜けたいです。
発生している問題・エラーメッセージ
エラーメッセージは出ていません
該当のソースコード(main.py)
python
1import tkinter as tk 2 3 4class main: 5 def __init__(self) -> None: 6 win = tk.Tk() 7 win.title("main") 8 win.geometry('510x170') 9 Button1= tk.Button(win, text="カラーマッチング",bg="lightgreen",command= self.ctdown).grid() 10 win.mainloop() 11 12 13 14 15 def ctdown(self): 16 import colorMatch 17 18 19 20app = main()
該当のソースコード(colorMatch.py)
python
1import tkinter as tk 2from tkinter import filedialog 3from PIL import Image, ImageTk, ImageOps # 画像データ用 4import matplotlib.pyplot as plt 5from matplotlib.patches import Polygon 6import numpy as np 7from tkinter import font 8import time 9from tkinter import messagebox 10import cv2 11import sys 12 13class Application(tk.Frame): 14 15 def __init__(self, master = None): 16 super().__init__(master) 17 self.pack() 18 19 fonts = ("", 14) 20 21 22 self.master.title("OpenCVの動画表示") # ウィンドウタイトル 23 self.master.geometry("1330x750+0+0") 24 #self.master.attributes('-fullscreen', True) # ウィンドウサイズ(幅x高さ) 25 26 27 28 frame1 = tk.Frame(self.master, width=400,height=800) 29 frame1.pack(expand = True,fill=tk.BOTH) 30 31 32 self.button = tk.Button(frame1,text="Snapshot",width=20, height=5, font=fonts,bg="beige" ,command=self.snapshot) 33 self.button.pack(side=tk.BOTTOM,fill=tk.X) 34 35 # Canvasの作成 36 self.canvas = tk.Canvas(frame1) 37 # Canvasにマウスイベント(左ボタンクリック)の追加 38 self.canvas.bind('<Button-1>', self.canvas_click) 39 # Canvasを配置 40 self.canvas.pack(expand = True, fill = tk.BOTH) 41 42 # カメラをオープンする 43 self.capture = cv2.VideoCapture(0) 44 45 self.disp_id = None 46 47 48 49 50 def canvas_click(self, event): 51 '''Canvasのマウスクリックイベント''' 52 53 if self.disp_id is None: 54 # 動画を表示 55 self.disp_image() 56 else: 57 # 動画を停止 58 self.after_cancel(self.disp_id) 59 self.disp_id = None 60 61 def disp_image(self): 62 '''画像をCanvasに表示する''' 63 64 # フレーム画像の取得 65 ret, self.frame22 = self.capture.read() 66 67 # BGR→RGB変換 68 cv_image = cv2.cvtColor(self.frame22, cv2.COLOR_BGR2RGB) 69 # NumPyのndarrayからPillowのImageへ変換 70 pil_image = Image.fromarray(cv_image) 71 72 # キャンバスのサイズを取得 73 canvas_width = self.canvas.winfo_width() 74 canvas_height = self.canvas.winfo_height() 75 76 # 画像のアスペクト比(縦横比)を崩さずに指定したサイズ(キャンバスのサイズ)全体に画像をリサイズする 77 pil_image = ImageOps.pad(pil_image, (canvas_width, canvas_height)) 78 79 # PIL.ImageからPhotoImageへ変換する 80 self.photo_image = ImageTk.PhotoImage(master = self.master,image=pil_image) 81 82 # 画像の描画 83 self.canvas.create_image( 84 canvas_width / 2, # 画像表示位置(Canvasの中心) 85 canvas_height / 2, 86 image=self.photo_image # 表示画像データ 87 ) 88 89 90 # disp_image()を10msec後に実行する 91 self.disp_id = self.after(10, self.disp_image) 92 93 94 def snapshot(self): 95 filename = "C:/Users/Pictures/test.png" 96 self.snapnum = 1 97 self.after_cancel(self.disp_id) 98 self.disp_id = None 99 100 cv2.imwrite( filename,self.frame22) 101 print(filename) 102 self.master.destroy() 103 self.capture.release() 104 105 cv2.destroyAllWindows() 106 time.sleep(1) 107 self.snapnum = 1 108 109class match(tk.Frame): 110 111 def __init__(self, master = None): 112 super().__init__(master) 113 #self.pack() 114 self.pinCorrect = 0 115 116 117 self.master.title("処理結果") # ウィンドウタイトル 118 self.master.geometry("1330x750+0+0") 119 self.master.lift() 120 121 #root.protocol('WM_DELETE_WINDOW', quit) 122 img = cv2.imread("C:/Users/Pictures/test.png") # 画像を読み込む。 123 124 # 色基準で2値化する。 125 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # HSV 色空間に変換 126 127 red = cv2.inRange(hsv, np.array([145, 70, 0]), np.array([180, 255, 255])) 128 yellow = cv2.inRange(hsv, np.array([10, 80, 0]), np.array([50, 255, 255])) 129 green = cv2.inRange(hsv, np.array([30, 190, 0]), np.array([90, 255, 255])) 130 blue = cv2.inRange(hsv, np.array([90, 70, 90]), np.array([210, 255, 255])) 131 #white = cv2.inRange(hsv, np.array([108, 21, 0]), np.array([255, 70, 255])) 132 133 # 白だけゴミがあるので、収縮演算 134 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) 135 #white = cv2.erode(white, kernel) 136 137 138 bin_imgs = {'red': red, 'yellow': yellow, 'green': green, 139 'blue': blue, } 140 141 142 143 144 145 146 fig, ax = plt.subplots(figsize=(8, 5)) 147 ax.axis('off') 148 ax.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) 149 count1 = {'red':0,'yellow':0,'green':0,'blue':0} 150 # 輪郭検出し、数を求める。 151 ############################################## 152 for label, bin_img in bin_imgs.items(): 153 contours,hierarchy = cv2.findContours( 154 bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 155 # 輪郭を構成する頂点数で誤検出を除く。 156 contours = list(filter(lambda cnt: len(cnt) > 30, contours)) 157 count = len(contours) 158 count1[label] = count 159 print('color: {}, conunt: {}'.format(label, count)) 160 161 # 描画する。 162 for cnt in contours: 163 cnt = np.squeeze(cnt, axis=1) # (N, 1, 2) -> (N, 2) 164 ax.add_patch(Polygon(cnt, fill=None, lw=2., color=label)) 165 plt.show(block=False) 166 plt.savefig("C:/Users/Pictures/testafter.png") 167 168 plt.show(block=False) 169 plt.close() 170 171 172 173 frame1 = tk.Frame(self.master,bg="beige",width=1200,height=500) 174 frame1.pack(expand = True,fill=tk.BOTH) 175 176 177 178 # Canvasの作成 179 canvas = tk.Canvas(frame1,bg="beige",width=1200,height=500) 180 181 # Canvasを配置 182 canvas.pack(expand = True, fill = tk.BOTH) 183#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 184 # フレーム画像の取得 185 img = ImageTk.PhotoImage(master = self.master,file = "C:/Users/Pictures/testafter.png") 186 self.w = img.width # 横幅を取得 187 self.h = img.height # 縦幅を取得 188 189 190 191 # キャンバスのサイズを取得 192 self.canvas_width = canvas.winfo_width() 193 self.canvas_height = canvas.winfo_height() 194 195 196 RedAnswer = 5 197 BlueAnswer = 5 198 YellowAnswer = 5 199 GreenAnswer = 5 200 201 if (count1['red']) >= RedAnswer and \ 202 (count1['yellow']) >= YellowAnswer and\ 203 (count1['green']) >= GreenAnswer and \ 204 (count1['blue']) >= BlueAnswer : 205 self.pinCorrect = 1 206 font1 = font.Font(family='Helvetica', size=110, weight='bold') 207 label2 = tk.Label(self.master, text="OK",font=font1,fg="green") #文字ラベル設定 208 label2.pack(side = "bottom") 209 canvas.create_image( 210 600, # 画像表示位置(Canvasの中心) 211 250, 212 image=img, 213 anchor = tk.CENTER 214 # 表示画像データ 215 ) 216 217 else: 218 rednotenough = RedAnswer-(count1['red']) 219 yellowNotEnough = YellowAnswer-(count1['yellow']) 220 greenNotEnough = GreenAnswer-(count1['green']) 221 blueNotEnough = BlueAnswer-(count1['blue']) 222 self.pinCorrect = 0 223 #0以下は0にする 224 rednotenough = max(0,rednotenough) 225 yellowNotEnough = max(0,yellowNotEnough) 226 greenNotEnough = max(0,greenNotEnough) 227 blueNotEnough = max(0,blueNotEnough) 228 229 font0 = font.Font(family='Helvetica', size=20, weight='bold') 230 text0 = "赤色が"+ str(rednotenough) + "個\n"\ 231 "黄色が"+ str(yellowNotEnough) + "個\n"\ 232 "緑が"+ str(greenNotEnough) + "個\n"\ 233 "青が"+ str(blueNotEnough) + "個\n"\ 234 "足りません" 235 236 237 238 239 240 label0 = tk.Label(self.master, text=text0,font=font0,fg="red") 241 label0 .place(relx=0.85,rely=0.75) 242 243 244 font1 = font.Font(family='Helvetica', size=110, weight='bold') 245 label1 = tk.Label(self.master, text="NG",font=font1,fg="red") #文字ラベル設定 246 label1.pack(side = "bottom") 247 248 canvas.create_image( 249 600, # 画像表示位置(Canvasの中心) 250 250, 251 image=img, 252 anchor = tk.CENTER 253 # 表示画像データ 254 ) 255 256 #time.sleep() 257 ret = messagebox.showerror("NG画面", "マッチしていません") 258 if ret == "ok": 259 self.master.quit() 260 self.master.destroy() 261 262 263while True: 264 root = tk.Tk() 265 app = Application(master = root) 266 app.mainloop() 267 if app.snapnum == 1: 268 win = tk.Tk() 269 apple= match(master = win) 270 apple.mainloop() 271 print("done33") 272 if apple.pinCorrect == 1: 273 break 274 275 276
試したこと
google検索
検索しましたが、同じパターンのページを見つけることができず、解決に至りませんでした。
補足情報(FW/ツールのバージョンなど)
開発環境はVScodeで言語はpython です。
お分かりになる方がいましたらご教授お願いいたします。
あなたの回答
tips
プレビュー