teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

5

解説!

2018/08/18 14:33

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -1,8 +1,29 @@
1
1
  やりたいことがあまり初心者向けとは思えないのですが、
2
2
  `multiprocessing`や`ProcessPoolExecutor`/`asyncio`でググるとサンプルソースがヒットするかもです。
3
3
 
4
+ ■原因
5
+ `root.mainloop()` # ←の行でGUI入力待ちのブロッキングをしているからです。
6
+ そのため、`while`ループ内の`ret, frame = cap.read()`の行が実行されません。
7
+ 参考:[Use TkInter without mainloop](https://gordonlesti.com/use-tkinter-without-mainloop/)
8
+
9
+ ■対策
10
+ | | |
11
+ |:--|:--:|
12
+ |動画の処理を行う部分|cap.read()|
13
+ |tkinter表示部|root.mainloop()|
14
+
15
+ を分割してマルチスレッド/マルチプロセスで並列化すれば解消されるかと。
16
+ ここまでが、動画検知を行いながら+αの処理も行う方法
17
+
18
+ > Tkinterにて警告を出したい
19
+
20
+ そして、質問文のこの要件があるので、動画検知側から`tkinter`側に通知する必要があります。
21
+ そのために`multiprocessing#Queue`を使った、`producer-consumer`デザインパターンを使用しました。
22
+
23
+ ---
24
+
4
25
  あまり動作確認していませんが、サンプルコードを置いておきます。ご参考まで。
5
- 個人的には、プロセスを分けた方が良いのではとも。
26
+ 個人的には、`python`のプロセスを分けた方が良いのではとも。
6
27
 
7
28
  ```Python
8
29
  # -*- coding: utf-8 -*-

4

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

2018/08/18 14:33

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -102,10 +102,11 @@
102
102
  if not file_path: # isEmpty
103
103
  return
104
104
  print(file_path)
105
+ ※ producer-consumer デザインパターン
105
106
  queue = Queue()
106
107
  producer = Process(target=produce, args=(queue, file_path))
107
- customer = Process(target=consume, args=(queue,))
108
+ consumer = Process(target=consume, args=(queue,))
108
- customer.start() # ※ カスタマーから先に起動
109
+ consumer.start() # ※ コンシュから先に起動
109
110
  producer.start()
110
111
  producer.join() # ※ プロデューサーはjoinで終了待ちを行う。
111
112
 

3

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

2018/08/18 05:24

投稿

umyu
umyu

スコア5846

answer CHANGED
File without changes

2

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

2018/08/18 05:06

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -1,7 +1,7 @@
1
1
  やりたいことがあまり初心者向けとは思えないのですが、
2
2
  `multiprocessing`や`ProcessPoolExecutor`/`asyncio`でググるとサンプルソースがヒットするかもです。
3
3
 
4
- とりえず、ざっくばらんに書サンプルコードを置いておきます。ご参考まで。
4
+ まり動作確認してませんが、サンプルコードを置いておきます。ご参考まで。
5
5
  個人的には、プロセスを分けた方が良いのではとも。
6
6
 
7
7
  ```Python

1

追記

2018/08/18 05:06

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -1,5 +1,5 @@
1
1
  やりたいことがあまり初心者向けとは思えないのですが、
2
- multiprocessing ProcessPoolExecutor / asyncioでググるとサンプルソースがヒットするかもです。
2
+ `multiprocessing``ProcessPoolExecutor`/`asyncio`でググるとサンプルソースがヒットするかもです。
3
3
 
4
4
  とりあえず、ざっくばらんに書いたサンプルコードを置いておきます。ご参考まで。
5
5
  個人的には、プロセスを分けた方が良いのではとも。
@@ -24,7 +24,7 @@
24
24
 
25
25
  while True:
26
26
  ret, frame = capture.read()
27
- if not ret: # readの戻り値は絶対に確認すること!!!!!!!!!!!
27
+ if not ret: # readの戻り値は絶対に確認すること!!!!!!!!!!!
28
28
  break
29
29
  edframe = frame
30
30
  cv2.putText(edframe, 'test', (0, 50),
@@ -51,6 +51,7 @@
51
51
  else:
52
52
  pass
53
53
  print(wide) # , end=" ")
54
+ # ※ queueに追加 表示したい文字列なり数字なりEOF以外ならなんでも良い。
54
55
  queue.put("attention!!!!")
55
56
  else:
56
57
  pass
@@ -62,23 +63,23 @@
62
63
  k = cv2.waitKey(1)
63
64
  if k == 27:
64
65
  break
65
- # EOF
66
+ # EOF
66
67
  queue.put(None)
67
68
  print("produce END")
68
69
  cv2.destroyAllWindows()
69
70
 
70
71
 
71
72
  def on_message(queue:Queue):
72
- root.withdraw() # 非表示
73
+ root.withdraw() # 非表示
73
- item = queue.get(True) # タイムアウトを指定するかはどうかは仕様によるかと。
74
+ item = queue.get(True) # タイムアウトを指定するかはどうかは仕様によるかと。
74
75
  if not item: # EOF
75
- # Windowの終了
76
+ # Windowの終了
76
77
  print("on_message EOF")
77
78
  root.quit()
78
79
  return
79
80
  var_message.set(item)
80
- root.deiconify() # 表示
81
+ root.deiconify() # 表示
81
- # デッドライン間隔、Queueに要素を追加するのが早いのならその点も考慮する事
82
+ # デッドライン間隔、Queueに要素を追加するのが早いのならその点も考慮する事
82
83
  root.after(1000, on_message, queue)
83
84
 
84
85
 
@@ -95,7 +96,7 @@
95
96
 
96
97
 
97
98
  def main() -> None:
98
- # ↓ファイル選択ダイアログでTopLevelウィンドウが表示されるので。
99
+ # ↓ファイル選択ダイアログでTopLevelウィンドウが表示されるので。
99
100
  root.withdraw()
100
101
  file_path = filedialog.askopenfilename(parent=root)
101
102
  if not file_path: # isEmpty
@@ -104,9 +105,9 @@
104
105
  queue = Queue()
105
106
  producer = Process(target=produce, args=(queue, file_path))
106
107
  customer = Process(target=consume, args=(queue,))
107
- customer.start() # カスタマーから先に起動
108
+ customer.start() # カスタマーから先に起動
108
109
  producer.start()
109
- producer.join() # プロデューサーはjoinで終了待ちを行う。
110
+ producer.join() # プロデューサーはjoinで終了待ちを行う。
110
111
 
111
112
 
112
113
  if __name__ == "__main__":