前提・実現したいこと
Python3.9.6 + tkinter + opencv という環境で、USBに接続したWEBカメラの画像を表示しています。
tkinterでGUIを作成し、”Camera”ボタンを押したらカメラキャプチャー画像を表示します。
”Quit”ボタンを押したらカメラキャプチャー画像を終了し、画面を閉じる仕様です。
カメラ画像を表示するウィンドウにフォーカスしキー入力すれば終了出来るのですが、tkinterのGUI上で停止する事が出来ません。
WEBで色々探し、スレッド等を試したのですが、実現出来ていません。
良い方法は無いでしょうか?
宜しくお願いします。
該当のソースコード
Python
1#!/usr/bin/python3 2# -*- coding: utf8 -*- 3import tkinter 4import cv2 5def Capture(): 6 cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) 7 if cap.isOpened() == False: 8 return 9 while True: 10 ret, frame = cap.read() 11 name = "video" 12 cv2.namedWindow(name, cv2.WINDOW_NORMAL) 13 cv2.imshow(name,frame) 14 k = cv2.waitKey(1) 15 if k == 27: 16 break 17 cap.release() 18 cv2.destroyAllWindows() 19 return 20 21class Application(tkinter.Frame): 22 def __init__(self, master=None): 23 super().__init__(master) 24 self.pack() 25 self.create_widgets() 26 return 27 28 def create_widgets(self): 29 # capture 30 self.button = tkinter.Button(self) 31 self.button["text"] = u"Camera" 32 self.button["command"] = self.button_func 33 self.button["width"] = 20 34 self.button.pack() 35 36 # Quit 37 self.quit = tkinter.Button(self) 38 self.quit["text"] = u"Quit" 39 self.quit["width"] = 20 40 self.quit["command"] = self.master.destroy 41 self.quit.pack() 42 return 43 44 # Callbacks 45 def button_func(self): 46 Capture() 47 return 48 49# メイン関数 50def main(): 51 # Windowの生成 52 root = tkinter.Tk() 53 root.geometry("200x100") 54 root.title(u"Test") 55 app = Application(master=root) 56 app.mainloop() 57 pass 58 59if __name__ == '__main__': 60 main()
試したこと
マルチスレッドをWEB上の情報を参考に試しましたが、うまく行きませんでした。
マルチスレッド化したときのコードです。
cameraボタンを押しcaptureを開始すると、黒画面が出力し、ハングアップしてしまいます。
python
1 2#!/usr/bin/python3 3# -*- coding: utf8 -*- 4import tkinter 5import cv2 6import threading 7import time 8 9stopflag = 0 10 11# Thread Test → OK 12class ThreadJob(threading.Thread): 13 def __init__(self, v=""): 14 threading.Thread.__init__(self) 15 16 def run(self): 17 global stopflag 18 19 while not(stopflag): 20 print('hello,stop=',stopflag) 21 time.sleep(1) 22 if stopflag != 0: 23 break 24 25# camera capture 26class ThreadJob2(threading.Thread): 27 def __init__(self, v=""): 28 threading.Thread.__init__(self) 29 30 def run(self): 31 global stopflag 32 cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) 33 if cap.isOpened() == False: 34 return 35 36 while not(stopflag): 37 ret, frame = cap.read() 38 name = "video" 39 cv2.namedWindow(name, cv2.WINDOW_NORMAL) 40 cv2.imshow(name,frame) 41 if stopflag != 0: 42 break 43 44 cap.release() 45 cv2.destroyAllWindows() 46 47 48class Application(tkinter.Frame): 49 50 def __init__(self, master=None): 51 super().__init__(master) 52 self.pack() 53 self.create_widgets() 54 55 def create_widgets(self): 56 # capture 57 self.button = tkinter.Button(self) 58 self.button["text"] = u"Camera" 59 self.button["command"] = self.button_func 60 self.button["width"] = 20 61 self.button.pack() 62 63 # stop 64 self.btnStop = tkinter.Button(self) 65 self.btnStop["text"] = u"Stop" 66 self.btnStop["command"] = self.button_Stop 67 self.btnStop["width"] = 20 68 self.btnStop.pack() 69 70 # Quit 71 self.quit = tkinter.Button(self) 72 self.quit["text"] = u"Quit" 73 self.quit["width"] = 20 74 self.quit["command"] = self.master.destroy 75 self.quit.pack() 76 77 # Callbacks 78 def button_func(self): 79 global stopflag 80 stopflag = 0 81 #t = ThreadJob() # スレッド確認OK 82 t = ThreadJob2() # capture 83 t.start() # スレッドを実行 84 85 def button_Stop(self): 86 global stopflag 87 print('stop') 88 stopflag = 1 89 90 91# メイン関数 92def main(): 93 # Windowの生成 94 root = tkinter.Tk() 95 root.geometry("200x100") 96 root.title(u"basic1") 97 app = Application(master=root) 98 app.mainloop() 99 100if __name__ == '__main__': 101 main() 102
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/08/09 01:27
2021/08/09 04:20 編集
2021/08/09 23:38
2021/08/11 06:25 編集