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

回答編集履歴

1

コードを追加。

2018/11/13 14:47

投稿

tachikoma
tachikoma

スコア3601

answer CHANGED
@@ -1,3 +1,85 @@
1
- 検出処理を別スレッドに飛ばしたりするなどの工夫が必要ですね。
1
+ 検出処理を別スレッドに飛ばしたりするなどの工夫が必要ですね。難しいですが、検出器側の大まかな構造だけを実装してみました(検出ロジックは未実装)。
2
2
 
3
- 検出用のクラスを作って非同期処理(スレッド等)の検出メソッド作っておいて、検出処理が終わっているかをメンルーで確認。もし終わっていれば矩形を描画とか。もちろん検出結果数フーム前ものるので、現在の物体の位置とはズレが発生しますよん
3
+ 非同期処理には`threading`いて、タスクのパイプには`queue`を使っていす。Pythonのqueueッド同期利用できるのでうまく使う便利です。検出処理自体`run`の中に実装しますが、タスクの開始はdetectメソッドを通して行い、getResultで結果を回収することを意図した構造です
4
+
5
+ 一番したに試しにこのクラスを使ったコードがあります。動作を追いかけられますかね。
6
+
7
+ ```Python
8
+ import threading
9
+ import queue
10
+ import time
11
+ import numpy
12
+
13
+
14
+ class Detector(threading.Thread):
15
+ """非同期の物体検出クラス"""
16
+
17
+ def __init__(self):
18
+ threading.Thread.__init__(self)
19
+ self._lock = threading.Lock()
20
+
21
+ # タスク・結果のパイプ用
22
+ self._task_queue = queue.Queue(maxsize=1)
23
+ self._result_queue = queue.Queue(maxsize=1)
24
+
25
+ # threadを開始させておく
26
+ self.busy = False
27
+ self.start()
28
+
29
+ def join(self):
30
+ """終了処理"""
31
+ self._task_queue.put(None)
32
+ super(Detector, self).join()
33
+
34
+ def run(self):
35
+ """検出処理をするメイン部分"""
36
+ while True:
37
+ with self._lock:
38
+ task = self._task_queue.get()
39
+ if task is None:
40
+ # スレッドの終了条件
41
+ break
42
+ self.busy = True # 追加の処理を受け付けないようにする
43
+ print("get task", task, time.ctime())
44
+
45
+ # 重い処理の部分
46
+ time.sleep(3)
47
+
48
+ # 結果をqueueに送り込む
49
+ with self._lock:
50
+ if self._result_queue.full():
51
+ # 回収されていない結果は捨てる
52
+ self._result_queue.get()
53
+ self._result_queue.put("done " + task)
54
+ self.busy = False
55
+ print("finishd task", task, time.ctime())
56
+ print("thread finished", time.ctime())
57
+
58
+ def detect(self, img: numpy.array) -> bool:
59
+ """非同期で検出処理を受け付ける"""
60
+ if not self.busy:
61
+ self._task_queue.put(img)
62
+ return True
63
+ return False
64
+
65
+ def getResult(self) -> (bool, list):
66
+ """結果を回収する"""
67
+ if not self._result_queue.empty():
68
+ return True, self._result_queue.get()
69
+ return False, []
70
+
71
+
72
+ if __name__ == "__main__":
73
+ det = Detector()
74
+ print(det.detect("hoge")) # 検出処理を依頼
75
+ time.sleep(1)
76
+ print(det.detect("foo")) # 続けざまに処理を依頼すると拒否される
77
+ time.sleep(3) # 終了するまで待つ
78
+ done, result = det.getResult() # 結果の回収を試みる
79
+ if done:
80
+ # もしタスクが完了していれば
81
+ print("result ", result)
82
+ # 前のタスクが完了していれば次の処理を受け付ける
83
+ print(det.detect("bar"))
84
+ det.join()
85
+ ```