ウィンドウのフリーズ
現在画像認識のプログラムを作成しており、認識自体はできるようになりました。
実行の結果をTkinterで文字として表示しようと思ったのですが、動作が固まってしまいます。
Tkinterのウィンドウを消せばまた認識をしてくれるのですが、止まることなく実行するにはどうすればいいでしょうか。
解決策を教えていただけると嬉しいです。
画像認識について
認識は、あらかじめ作成したデータを読み込んで使用しています。
写真はcv2で撮影したリアルタイム映像から、静止画として同じ階層に一時的に保存し、
PILで読み込んでいます。
環境
python 3.6.1
opencv-contrib-python 4.2.0.32
opencv-python 4.2.0.32
pillow 4.1.1
scikit-learn 0.18.1
コードです↓
python
1import cv2 2import os 3import datetime 4import pickle 5from PIL import Image 6from sklearn import svm 7import numpy as np 8import tkinter as tk 9from tkinter import font 10 11# ウィンドウ表示の定義 12def print_text(result): 13 root = tk.Tk()#ウィンドウを作る 14 15 root.title("ティッシュ認識システム") #タイトルの変更 16 root.geometry("300x100") #サイズの指定 17 18 font1 = font.Font(family='Helvetica', size=20, weight='bold') #フォントを設定 19 20 text = tk.StringVar()#textをStringVar関数にする 21 22 if result ==1: 23 text.set("これはティッシュです") 24 25 else: 26 text.set("これは床です") 27 28 label = tk.Label(textvariable = text, font = font1) #ラベルを追加 29 label.pack() 30 31 root.mainloop() #実行して表示 32 33 34# 画像認識の学習データを読み込む 35filename = 'tissue_model_1.sav' 36clf = pickle.load(open(filename, 'rb')) 37 38# 変数の定義 39size = 16 40 41# 認識システムを関数で定義 42def save_frame_camera_cycle(device_num, dir_path, basename, cycle, ext='JPG', delay=1, window_name='frame'): 43 cap = cv2.VideoCapture(1)# カメラは1(usbカメラ)を用いる 44 45 if not cap.isOpened():#カメラが見つからなかった場合 46 return#中止する 47 48 os.makedirs(dir_path, exist_ok=True) 49 base_path = os.path.join(dir_path, basename) 50 51 n = 0 52 while True: #Trueでずっとループさせる 53 ret, frame = cap.read() 54 cv2.imshow(window_name, frame) 55 if cv2.waitKey(delay) & 0xFF == ord('q'):# qが押されたら終了する 56 break 57 if n == cycle:#cycleとnが同じ数になったら写真を保存する 58 59 cv2.imwrite('{}_{}.{}'.format(base_path, datetime.datetime.now().strftime('%Y%m%d%H%M%S%f'), ext), frame)#画像を保存(学習用に保存) 60 cv2.imwrite('picture.' + ext, frame)#認識用の画像を保存 61 img = Image.open('picture.JPG')#画像を開く 62 img = img.resize((size,size))#リサイズ 63 ary = np.array(img).reshape(-1,)#一次元の配列にする 64 result = clf.predict(ary)#認識 65 print(result)#結果を表示 66 67 print_text(result = result) 68 69 n = 0 70 n += 1 71 72 cv2.destroyWindow(window_name) 73 74#関数を実行 75save_frame_camera_cycle(0, 'camera_data', 'camera_capture_cycle', 15)
アドバイスを受け、マルチスレッドで実行するようにプログラムを変更しました。
python
1import cv2 2import os 3import datetime 4from sklearn import svm 5import pickle 6from PIL import Image 7import numpy as np 8import tkinter as tk 9from tkinter import font 10import threading 11 12# ウィンドウ表示の定義 13def print_text(): 14 root = tk.Tk()#ウィンドウを作る 15 16 root.title("ティッシュ認識システム") #タイトルの変更 17 root.geometry("300x100") #サイズの指定 18 19 font1 = font.Font(family='Helvetica', size=20, weight='bold') #フォントを設定 20 21 text = tk.StringVar()#textをStringVar関数にする 22 23 if result ==1: 24 text.set("これはティッシュです") 25 26 else: 27 text.set("これは床です") 28 29 label = tk.Label(textvariable = text, font = font1) #ラベルを追加 30 label.pack() 31 32 root.mainloop() #実行して表示 33 print("a") 34 35# 画像認識の学習データを読み込む 36filename = 'tissue_model_1.sav' 37clf = pickle.load(open(filename, 'rb')) 38 39# 変数の定義 40size = 16 41 42# 認識システムを関数で定義 43def save_frame_camera_cycle(device_num, dir_path, basename, cycle, ext='JPG', delay=1, window_name='frame'): 44 cap = cv2.VideoCapture(1)# カメラは1(usbカメラ)を用いる 45 46 if not cap.isOpened():#カメラが見つからなかった場合 47 return#中止する 48 49 os.makedirs(dir_path, exist_ok=True) 50 base_path = os.path.join(dir_path, basename) 51 52 n = 0 53 while True: #Trueでずっとループさせる 54 ret, frame = cap.read() 55 cv2.imshow(window_name, frame) 56 if cv2.waitKey(delay) & 0xFF == ord('q'):# qが押されたら終了する 57 break 58 if n == cycle:#cycleとnが同じ数になったら写真を保存する 59 60 cv2.imwrite('{}_{}.{}'.format(base_path, datetime.datetime.now().strftime('%Y%m%d%H%M%S%f'), ext), frame)#画像を保存 61 cv2.imwrite('picture.' + ext, frame)#画像を1時的に保存 62 img = Image.open('picture.JPG')#画像を開く 63 img = img.resize((size,size))#リサイズ 64 ary = np.array(img).reshape(-1,)#一次元の配列にする 65 global result 66 result = clf.predict(ary)#認識 67 print(result)#結果を表示 68 69 print_text(result = result) 70 71 n = 0 72 n += 1 73 74 cv2.destroyWindow(window_name) 75 76#関数を実行 77t1 = threading.Thread(target = save_frame_camera_cycle, args = (0, 'camera_data', 'camera_capture_cycle', 15)) 78t2 = threading.Thread(target = print_text,) 79t2.start() 80t1.start()
しかし、
python
1Exception in thread Thread-12: 2Traceback (most recent call last): 3 File "C:\Users\ユーザー名\Anaconda3\lib\threading.py", line 916, in _bootstrap_inner 4 self.run() 5 File "C:\Users\ユーザー名\Anaconda3\lib\threading.py", line 864, in run 6 self._target(*self._args, **self._kwargs) 7 File "<ipython-input-8-c90b360b3e2d>", line 19, in print_text 8 font1 = font.Font(family='Helvetica', size=20, weight='bold') #フォントを設定 9 File "C:\Users\ユーザー名\Anaconda3\lib\tkinter\font.py", line 93, in __init__ 10 tk.call("font", "create", self.name, *font) 11RuntimeError: main thread is not in main loop 12 13C:\Users\ユーザー名\Anaconda3\lib\site-packages\sklearn\utils\validation.py:395: DeprecationWarning: Passing 1d arrays as data is deprecated in 0.17 and will raise ValueError in 0.19. Reshape your data either using X.reshape(-1, 1) if your data has a single feature or X.reshape(1, -1) if it contains a single sample. 14 DeprecationWarning) 15Exception in thread Thread-11: 16Traceback (most recent call last): 17 File "C:\Users\ユーザー名\Anaconda3\lib\threading.py", line 916, in _bootstrap_inner 18 self.run() 19 File "C:\Users\ユーザー名\Anaconda3\lib\threading.py", line 864, in run 20 self._target(*self._args, **self._kwargs) 21 File "<ipython-input-8-c90b360b3e2d>", line 69, in save_frame_camera_cycle 22 print_text(result = result) 23TypeError: print_text() got an unexpected keyword argument 'result'
と、結果となるresultをTkinterウィンドウの関数が受け取ることができませんでした。
変数を共有するには、どうしたらよいでしょうか?
回答1件
あなたの回答
tips
プレビュー