質問編集履歴

5

タイトルの改善

2021/01/06 21:48

投稿

amos
amos

スコア5

test CHANGED
@@ -1 +1 @@
1
- 【Python】カスケード分類器による物体検出のプログラムとパーティクルフィルタ(粒子フィルタ)による物体追跡プログラムの合成
1
+ 【Python】カスケード分類器物体検出し、パーティクルフィルタ(粒子フィルタ)物体追跡するプログラム
test CHANGED
File without changes

4

書式の改善

2021/01/06 21:48

投稿

amos
amos

スコア5

test CHANGED
File without changes
test CHANGED
@@ -2,23 +2,11 @@
2
2
 
3
3
  カスケード分類器を利用してリアルタイムでカメラで検出したい物体が写った場合、
4
4
 
5
- その物体を赤い枠で囲むプログラムとパーティクルフィルタを利用してカメラで赤い物体が写った場合、その物体を赤い枠で囲み、粒子で追跡するプログラムを作成することまで
6
-
7
- できました。
8
-
9
-
10
-
11
- この2つのプログラムをエラーすることなく動くように合成することで、
12
-
13
- カスケード分類器を利用してリアルタイムでカメラで検出したい物体が写った場合、
14
-
15
5
  その物体を赤い枠で囲み、パーティクルフィルタでその物体を粒子で追跡するプログラムを
16
6
 
17
- 作成をしたいと考えております。私なりに合成してみた結果、次のようなプログラムでエラーが発生しました。
7
+ 作成をしたいと考えております。
18
-
19
-
20
-
21
- ・カスケード分類器とパーティクルフィルタのプログラムを合成
8
+
9
+
22
10
 
23
11
  ```
24
12
 
@@ -30,11 +18,11 @@
30
18
 
31
19
  # 追跡対象
32
20
 
33
-
34
-
35
- def is_target(castom_rect):
21
+ def is_target(roi):
22
+
23
+
24
+
36
-
25
+ # 定数定義
37
-
38
26
 
39
27
  DEVICE_ID = 0
40
28
 
@@ -52,9 +40,9 @@
52
40
 
53
41
 
54
42
 
55
- # 初期フレームの読込
43
+ # 初期フレームの読
56
-
44
+
57
- end_flag, frame = cap.read()
45
+ ret, frame = cap.read()
58
46
 
59
47
  height, width, channels = frame.shape
60
48
 
@@ -70,17 +58,7 @@
70
58
 
71
59
 
72
60
 
73
- # 物体検出が成功した場合、物体を長方形の赤い枠で囲む
74
-
75
- if len (custom_rect) > 0:
76
-
77
- for rect in custom_rect:
78
-
79
- cv2.rectangle(img, tuple(rect[0:2]), tuple(rect[0:2] + rect[2:4]), (0, 0, 255), thickness = 3)
80
-
81
-
82
-
83
- return custom_rect
61
+ return roi == custom_rect
84
62
 
85
63
 
86
64
 
@@ -280,31 +258,73 @@
280
258
 
281
259
  DEVICE_ID = 0
282
260
 
283
-
261
+ ESC_KEY = 27
262
+
284
-
263
+ INTERVAL = 33
264
+
265
+
266
+
285
- # 動画ファイルキャプチャ
267
+ # 分類器指定
268
+
269
+ custom_cascade = cv2.CascadeClassifier('cascade.xml')
270
+
271
+
272
+
273
+ # カメラ映像取得
286
274
 
287
275
  cap = cv2.VideoCapture(DEVICE_ID)
288
276
 
289
277
 
290
278
 
291
- while cv2.waitKey(30) < 0:
279
+ # 初期フレームの読み込み
292
-
280
+
293
- ret, frame = cap.read()
281
+ ret, frame = cap.read()
294
-
282
+
295
- hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV_FULL)
283
+ hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV_FULL)
296
-
284
+
297
- h = hsv[:, :, 0]
285
+ h = hsv[:, :, 0]
286
+
287
+
288
+
298
-
289
+ # ウィンドウの準備
290
+
299
-
291
+ cv2.namedWindow('Result')
300
-
292
+
293
+
294
+
301
- # S, Vを2値化
295
+ # S, Vを2値化
302
-
296
+
303
- ret, s = cv2.threshold(hsv[:, :, 1], 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
297
+ ret, s = cv2.threshold(hsv[:, :, 1], 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
304
-
298
+
305
- ret, v = cv2.threshold(hsv[:, :, 2], 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
299
+ ret, v = cv2.threshold(hsv[:, :, 2], 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
306
-
300
+
307
- h[(s == 0) | (v == 0)] = 100
301
+ h[(s == 0) | (v == 0)] = 100
302
+
303
+
304
+
305
+ # 変換処理ループ
306
+
307
+ while ret == True:
308
+
309
+
310
+
311
+ # 画像の取得と顔の検出
312
+
313
+ img = frame
314
+
315
+ graying = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
316
+
317
+ custom_rect = custom_cascade.detectMultiScale(graying, scaleFactor = 1.07, minNeighbors = 2, minSize = (1, 1))
318
+
319
+
320
+
321
+ # 物体検出が成功した場合、物体を長方形の赤い枠で囲む
322
+
323
+ if len (custom_rect) > 0:
324
+
325
+ for rect in custom_rect:
326
+
327
+ cv2.rectangle(img, tuple(rect[0:2]), tuple(rect[0:2] + rect[2:4]), (0, 0, 255), thickness = 3)
308
328
 
309
329
 
310
330
 
@@ -332,18 +352,28 @@
332
352
 
333
353
  frame[int(ps1[i, 1]), int(ps1[i, 0])] = [0, 0, 200]
334
354
 
335
-
336
-
337
- # パーティクルの集中部分を赤い矩形で囲む
338
-
339
- cv2.rectangle(frame, (x - 20, y - 20), (x + 20, y + 20), (0, 0, 200), 5)
340
-
341
355
 
342
356
 
343
357
  cv2.imshow('Result', frame)
344
358
 
345
359
 
346
360
 
361
+ # Escキーで終了
362
+
363
+ key = cv2.waitKey(INTERVAL)
364
+
365
+ if key == ESC_KEY:
366
+
367
+ break
368
+
369
+
370
+
371
+ # 次のフレーム読み込み
372
+
373
+ end_flag, c_frame = cap.read()
374
+
375
+
376
+
347
377
  cap.release()
348
378
 
349
379
  cv2.destroyAllWindows()
@@ -356,18 +386,6 @@
356
386
 
357
387
  ```
358
388
 
359
- **・エラー**
360
-
361
-
362
-
363
- count = roi[is_target(roi)].size
389
+ しかし、このプログラムを実行すると、エラーはでないのですが、何も起こりません。
364
-
365
-
366
-
367
- : index 248 is out of bounds for axis 0 with size 30
390
+
368
-
369
-
370
-
371
-
372
-
373
- どなたかお力添えのほうしくお願い申し上げます。
391
+ どなたかお力添えのほうよろしくお願い申し上げます。

3

2021/01/06 21:47

投稿

amos
amos

スコア5

test CHANGED
File without changes
test CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
 
20
20
 
21
- カスケード分類器とパーティクルフィルタのプログラムを合成
21
+ カスケード分類器とパーティクルフィルタのプログラムを合成
22
22
 
23
23
  ```
24
24
 
@@ -370,4 +370,4 @@
370
370
 
371
371
 
372
372
 
373
- どなたかお力添えの宜しくお願い申し上げます。
373
+ どなたかお力添えのほう宜しくお願い申し上げます。

2

書式の改善

2021/01/06 10:47

投稿

amos
amos

スコア5

test CHANGED
File without changes
test CHANGED
@@ -4,39 +4,35 @@
4
4
 
5
5
  その物体を赤い枠で囲むプログラムとパーティクルフィルタを利用してカメラで赤い物体が写った場合、その物体を赤い枠で囲み、粒子で追跡するプログラムを作成することまで
6
6
 
7
+ できました。
8
+
9
+
10
+
7
- できました。この2つのプログラムをエラーすることなく動くように合成することで、
11
+ この2つのプログラムをエラーすることなく動くように合成することで、
8
12
 
9
13
  カスケード分類器を利用してリアルタイムでカメラで検出したい物体が写った場合、
10
14
 
11
15
  その物体を赤い枠で囲み、パーティクルフィルタでその物体を粒子で追跡するプログラムを
12
16
 
13
- 作成をしたいと考えております。なたかお力添えをお願い申上げ
17
+ 作成をしたいと考えております。りに合成してみ結果、次のようなプログラムでエラーが発生しました
14
-
15
-
16
-
18
+
19
+
20
+
17
- **① カスケード分類器を利用してリアルタイムでカメラで物体検出をするプログラム**
21
+ カスケード分類器とパーティクフィルプログラムを合成
22
+
18
-
23
+ ```
19
-
20
-
24
+
21
- import cv2
25
+ import cv2
22
-
23
-
24
-
25
- if __name__ == '__main__':
26
+
26
-
27
-
28
-
29
- __# 定数定義__
30
-
31
- ESC_KEY = 27
32
-
33
- INTERVAL = 33
34
-
35
- FRAME_RATE = 30
27
+ import numpy as np
28
+
29
+
30
+
36
-
31
+ # 追跡対象
37
-
38
-
32
+
33
+
34
+
39
- ORG_WINDOW_NAME = "org"
35
+ def is_target(castom_rect):
40
36
 
41
37
 
42
38
 
@@ -44,380 +40,334 @@
44
40
 
45
41
 
46
42
 
47
- __# 分類器の指定__
43
+ # 分類器の指定
48
44
 
49
45
  custom_cascade = cv2.CascadeClassifier('cascade.xml')
50
46
 
51
47
 
52
48
 
53
- __# カメラ映像取得__
49
+ # カメラ映像取得
54
50
 
55
51
  cap = cv2.VideoCapture(DEVICE_ID)
56
52
 
57
53
 
58
54
 
59
- __# 初期フレームの読込__
55
+ # 初期フレームの読込
60
-
56
+
61
- end_flag, c_frame = cap.read()
57
+ end_flag, frame = cap.read()
62
-
58
+
63
- height, width, channels = c_frame.shape
59
+ height, width, channels = frame.shape
64
-
65
-
66
-
67
- __# ウィンドウの準備__
60
+
68
-
69
- cv2.namedWindow(ORG_WINDOW_NAME)
61
+
70
-
71
-
72
-
73
- __# 変換処理ループ__
62
+
74
-
75
- while end_flag == True:
76
-
77
-
78
-
79
- __# 画像の取得と顔の検出__
63
+ # 画像の取得と顔の検出
80
-
64
+
81
- img = c_frame
65
+ img = frame
82
-
66
+
83
- graying = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
67
+ graying = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
84
-
68
+
85
- custom_rect = custom_cascade.detectMultiScale(graying, scaleFactor = 1.07, minNeighbors = 2, minSize = (1, 1))
69
+ custom_rect = custom_cascade.detectMultiScale(graying, scaleFactor = 1.07, minNeighbors = 2, minSize = (1, 1))
86
-
87
-
88
-
70
+
71
+
72
+
89
- __# 物体検出が成功した場合、物体を長方形の赤い枠で囲む__
73
+ # 物体検出が成功した場合、物体を長方形の赤い枠で囲む
90
-
74
+
91
- if len (custom_rect) > 0:
75
+ if len (custom_rect) > 0:
92
-
76
+
93
- for rect in custom_rect:
77
+ for rect in custom_rect:
94
-
78
+
95
- cv2.rectangle(img, tuple(rect[0:2]), tuple(rect[0:2] + rect[2:4]), (0, 0, 255), thickness = 3)
79
+ cv2.rectangle(img, tuple(rect[0:2]), tuple(rect[0:2] + rect[2:4]), (0, 0, 255), thickness = 3)
96
80
 
97
81
 
98
82
 
99
- __# フレーム表示__
100
-
101
- cv2.imshow(ORG_WINDOW_NAME, c_frame)
102
-
103
-
104
-
105
- __# Escキーで終了
106
-
107
- __ key = cv2.waitKey(INTERVAL)
108
-
109
- if key == ESC_KEY:
110
-
111
- break
112
-
113
-
114
-
115
- __# フレーム読み込み__
116
-
117
- end_flag, c_frame = cap.read()
118
-
119
-
120
-
121
- __# 終了処理
122
-
123
- __ cv2.destroyAllWindows()
83
+ return custom_rect
84
+
85
+
86
+
87
+ # マスクから面積最大ブロブの中心座標を算出
88
+
89
+ def max_moment_point(mask):
90
+
91
+
92
+
93
+ # ラベリング処理
94
+
95
+ label = cv2.connectedComponentsWithStats(mask)
96
+
97
+ data = np.delete(label[2], 0, 0) # ブロブのデータ
98
+
99
+ center = np.delete(label[3], 0, 0) # 各ブロブ中心座標
100
+
101
+ moment = data[:, 4] # 各ブロブの面積
102
+
103
+ max_index = np.argmax(moment) # 面積最大のインデックス
104
+
105
+ return center[max_index] # 面積最大のブロブの中心座標
106
+
107
+
108
+
109
+ # パーティクルの初期化
110
+
111
+ def initialize(img, N):
112
+
113
+ mask = img.copy() # 画像のコピー
114
+
115
+ x, y = max_moment_point(mask) # マスクから面積最大ブロブの中心座標を算出
116
+
117
+ w = calc_likelihood(x, y, img) # 尤度の算出
118
+
119
+ ps = np.ndarray((N, 3), dtype = np.float32) # パーティクル格納用の配列を生成
120
+
121
+ ps[:] = [x, y, w] # パーティクル用配列に中心座標と尤度をセット
122
+
123
+ return ps
124
+
125
+
126
+
127
+ # リサンプリング
128
+
129
+ def resampling(ps):
130
+
131
+
132
+
133
+ # 累積重みの計算
134
+
135
+ ws = ps[:, 2].cumsum()
136
+
137
+ last_w = ws[ws.shape[0] - 1]
138
+
139
+
140
+
141
+ # 新しいパーティクル用の空配列を生成
142
+
143
+ new_ps = np.empty(ps.shape)
144
+
145
+
146
+
147
+ # 前状態の重みに応じてパーティクルをリサンプリング (重みは1.0)
148
+
149
+ for i in range(ps.shape[0]):
150
+
151
+ w = np.random.rand() * last_w
152
+
153
+ new_ps[i] = ps[(ws > w).argmax()]
154
+
155
+ new_ps[i, 2] = 1.0
156
+
157
+
158
+
159
+ return new_ps
160
+
161
+
162
+
163
+ # 推定
164
+
165
+ def predict_position(ps, var = 13.0):
166
+
167
+
168
+
169
+ # 分散に従ってランダムに少し位置をずらす
170
+
171
+ ps[:, 0] += np.random.randn((ps.shape[0])) * var
172
+
173
+ ps[:, 1] += np.random.randn((ps.shape[0])) * var
174
+
175
+
176
+
177
+ # 尤度の算出
178
+
179
+ def calc_likelihood(x, y, img, w = 30, h = 30):
180
+
181
+
182
+
183
+ # 画像から座標(x, y)を中心とする幅 w, 高さ hの矩形領域の全画素を取得
184
+
185
+ x1, y1 = max(0, x - w/2), max(0, y - h/2)
186
+
187
+ x2, y2 = min(img.shape[1], x + w/2), min(img.shape[0], y + h/2)
188
+
189
+ x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
190
+
191
+ roi = img[y1:y2, x1:x2]
192
+
193
+
194
+
195
+ # 矩形領域中に含まれる追跡対象(色)の存在率を尤度として計算
196
+
197
+ count = roi[is_target(roi)].size
198
+
199
+ return (float(count) / img.size) if count > 0 else 0.0001
200
+
201
+
202
+
203
+ # パーティクルの重み付け
204
+
205
+ def calc_weight(ps, img):
206
+
207
+
208
+
209
+ # 尤度に従ってパーティクルの重み付け
210
+
211
+ for i in range(ps.shape[0]):
212
+
213
+ ps[i][2] = calc_likelihood(ps[i, 0], ps[i, 1], img)
214
+
215
+
216
+
217
+ # 重みの正規化
218
+
219
+ ps[:, 2] *= ps.shape[0] / ps[:, 2].sum()
220
+
221
+
222
+
223
+ # 観測
224
+
225
+ def observer(ps, img):
226
+
227
+
228
+
229
+ # パーティクルの重み付け
230
+
231
+ calc_weight(ps, img)
232
+
233
+
234
+
235
+ # 重み和の計算
236
+
237
+ x = (ps[:, 0] * ps[:, 2]).sum()
238
+
239
+ y = (ps[:, 1] * ps[:, 2]).sum()
240
+
241
+
242
+
243
+ # 重み付き平均を返す
244
+
245
+ return (x, y) / ps[:, 2].sum()
246
+
247
+
248
+
249
+ # パーティクルフィルタ
250
+
251
+ def particle_filter(ps, img, N = 300):
252
+
253
+
254
+
255
+ # パーティクルが無い場合
256
+
257
+ if ps is None:
258
+
259
+ ps = initialize(img, N) # パーティクルを初期化
260
+
261
+
262
+
263
+ ps = resampling(ps) # リサンプリング
264
+
265
+ predict_position(ps) # 推定
266
+
267
+ x, y = observer(ps, img) # 観測
268
+
269
+ return ps, int(x), int(y)
270
+
271
+
272
+
273
+ def main():
274
+
275
+
276
+
277
+ # パーティクル格納用の変数
278
+
279
+ ps = None
280
+
281
+ DEVICE_ID = 0
282
+
283
+
284
+
285
+ # 動画ファイルのキャプチャ
286
+
287
+ cap = cv2.VideoCapture(DEVICE_ID)
288
+
289
+
290
+
291
+ while cv2.waitKey(30) < 0:
292
+
293
+ ret, frame = cap.read()
294
+
295
+ hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV_FULL)
296
+
297
+ h = hsv[:, :, 0]
298
+
299
+
300
+
301
+ # S, Vを2値化
302
+
303
+ ret, s = cv2.threshold(hsv[:, :, 1], 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
304
+
305
+ ret, v = cv2.threshold(hsv[:, :, 2], 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
306
+
307
+ h[(s == 0) | (v == 0)] = 100
308
+
309
+
310
+
311
+ # パーティクルフィルタ
312
+
313
+ ps, x, y = particle_filter(ps, h, 300)
314
+
315
+
316
+
317
+ if ps is None:
318
+
319
+ continue
320
+
321
+
322
+
323
+ # 画像の範囲内にあるパーティクルのみ取り出し
324
+
325
+ ps1 = ps[(ps[:, 0] >= 0) & (ps[:, 0] < frame.shape[1]) & (ps[:, 1] >= 0) & (ps[:, 1] < frame.shape[0])]
326
+
327
+
328
+
329
+ # パーティクルを赤色で塗りつぶす
330
+
331
+ for i in range(ps1.shape[0]):
332
+
333
+ frame[int(ps1[i, 1]), int(ps1[i, 0])] = [0, 0, 200]
334
+
335
+
336
+
337
+ # パーティクルの集中部分を赤い矩形で囲む
338
+
339
+ cv2.rectangle(frame, (x - 20, y - 20), (x + 20, y + 20), (0, 0, 200), 5)
340
+
341
+
342
+
343
+ cv2.imshow('Result', frame)
344
+
345
+
124
346
 
125
347
  cap.release()
126
348
 
127
-
128
-
129
- **② パーティクルフィルタでカメラで赤い物体を赤い枠で囲み粒子で追跡するプログラム**
130
-
131
-
132
-
133
- import cv2
134
-
135
- import numpy as np
136
-
137
-
138
-
139
-
140
-
141
- __# 追跡対象の色範囲(Hueの値域)__
142
-
143
- def is_target(roi):
144
-
145
- return (roi <= 30) | (roi >= 150)
146
-
147
-
148
-
149
-
150
-
151
- __# マスクから面積最大ブロブの中心座標を算出
152
-
153
- __def max_moment_point(mask):
154
-
155
- __# ラベリング処理__
156
-
157
- label = cv2.connectedComponentsWithStats(mask)
158
-
159
- data = np.delete(label[2], 0, 0) # ブロブのデータ
160
-
161
- center = np.delete(label[3], 0, 0) # 各ブロブの中心座標
162
-
163
- moment = data[:, 4] # 各ブロブの面積
164
-
165
- max_index = np.argmax(moment) # 面積最大のインデックス
166
-
167
- return center[max_index] # 面積最大のブロブの中心座標
168
-
169
-
170
-
171
-
172
-
173
- __# パーティクルの初期化__
174
-
175
- def initialize(img, N):
176
-
177
- mask = img.copy() # 画像のコピー
178
-
179
- mask[is_target(mask) == False] = 0 # マスク画像の作成(追跡対象外の色なら画素値0)
180
-
181
- x, y = max_moment_point(mask) # マスクから面積最大ブロブの中心座標を算出
182
-
183
- w = calc_likelihood(x, y, img) # 尤度の算出
184
-
185
- ps = np.ndarray((N, 3), dtype=np.float32) # パーティクル格納用の配列を生成
186
-
187
- ps[:] = [x, y, w] # パーティクル用配列に中心座標と尤度をセット
188
-
189
- return ps
190
-
191
-
192
-
193
-
194
-
195
- __# 1.リサンプリング(前状態の重みに応じてパーティクルを再選定)
196
-
197
- __def resampling(ps):
198
-
199
- __ # 累積重みの計算
200
-
201
- __ ws = ps[:, 2].cumsum()
202
-
203
- last_w = ws[ws.shape[0] - 1]
204
-
205
- __# 新しいパーティクル用の空配列を生成__
206
-
207
- new_ps = np.empty(ps.shape)
208
-
209
- __# 前状態の重みに応じてパーティクルをリサンプリング(重みは1.0)__
210
-
211
- for i in range(ps.shape[0]):
212
-
213
- w = np.random.rand() * last_w
214
-
215
- new_ps[i] = ps[(ws > w).argmax()]
216
-
217
- new_ps[i, 2] = 1.0
218
-
219
-
220
-
221
- return new_ps
222
-
223
-
224
-
225
-
226
-
227
- __# 2.推定(パーティクルの位置)
228
-
229
- __def predict_position(ps, var=13.0):
230
-
231
- __# 分散に従ってランダムに少し位置をずらす__
232
-
233
- ps[:, 0] += np.random.randn((ps.shape[0])) * var
234
-
235
- ps[:, 1] += np.random.randn((ps.shape[0])) * var
236
-
237
-
238
-
239
-
240
-
241
- __# 尤度の算出
242
-
243
- __def calc_likelihood(x, y, img, w=30, h=30):
244
-
245
- __# 画像から座標(x,y)を中心とする幅w, 高さhの矩形領域の全画素を取得
246
-
247
- __ x1, y1 = max(0, x-w/2), max(0, y-h/2)
248
-
249
- x2, y2 = min(img.shape[1], x+w/2), min(img.shape[0], y+h/2)
250
-
251
- x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
252
-
253
- roi = img[y1:y2, x1:x2]
254
-
255
-
256
-
257
- __# 矩形領域中に含まれる追跡対象(色)の存在率を尤度として計算__
258
-
259
- count = roi[is_target(roi)].size
260
-
261
- return (float(count) / img.size) if count > 0 else 0.0001
262
-
263
-
264
-
265
- __# パーティクルの重み付け__
266
-
267
-
268
-
269
-
270
-
271
- def calc_weight(ps, img):
272
-
273
- __# 尤度に従ってパーティクルの重み付け
274
-
275
- __ for i in range(ps.shape[0]):
276
-
277
- ps[i][2] = calc_likelihood(ps[i, 0], ps[i, 1], img)
278
-
279
-
280
-
281
- __# 重みの正規化__
282
-
283
- ps[:, 2] *= ps.shape[0] / ps[:, 2].sum()
284
-
285
-
286
-
287
- __# 3.観測(全パーティクルの重み付き平均を取得)__
288
-
289
- def observer(ps, img):
290
-
291
- __# パーティクルの重み付け
292
-
293
- __ calc_weight(ps, img)
294
-
295
- __# 重み和の計算
296
-
297
- __ x = (ps[:, 0] * ps[:, 2]).sum()
298
-
299
- y = (ps[:, 1] * ps[:, 2]).sum()
300
-
301
- __# 重み付き平均を返す
302
-
303
- __ return (x, y) / ps[:, 2].sum()
304
-
305
-
306
-
307
-
308
-
309
- __# パーティクルフィルタ__
310
-
311
- def particle_filter(ps, img, N=300):
312
-
313
- __# パーティクルが無い場合__
314
-
315
- if ps is None:
316
-
317
- ps = initialize(img, N) # パーティクルを初期化
318
-
319
-
320
-
321
- ps = resampling(ps) # 1.リサンプリング
322
-
323
- predict_position(ps) # 2.推定
324
-
325
- x, y = observer(ps, img) # 3.観測
326
-
327
- return ps, int(x), int(y)
328
-
329
-
330
-
331
-
332
-
333
- def main():
334
-
335
- __# パーティクル格納用の変数__
336
-
337
- ps = None
338
-
339
-
340
-
341
- __# 動画ファイルのキャプチャ__
342
-
343
- cap = cv2.VideoCapture("C:/github/sample/python/opencv/dataset/videos/red_marker.mp4")
344
-
345
-
346
-
347
- while cv2.waitKey(30) < 0:
348
-
349
- ret, frame = cap.read()
350
-
351
- hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV_FULL)
352
-
353
- h = hsv[:, :, 0]
354
-
355
-
356
-
357
- __# S, Vを2値化(大津の手法)__
358
-
359
- ret, s = cv2.threshold(hsv[:, :, 1], 0, 255,
360
-
361
- cv2.THRESH_BINARY | cv2.THRESH_OTSU)
362
-
363
- ret, v = cv2.threshold(hsv[:, :, 2], 0, 255,
364
-
365
- cv2.THRESH_BINARY | cv2.THRESH_OTSU)
366
-
367
- h[(s == 0) | (v == 0)] = 100
368
-
369
-
370
-
371
- __# パーティクルフィルタ__
372
-
373
- ps, x, y = particle_filter(ps, h, 300)
374
-
375
-
376
-
377
- if ps is None:
378
-
379
- continue
380
-
381
-
382
-
383
- __# 画像の範囲内にあるパーティクルのみ取り出し__
384
-
385
- ps1 = ps[(ps[:, 0] >= 0) & (ps[:, 0] < frame.shape[1]) &
386
-
387
- (ps[:, 1] >= 0) & (ps[:, 1] < frame.shape[0])]
388
-
389
-
390
-
391
- __# パーティクルを赤色で塗りつぶす__
392
-
393
- for i in range(ps1.shape[0]):
394
-
395
- frame[int(ps1[i, 1]), int(ps1[i, 0])] = [0, 0, 200]
396
-
397
-
398
-
399
- __# パーティクルの集中部分を赤い矩形で囲む__
400
-
401
- cv2.rectangle(frame, (x-20, y-20), (x+20, y+20), (0, 0, 200), 5)
402
-
403
-
404
-
405
- cv2.imshow('Result', frame)
406
-
407
-
408
-
409
- cap.release()
410
-
411
349
  cv2.destroyAllWindows()
412
350
 
413
-
414
-
415
-
351
+
416
352
 
417
353
  if __name__ == "__main__":
418
354
 
419
355
  main()
420
356
 
421
-
357
+ ```
358
+
422
-
359
+ **・エラー**
360
+
361
+
362
+
363
+ count = roi[is_target(roi)].size
364
+
365
+
366
+
367
+ : index 248 is out of bounds for axis 0 with size 30
368
+
369
+
370
+
371
+
372
+
423
- 長くりまし。よろしくお願い申し上げます。
373
+ なたかお力添えの方宜しくお願い申し上げます。

1

文法の修正

2021/01/06 01:13

投稿

amos
amos

スコア5

test CHANGED
File without changes
test CHANGED
@@ -417,3 +417,7 @@
417
417
  if __name__ == "__main__":
418
418
 
419
419
  main()
420
+
421
+
422
+
423
+ 長くなりました。よろしくお願い申し上げます。