質問編集履歴

1

書式の改善

2019/07/01 01:28

投稿

ajgtwjj
ajgtwjj

スコア11

test CHANGED
File without changes
test CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
 
18
18
 
19
- 上手組み込むことができない
19
+ プログラムは起動するが、断続的にカメラの画角に動ものがある、シャッターを切るようにして静止画表示されます
20
20
 
21
21
 
22
22
 
@@ -24,8 +24,358 @@
24
24
 
25
25
  移動物体検出のプログラム
26
26
 
27
+ ```
28
+
29
+ import cv2
30
+
31
+ import numpy as np
32
+
33
+
34
+
35
+
36
+
37
+ # 追跡対象の色範囲( Hue の値域)
38
+
39
+ def is_target(roi):
40
+
41
+ return (roi <= 30) | (roi >= 150)
42
+
43
+
44
+
45
+
46
+
47
+ # マスクから面積最大ブロブの中心座標を算出
48
+
49
+ def max_moment_point(mask):
50
+
51
+ # ラベリング処理
52
+
53
+ label = cv2.connectedComponentsWithStats(mask)
54
+
55
+ data = np.delete(label[2], 0, 0) # ブロブのデータ
56
+
57
+ center = np.delete(label[3], 0, 0) # 各ブロブの中心座標
58
+
59
+ moment = data[:,4] # 各ブロブの面積
60
+
61
+ max_index = np.argmax(moment) # 面積最大のインデックス
62
+
63
+ return center[max_index] # 面積最大のブロブの中心座標
64
+
65
+
66
+
67
+
68
+
69
+ # パーティクルの初期化
70
+
71
+ def initialize(img, N):
72
+
73
+ mask = img.copy() # 画像のコピー
74
+
75
+ mask[is_target(mask) == False] = 0 # マスク画像の作成(追跡対象外の色なら画素値 0 )
76
+
77
+ x, y = max_moment_point(mask) # マスクから面積最大ブロブの中心座標を算出
78
+
79
+ w = calc_likelihood(x, y, img) # 尤度の算出
80
+
81
+ ps = np.ndarray((N, 3), dtype=np.float32) # パーティクル格納用の配列を生成
82
+
83
+ ps[:] = [x, y, w] # パーティクル用配列に中心座標と尤度をセット
84
+
85
+ return ps
86
+
87
+
88
+
89
+
90
+
91
+ # 1. リサンプリング ( 前状態の重みに応じてパーティクルを再選定 )
92
+
93
+ def resampling(ps):
94
+
95
+
96
+
97
+ # 累積重みの計算
98
+
99
+ ws = ps[:, 2].cumsum()
100
+
101
+ last_w = ws[ws.shape[0] - 1]
102
+
103
+
104
+
105
+ # 新しいパーティクル用の空配列を生成
106
+
107
+ new_ps = np.empty(ps.shape)
108
+
109
+
110
+
111
+ # 前状態の重みに応じてパーティクルをリサンプリング(重みは 1.0 )
112
+
113
+ for i in range(ps.shape[0]):
114
+
115
+ w = np.random.rand() * last_w
116
+
117
+ new_ps[i] = ps[(ws > w).argmax()]
118
+
119
+ new_ps[i, 2] = 1.0
120
+
121
+ return new_ps
122
+
123
+
124
+
125
+
126
+
127
+ # 2. 推定(パーティクルの位置)
128
+
129
+ def predict_position(ps, var=13.0):
130
+
131
+ # 分散に従ってランダムに少し位置をずらす
132
+
133
+ ps[:, 0] += np.random.randn((ps.shape[0])) * var
134
+
135
+ ps[:, 1] += np.random.randn((ps.shape[0])) * var
136
+
137
+
138
+
139
+
140
+
141
+ # 尤度の算出
142
+
143
+ def calc_likelihood(x, y, img, w=30, h=30):
144
+
145
+
146
+
147
+ # 画像から座標 (x,y) を中心とする幅
148
+
149
+ x1, y1 = max(0, x-w/2), max(0, y-h/2)
150
+
151
+ x2, y2 = min(img.shape[1], x+w/2), min(img.shape[0], y+h/2)
152
+
153
+ x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
154
+
155
+ roi = img[y1:y2, x1:x2]
156
+
157
+
158
+
159
+ # 矩形領域中に含まれる追跡対象 ( 色 ) の存在率を尤度として計算
160
+
161
+ count = roi[is_target(roi)].size
162
+
163
+ return (float(count) / img.size) if count > 0 else 0.0001
164
+
165
+
166
+
167
+
168
+
169
+ # パーティクルの重み付け
170
+
171
+ def calc_weight(ps, img):
172
+
173
+
174
+
175
+ # 尤度に従ってパーティクルの重み付け
176
+
177
+ for i in range(ps.shape[0]):
178
+
179
+ ps[i][2] = calc_likelihood(ps[i, 0], ps[i, 1], img)
180
+
181
+
182
+
183
+ # 重みの正規化
184
+
185
+ ps[:, 2] *= ps.shape[0] / ps[:, 2].sum()
186
+
187
+
188
+
189
+
190
+
191
+ # 3. 観測(全パーティクルの重み付き平均を取得)
192
+
193
+ def observer(ps, img):
194
+
195
+ # パーティクルの重み付け
196
+
197
+ calc_weight(ps, img)
198
+
199
+
200
+
201
+ # 重み和の計算
202
+
203
+ x = (ps[:, 0] * ps[:, 2]).sum()
204
+
205
+ y = (ps[:, 1] * ps[:, 2]).sum()
206
+
207
+
208
+
209
+ # 重み付き平均を返す
210
+
211
+ return (x, y) / ps[:, 2].sum()
212
+
213
+
214
+
215
+
216
+
217
+ # 「パーティクル・フィルタ」
218
+
219
+ def particle_filter(ps, img, N=300):
220
+
221
+ # パーティクルが無い場合
222
+
223
+ if ps is None:
224
+
225
+ ps = initialize(img, N) # パーティクルを初期化
226
+
227
+
228
+
229
+ ps = resampling(ps) # 1. リサンプリング
230
+
231
+ predict_position(ps) # 2. 推定
232
+
233
+ x, y = observer(ps, img) # 3. 観測
234
+
235
+ return ps, int(x), int(y)
236
+
237
+
238
+
239
+
240
+
241
+ def main():
242
+
243
+
244
+
245
+ # 動画のキャプチャ
246
+
247
+ cap = cv2.VideoCapture("input1.mp4")
248
+
249
+ ps = None
250
+
251
+
252
+
253
+ while(cap.isOpened()):
254
+
255
+
256
+
257
+ ret, frame = cap.read()
258
+
259
+ hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV_FULL)
260
+
261
+ h = hsv[:, :, 0]
262
+
263
+
264
+
265
+ # S, V を 2 値化(大津の手法)
266
+
267
+ ret, s = cv2.threshold(hsv[:, :, 1], 0, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
268
+
269
+ ret, v = cv2.threshold(hsv[:, :, 2], 0, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
270
+
271
+ h[(s == 0) | (v == 0)] = 100
272
+
273
+
274
+
275
+ # 「パーティクル・フィルタ」
276
+
277
+ ps, x, y = particle_filter(ps, h, 300)
278
+
279
+
280
+
281
+ if ps is None:
282
+
283
+ continue
284
+
285
+
286
+
287
+ # 画像の範囲内にあるパーティクルのみ取り出し
288
+
289
+ ps1 = ps[(ps[:, 0] >= 0) & (ps[:, 0] < frame.shape[1]) &
290
+
291
+ (ps[:, 1] >= 0) & (ps[:, 1] < frame.shape[0])]
292
+
293
+
294
+
295
+ # パーティクルを赤色で塗りつぶす
296
+
297
+ for i in range(ps1.shape[0]):
298
+
299
+ frame[int(ps1[i, 1]), int(ps1[i, 0])] = [0, 0, 200]
300
+
301
+
302
+
303
+ # パーティクルの集中部分を赤い矩形で囲む
304
+
305
+ cv2.rectangle(frame, (x-20, y-20), (x+20, y+20), (0, 0, 200), 5)
306
+
307
+ cv2.imshow('Result', frame)
308
+
309
+
310
+
311
+ # q キーが押されたら終了
312
+
313
+ if cv2.waitKey(25) & 0xFF == ord('q'):
314
+
315
+ break
316
+
317
+
318
+
319
+ cap.release()
320
+
321
+ cv2.destroyAllWindows()
322
+
323
+
324
+
325
+
326
+
327
+ if __name__ == "__main__":
328
+
329
+ main()
330
+
331
+ ```
332
+
333
+ カメラから動画を取得するプログラム
334
+
27
335
  ```import cv2
28
336
 
337
+
338
+
339
+ # VideoCapture オブジェクトを取得します
340
+
341
+ capture = cv2.VideoCapture(0)
342
+
343
+
344
+
345
+ while(True):
346
+
347
+ ret, frame = capture.read()
348
+
349
+ cv2.imshow('frame',frame)
350
+
351
+ if cv2.waitKey(1) & 0xFF == ord('q'):
352
+
353
+ break
354
+
355
+
356
+
357
+ capture.release()
358
+
359
+ cv2.destroyAllWindows()
360
+
361
+ ```
362
+
363
+
364
+
365
+ ### 試したこと
366
+
367
+  各プログラムはそれぞれ、問題なく動くのを確認済みです。
368
+
369
+
370
+
371
+ 前者のプログラムの#動画のキャプチャ を後者のプログラムに差し替えました。
372
+
373
+
374
+
375
+ ```
376
+
377
+ import cv2
378
+
29
379
  import numpy as np
30
380
 
31
381
 
@@ -38,9 +388,9 @@
38
388
 
39
389
  return (roi <= 30) | (roi >= 150)
40
390
 
41
-
42
-
43
-
391
+
392
+
393
+
44
394
 
45
395
  # マスクから面積最大ブロブの中心座標を算出
46
396
 
@@ -60,9 +410,9 @@
60
410
 
61
411
  return center[max_index] # 面積最大のブロブの中心座標
62
412
 
63
-
64
-
65
-
413
+
414
+
415
+
66
416
 
67
417
  # パーティクルの初期化
68
418
 
@@ -82,9 +432,9 @@
82
432
 
83
433
  return ps
84
434
 
85
-
86
-
87
-
435
+
436
+
437
+
88
438
 
89
439
  # 1. リサンプリング ( 前状態の重みに応じてパーティクルを再選定 )
90
440
 
@@ -98,13 +448,13 @@
98
448
 
99
449
  last_w = ws[ws.shape[0] - 1]
100
450
 
101
-
451
+
102
452
 
103
453
  # 新しいパーティクル用の空配列を生成
104
454
 
105
455
  new_ps = np.empty(ps.shape)
106
456
 
107
-
457
+
108
458
 
109
459
  # 前状態の重みに応じてパーティクルをリサンプリング(重みは 1.0 )
110
460
 
@@ -118,9 +468,9 @@
118
468
 
119
469
  return new_ps
120
470
 
121
-
122
-
123
-
471
+
472
+
473
+
124
474
 
125
475
  # 2. 推定(パーティクルの位置)
126
476
 
@@ -132,9 +482,9 @@
132
482
 
133
483
  ps[:, 1] += np.random.randn((ps.shape[0])) * var
134
484
 
135
-
136
-
137
-
485
+
486
+
487
+
138
488
 
139
489
  # 尤度の算出
140
490
 
@@ -152,7 +502,7 @@
152
502
 
153
503
  roi = img[y1:y2, x1:x2]
154
504
 
155
-
505
+
156
506
 
157
507
  # 矩形領域中に含まれる追跡対象 ( 色 ) の存在率を尤度として計算
158
508
 
@@ -160,9 +510,9 @@
160
510
 
161
511
  return (float(count) / img.size) if count > 0 else 0.0001
162
512
 
163
-
164
-
165
-
513
+
514
+
515
+
166
516
 
167
517
  # パーティクルの重み付け
168
518
 
@@ -176,15 +526,15 @@
176
526
 
177
527
  ps[i][2] = calc_likelihood(ps[i, 0], ps[i, 1], img)
178
528
 
179
-
529
+
180
530
 
181
531
  # 重みの正規化
182
532
 
183
533
  ps[:, 2] *= ps.shape[0] / ps[:, 2].sum()
184
534
 
185
-
186
-
187
-
535
+
536
+
537
+
188
538
 
189
539
  # 3. 観測(全パーティクルの重み付き平均を取得)
190
540
 
@@ -194,7 +544,7 @@
194
544
 
195
545
  calc_weight(ps, img)
196
546
 
197
-
547
+
198
548
 
199
549
  # 重み和の計算
200
550
 
@@ -202,15 +552,15 @@
202
552
 
203
553
  y = (ps[:, 1] * ps[:, 2]).sum()
204
554
 
205
-
555
+
206
556
 
207
557
  # 重み付き平均を返す
208
558
 
209
559
  return (x, y) / ps[:, 2].sum()
210
560
 
211
-
212
-
213
-
561
+
562
+
563
+
214
564
 
215
565
  # 「パーティクル・フィルタ」
216
566
 
@@ -222,7 +572,7 @@
222
572
 
223
573
  ps = initialize(img, N) # パーティクルを初期化
224
574
 
225
-
575
+
226
576
 
227
577
  ps = resampling(ps) # 1. リサンプリング
228
578
 
@@ -232,9 +582,9 @@
232
582
 
233
583
  return ps, int(x), int(y)
234
584
 
235
-
236
-
237
-
585
+
586
+
587
+
238
588
 
239
589
  def main():
240
590
 
@@ -242,23 +592,45 @@
242
592
 
243
593
  # 動画のキャプチャ
244
594
 
595
+ # VideoCapture オブジェクトを取得します
596
+
597
+ import cv2
598
+
599
+
600
+
245
- cap = cv2.VideoCapture("input1.mp4")
601
+ capture = cv2.VideoCapture(0)
602
+
603
+
604
+
605
+ ret, frame = cv2.VideoCapture(0).read()
606
+
607
+ cv2.imshow('frame',frame)
608
+
609
+ if cv2.waitKey(1) & 0xFF == ord('q'):
610
+
611
+
612
+
613
+
614
+
615
+ cv2.VideoCapture(0).release()
616
+
617
+ cv2.destroyAllWindows()
246
618
 
247
619
  ps = None
248
620
 
249
-
250
-
621
+
622
+
251
- while(cap.isOpened()):
623
+ while(cv2.VideoCapture(0).isOpened()):
252
-
253
-
254
-
624
+
625
+
626
+
255
- ret, frame = cap.read()
627
+ ret, frame = cv2.VideoCapture(0).read()
256
628
 
257
629
  hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV_FULL)
258
630
 
259
631
  h = hsv[:, :, 0]
260
632
 
261
-
633
+
262
634
 
263
635
  # S, V を 2 値化(大津の手法)
264
636
 
@@ -268,19 +640,19 @@
268
640
 
269
641
  h[(s == 0) | (v == 0)] = 100
270
642
 
271
-
643
+
272
644
 
273
645
  # 「パーティクル・フィルタ」
274
646
 
275
647
  ps, x, y = particle_filter(ps, h, 300)
276
648
 
277
-
649
+
278
650
 
279
651
  if ps is None:
280
652
 
281
653
  continue
282
654
 
283
-
655
+
284
656
 
285
657
  # 画像の範囲内にあるパーティクルのみ取り出し
286
658
 
@@ -288,7 +660,7 @@
288
660
 
289
661
  (ps[:, 1] >= 0) & (ps[:, 1] < frame.shape[0])]
290
662
 
291
-
663
+
292
664
 
293
665
  # パーティクルを赤色で塗りつぶす
294
666
 
@@ -296,7 +668,7 @@
296
668
 
297
669
  frame[int(ps1[i, 1]), int(ps1[i, 0])] = [0, 0, 200]
298
670
 
299
-
671
+
300
672
 
301
673
  # パーティクルの集中部分を赤い矩形で囲む
302
674
 
@@ -304,7 +676,7 @@
304
676
 
305
677
  cv2.imshow('Result', frame)
306
678
 
307
-
679
+
308
680
 
309
681
  # q キーが押されたら終了
310
682
 
@@ -312,62 +684,24 @@
312
684
 
313
685
  break
314
686
 
315
-
316
-
687
+
688
+
317
- cap.release()
689
+ cv2.VideoCapture(0).release()
318
690
 
319
691
  cv2.destroyAllWindows()
320
692
 
321
-
322
-
323
-
693
+
694
+
695
+
324
696
 
325
697
  if __name__ == "__main__":
326
698
 
327
699
  main()
328
700
 
701
+
702
+
329
703
  ```
330
704
 
331
- カメラから動画を取得するプログラム
332
-
333
- ```import cv2
334
-
335
-
336
-
337
- # VideoCapture オブジェクトを取得します
338
-
339
- capture = cv2.VideoCapture(0)
340
-
341
-
342
-
343
- while(True):
344
-
345
- ret, frame = capture.read()
346
-
347
- cv2.imshow('frame',frame)
348
-
349
- if cv2.waitKey(1) & 0xFF == ord('q'):
350
-
351
- break
352
-
353
-
354
-
355
- capture.release()
356
-
357
- cv2.destroyAllWindows()
358
-
359
- ```
360
-
361
-
362
-
363
- ### 試したこと
364
-
365
- 移動物体検出のプログラムのline 110 # 動画のキャプチャ 以降の部分を、後者のプログラムに差し替えて行ってみましたが、うまくいきません。
366
-
367
-
368
-
369
- また、各プログラムはそれぞれ、問題なく動くのを確認済みです。
370
-
371
705
 
372
706
 
373
707
  ### 補足情報(FW/ツールのバージョンなど)
@@ -388,6 +722,16 @@
388
722
 
389
723
  ###教えてほしいこと
390
724
 
391
- 移動物体検出のプログラムのファイルから動画をインポートする部分を、カメラから取得した動画データに変えて、リアルタイムで移動体検出をしたい
725
+ 移動物体検出のプログラムのファイルから動画をインポートする部分を、カメラから取得した動画データに変えて、リアルタイムで移動体検出をしたいです。
726
+
727
+
728
+
392
-
729
+ 試したコードだと、断続的過ぎてしまいます、処理したい環境は自動車の交通の流れを上から見るようなものを、想定しており 現在は天井に設置したカメラからラジコンの車のような物を検出しようとしています。
730
+
731
+
732
+
733
+ なので、カメラからの映像がそのまま流れ、その中で移動体を常に検出し、追跡できるプログラムを目指しております。
734
+
393
- よろしければ、実現するめの方法や成功した際のコーなどを教授願います。
735
+ このプログラムを改良すれば可能でしょうか? また、何かアバイスはいませんか?
736
+
737
+ よろしくお願いします。。。