前提・実現したいこと
tkinterを用いたGUIのアプリケーションを作っているのですが、実行ボタンが押された際に関数を実行して目的の動作を行わせ、停止ボタンが押された際に停止させようと思っています。ボタンを押した際の動作はうまくいったのですが、停止ボタンを押そうとしてもstartの関数内でループしてしまい停止ボタンを押すことができません、どうすればよいでしょうか
該当のソースコード
Python
1from mutagen.mp3 import MP3 as mp3 2import numpy as np 3import cv2 4import pygame 5import time 6import threading 7import sys 8import tkinter 9 10root =tkinter.Tk() 11root.title(u"app") 12root.geometry("600x700") 13 14def end1(): 15 t=1 16 17def getCircle1(frame, lower_color, upper_color): 18 MIN_RADIUS = 25 19 20 # HSVによる画像情報に変換 21 hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) 22 23 # ガウシアンぼかしを適用して、認識精度を上げる 24 blur = cv2.GaussianBlur(hsv, (9, 9), 0) 25 26 # 指定した色範囲のみを抽出する 27 color = cv2.inRange(blur, lower_color, upper_color) 28 29 # オープニング・クロージングによるノイズ除去 30 element8 = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]], np.uint8) 31 oc = cv2.morphologyEx(color, cv2.MORPH_OPEN, element8) 32 oc = cv2.morphologyEx(oc, cv2.MORPH_CLOSE, element8) 33 34 # 輪郭抽出 35 img, contours, hierarchy = cv2.findContours(oc, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 36 print("{} contours.".format(len(contours))) 37 38 if len(contours) > 0: 39 # 一番大きい赤色領域を指定する 40 contours.sort(key=cv2.contourArea, reverse=True) 41 cnt = contours[0] 42 43 # 最小外接円を用いて円を検出する 44 (x, y), radius = cv2.minEnclosingCircle(cnt) 45 center = (int(x), int(y)) 46 radius = int(radius) 47 48 49 # 円が小さすぎたら円を検出していないとみなす 50 if radius < MIN_RADIUS: 51 return None 52 else: 53 return center, radius 54 else: 55 return None 56 57def getCircle2(frame, lower_color, upper_color): 58 MIN_RADIUS = 25 59 60 # HSVによる画像情報に変換 61 hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) 62 63 # ガウシアンぼかしを適用して、認識精度を上げる 64 blur = cv2.GaussianBlur(hsv, (9, 9), 0) 65 66 # 指定した色範囲のみを抽出する 67 color = cv2.inRange(blur, lower_color, upper_color) 68 69 # オープニング・クロージングによるノイズ除去 70 element8 = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]], np.uint8) 71 oc = cv2.morphologyEx(color, cv2.MORPH_OPEN, element8) 72 oc = cv2.morphologyEx(oc, cv2.MORPH_CLOSE, element8) 73 74 # 輪郭抽出 75 img, contours, hierarchy = cv2.findContours(oc, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 76 print("{} contours.".format(len(contours))) 77 78 if len(contours) > 0: 79 # 一番大きい赤色領域を指定する 80 contours.sort(key=cv2.contourArea, reverse=True) 81 cnt = contours[0] 82 83 # 最小外接円を用いて円を検出する 84 (x, y), radius = cv2.minEnclosingCircle(cnt) 85 center = (int(x), int(y)) 86 radius = int(radius) 87 88 89 # 円が小さすぎたら円を検出していないとみなす 90 if radius < MIN_RADIUS: 91 return None 92 else: 93 return center, radius 94 else: 95 return None 96 97def start(): 98 99 # 内蔵カメラを起動(カメラが一つしか繋がっていない場合は、引数に0を渡せば良い) 100 cap = cv2.VideoCapture(1) 101 102 flgb1=0 103 flgt1=0 104 flgb2=0 105 flgt2=0 106 107 while True: 108 109 # 赤色の円を抽出する 110 frame = cap.read()[1] 111 getframe1 = getCircle1(frame, np.array([130,80,80]), np.array([200,255,255])) 112 #黄色の円を検出 113 getframe2 = getCircle2(frame, np.array([30,50,50]), np.array([80,255,255])) 114 115 #赤が見つかったら 116 if getframe1 is not None: 117 # 見つかった円の上に青い円を描画 118 # getframe[0]:中心座標、getframe[1]:半径 119 cv2.circle(frame, getframe1[0], getframe1[1], (255, 0, 0), 2) 120 if flgb1==0:#flgb1が0の時 121 filename = 'ファイルパス' #再生したいmp3ファイル 122 pygame.mixer.init() 123 pygame.mixer.music.load(filename) #音源を読み込み 124 mp3_length = mp3(filename).info.length #音源の長さ取得 125 pygame.mixer.music.play(1) #再生開始。1の部分を変えるとn回再生(その場合は次の行の秒数も×nすること) 126 time.sleep(mp3_length + 0.25) #再生開始後、音源の長さだけ待つ(0.25待つのは誤差解消) 127 pygame.mixer.music.stop() #音源の長さ待ったら再生停止 128 flgb1=1#flgb1に1を代入し一回だけの処理 129 flgt1=0#flgt1に0を代入し時間処理を可能にする 130 at1=time.time()+5#今の時間+5秒 131 132 #黄色が見つかったら 133 if getframe2 is not None: 134 # 見つかった円の上に青い円を描画 135 # getframe[0]:中心座標、getframe[1]:半径 136 cv2.circle(frame, getframe2[0], getframe2[1], (255, 0, 0), 2) 137 if flgb2==0:#flgb2が0の時 138 filename = 'ファイルパス' #再生したいmp3ファイル 139 pygame.mixer.init() 140 pygame.mixer.music.load(filename) #音源を読み込み 141 mp3_length = mp3(filename).info.length #音源の長さ取得 142 pygame.mixer.music.play(1) #再生開始。1の部分を変えるとn回再生(その場合は次の行の秒数も×nすること) 143 time.sleep(mp3_length + 0.25) #再生開始後、音源の長さだけ待つ(0.25待つのは誤差解消) 144 pygame.mixer.music.stop() #音源の長さ待ったら再生停止 145 flgb2=1#flgb2に1を代入し一回だけの処理 146 flgt2=0#flgt2に0を代入し時間処理を可能にする 147 at2=time.time()+5#今の時間+5秒 148 149 nt1=time.time() 150 nt2=time.time() 151 152 if flgb1==1 and flgt1==0 and at1<=nt1: 153 flgb1=0 154 flgt1=1 155 156 if flgb2==1 and flgt2==0 and at2<=nt2: 157 flgb2=0 158 flgg2=1 159 160 # 検出結果とともに映像を表示 161 cv2.imshow('Circle Detect', frame) 162 163 164 if cv2.waitKey(1) & 0xFF == ord('q'): 165 break 166 167 # 終了時にカメラを解放 168 cap.release() 169 cv2.destroyAllWindows() 170 171btn1=tkinter.Button(root, text='aモード 開始',font=(" ",20),bg='#f0e68c',fg='#ff0000',height=5,width=14,command=start) 172btn1.place(x=50,y=170) 173 174btn2=tkinter.Button(root, text='aモード 停止',font=(" ",20),bg='#f0e68c',fg='#ff0000',height=5,width=14,command=end1) 175btn2.place(x=340,y=170) 176 177root.mainloop() 178 179
試したこと
ボタンが押された際にstartの関数を呼び出し、動作させることに成功した。
停止ボタンが押された際にstart内の動作を停止させたい。
補足情報(FW/ツールのバージョンなど)
python3.7
opencv-python(3.4.3.18)
numpy(1.15.1)
pygame(1.9.4)
muatagen(1.41.1)
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/12/06 08:13