回答編集履歴

5

解説!

2018/08/18 14:33

投稿

umyu
umyu

スコア5846

test CHANGED
@@ -4,9 +4,51 @@
4
4
 
5
5
 
6
6
 
7
+ ■原因
8
+
9
+ `root.mainloop()` # ←の行でGUI入力待ちのブロッキングをしているからです。
10
+
11
+ そのため、`while`ループ内の`ret, frame = cap.read()`の行が実行されません。
12
+
13
+ 参考:[Use TkInter without mainloop](https://gordonlesti.com/use-tkinter-without-mainloop/)
14
+
15
+
16
+
17
+ ■対策
18
+
19
+ | | |
20
+
21
+ |:--|:--:|
22
+
23
+ |動画の処理を行う部分|cap.read()|
24
+
25
+ |tkinter表示部|root.mainloop()|
26
+
27
+
28
+
29
+ を分割してマルチスレッド/マルチプロセスで並列化すれば解消されるかと。
30
+
31
+ ここまでが、動画検知を行いながら+αの処理も行う方法
32
+
33
+
34
+
35
+ > Tkinterにて警告を出したい
36
+
37
+
38
+
39
+ そして、質問文のこの要件があるので、動画検知側から`tkinter`側に通知する必要があります。
40
+
41
+ そのために`multiprocessing#Queue`を使った、`producer-consumer`デザインパターンを使用しました。
42
+
43
+
44
+
45
+ ---
46
+
47
+
48
+
7
49
  あまり動作確認していませんが、サンプルコードを置いておきます。ご参考まで。
8
50
 
9
- 個人的には、プロセスを分けた方が良いのではとも。
51
+ 個人的には、`python`のプロセスを分けた方が良いのではとも。
10
52
 
11
53
 
12
54
 

4

typoと初心者さんみたいなので、デザインパターン名を追加。

2018/08/18 14:33

投稿

umyu
umyu

スコア5846

test CHANGED
@@ -206,13 +206,15 @@
206
206
 
207
207
  print(file_path)
208
208
 
209
+ ※ producer-consumer デザインパターン
210
+
209
211
  queue = Queue()
210
212
 
211
213
  producer = Process(target=produce, args=(queue, file_path))
212
214
 
213
- customer = Process(target=consume, args=(queue,))
215
+ consumer = Process(target=consume, args=(queue,))
214
-
216
+
215
- customer.start() # ※ カスタから先に起動
217
+ consumer.start() # ※ コンシューマから先に起動
216
218
 
217
219
  producer.start()
218
220
 

3

ざっくばらんは方言みたいなので言葉を変更

2018/08/18 05:24

投稿

umyu
umyu

スコア5846

test CHANGED
File without changes

2

ざっくばらんは方言みたいなので言葉を変更

2018/08/18 05:06

投稿

umyu
umyu

スコア5846

test CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
 
6
6
 
7
- あえずざっくばらんに書いたサンプルコードを置いておきます。ご参考まで。
7
+ あま動作確認していませんが、サンプルコードを置いておきます。ご参考まで。
8
8
 
9
9
  個人的には、プロセスを分けた方が良いのではとも。
10
10
 

1

追記

2018/08/18 05:06

投稿

umyu
umyu

スコア5846

test CHANGED
@@ -1,6 +1,6 @@
1
1
  やりたいことがあまり初心者向けとは思えないのですが、
2
2
 
3
- multiprocessing ProcessPoolExecutor / asyncioでググるとサンプルソースがヒットするかもです。
3
+ `multiprocessing``ProcessPoolExecutor`/`asyncio`でググるとサンプルソースがヒットするかもです。
4
4
 
5
5
 
6
6
 
@@ -50,7 +50,7 @@
50
50
 
51
51
  ret, frame = capture.read()
52
52
 
53
- if not ret: # readの戻り値は絶対に確認すること!!!!!!!!!!!
53
+ if not ret: # readの戻り値は絶対に確認すること!!!!!!!!!!!
54
54
 
55
55
  break
56
56
 
@@ -104,6 +104,8 @@
104
104
 
105
105
  print(wide) # , end=" ")
106
106
 
107
+ # ※ queueに追加 表示したい文字列なり数字なりEOF以外ならなんでも良い。
108
+
107
109
  queue.put("attention!!!!")
108
110
 
109
111
  else:
@@ -126,7 +128,7 @@
126
128
 
127
129
  break
128
130
 
129
- # EOF
131
+ # EOF
130
132
 
131
133
  queue.put(None)
132
134
 
@@ -140,13 +142,13 @@
140
142
 
141
143
  def on_message(queue:Queue):
142
144
 
143
- root.withdraw() # 非表示
145
+ root.withdraw() # 非表示
144
-
146
+
145
- item = queue.get(True) # タイムアウトを指定するかはどうかは仕様によるかと。
147
+ item = queue.get(True) # タイムアウトを指定するかはどうかは仕様によるかと。
146
148
 
147
149
  if not item: # EOF
148
150
 
149
- # Windowの終了
151
+ # Windowの終了
150
152
 
151
153
  print("on_message EOF")
152
154
 
@@ -156,9 +158,9 @@
156
158
 
157
159
  var_message.set(item)
158
160
 
159
- root.deiconify() # 表示
161
+ root.deiconify() # 表示
160
-
162
+
161
- # デッドライン間隔、Queueに要素を追加するのが早いのならその点も考慮する事
163
+ # デッドライン間隔、Queueに要素を追加するのが早いのならその点も考慮する事
162
164
 
163
165
  root.after(1000, on_message, queue)
164
166
 
@@ -192,7 +194,7 @@
192
194
 
193
195
  def main() -> None:
194
196
 
195
- # ↓ファイル選択ダイアログでTopLevelウィンドウが表示されるので。
197
+ # ↓ファイル選択ダイアログでTopLevelウィンドウが表示されるので。
196
198
 
197
199
  root.withdraw()
198
200
 
@@ -210,11 +212,11 @@
210
212
 
211
213
  customer = Process(target=consume, args=(queue,))
212
214
 
213
- customer.start() # カスタマーから先に起動
215
+ customer.start() # カスタマーから先に起動
214
216
 
215
217
  producer.start()
216
218
 
217
- producer.join() # プロデューサーはjoinで終了待ちを行う。
219
+ producer.join() # プロデューサーはjoinで終了待ちを行う。
218
220
 
219
221
 
220
222