質問編集履歴

5

リンク内容の変更

2018/09/13 12:10

投稿

snake207
snake207

スコア13

test CHANGED
File without changes
test CHANGED
@@ -330,7 +330,7 @@
330
330
 
331
331
  ### マウスで領域選択(元のプログラム)
332
332
 
333
- [リンク内容](https://teratail.com/users/snake207/Question)
333
+ [リンク内容](https://teratail.com/questions/142436)
334
334
 
335
335
 
336
336
 

4

作成プログラムの改善と新たなエラーの追記

2018/09/13 12:10

投稿

snake207
snake207

スコア13

test CHANGED
File without changes
test CHANGED
@@ -2,29 +2,349 @@
2
2
 
3
3
  動画からボールの軌道を抽出するプログラムと
4
4
 
5
- 動画にマウスで領域の4隅を選択すると線が引かれて領域を囲むプログラムを作成した。
5
+ 動画にマウスで領域の4隅を選択すると線が引かれて領域を囲む
6
+
6
-
7
+ プログラムを作成した。
8
+
7
- この2つのプログラムを組み合わせ、領域を選択してからボールの軌道を抽出するプログラムを作成したい。
9
+ この2つのプログラムを組み合わせ、領域を選択してからボールの軌道を抽出する
10
+
8
-
11
+ プログラムを作成したい。
12
+
9
- ###実行結果
13
+ ### 発生したエラー
14
+
10
-
15
+ Traceback (most recent call last):
16
+
17
+ File "test.py",line 141, in <module>
18
+
19
+ plist.run()
20
+
11
- 作成した2つのプログラムを1つにまとめたのですが、何も画面に表示されなかった。
21
+ File "test.py",line 100, in run
22
+
23
+ color_diff = cv2.absdiff(self.frame_next, self.frame_pre)   #フレーム間の差分
24
+
25
+ AttributeError: 'PointList' object has no attribute 'frame_next'
12
26
 
13
27
  ```Python
14
28
 
15
29
  # -*- coding: utf-8 -*-
16
30
 
31
+ import cv2
32
+
33
+ import sys
34
+
17
35
  import numpy as np
18
36
 
37
+
38
+
39
+
40
+
41
+ VIDEO_DATE = "/home/pi/テニスコート撮影/tennis.AVI"
42
+
43
+ WINDOW_NAME = "MouseEvent"
44
+
45
+
46
+
47
+ def dilation(dilationSize, kernelSize, img): # 膨張した画像にして返す
48
+
49
+ kernel = np.ones((kernelSize, kernelSize), np.uint8)
50
+
51
+ element = cv2.getStructuringElement(
52
+
53
+ cv2.MORPH_RECT, (2 * dilationSize + 1, 2 * dilationSize + 1), (dilationSize, dilationSize))
54
+
55
+ dilation_img = cv2.dilate(img, kernel, element)
56
+
57
+ return dilation_img
58
+
59
+
60
+
61
+
62
+
63
+ def detect(gray_diff, thresh_diff=95, dilationSize=9, kernelSize=20): # 一定面積以上の物体を検出
64
+
65
+ retval, black_diff = cv2.threshold(
66
+
67
+ gray_diff, thresh_diff, 255, cv2.THRESH_BINARY) # 2値化
68
+
69
+ dilation_img = dilation(dilationSize, kernelSize, black_diff) # 膨張処理
70
+
71
+ img = dilation_img.copy()
72
+
73
+ image, contours, hierarchy = cv2.findContours(
74
+
75
+ dilation_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 境界線検出
76
+
77
+
78
+
79
+ ball_pos = []
80
+
81
+
82
+
83
+ for i in range(len(contours)): # 重心位置を計算
84
+
85
+ count = len(contours[i])
86
+
87
+ area = cv2.contourArea(contours[i]) # 面積計算
88
+
89
+ x, y = 0.0, 0.0
90
+
91
+ for j in range(count):
92
+
93
+ x += contours[i][j][0][0]
94
+
95
+ y += contours[i][j][0][1]
96
+
97
+
98
+
99
+ x /= count
100
+
101
+ y /= count
102
+
103
+ x = int(x)
104
+
105
+ y = int(y)
106
+
107
+ ball_pos.append([x, y])
108
+
109
+
110
+
111
+ return ball_pos, img
112
+
113
+
114
+
115
+
116
+
117
+ def displayCircle(image, ballList, thickness=5):
118
+
119
+ for i in range(len(ballList)):
120
+
121
+ x = int(ballList[i][0])
122
+
123
+ y = int(ballList[i][1])
124
+
125
+ cv2.circle(image, (x, y), 10, (0, 0, 255), thickness)
126
+
127
+ return image
128
+
129
+
130
+
131
+
132
+
133
+ def resizeImage(image, w=2, h=2):
134
+
135
+ height = image.shape[0]
136
+
137
+ width = image.shape[1]
138
+
139
+ resizedImage = cv2.resize(image, (int(width / w), int(height / h)))
140
+
141
+ return resizedImage
142
+
143
+
144
+
145
+
146
+
147
+ def blackToColor(bImage):
148
+
149
+ colorImage = np.array((bImage, bImage, bImage))
150
+
151
+ colorImage = colorImage.transpose(1, 2, 0)
152
+
153
+ return colorImage
154
+
155
+
156
+
157
+ class PointList():
158
+
159
+ def __init__(self, npoints):
160
+
161
+ self.video = cv2.VideoCapture(VIDEO_DATE)
162
+
163
+ self.frame = None
164
+
165
+ self.npoints = npoints
166
+
167
+ self.ptlist = np.empty((npoints, 2), dtype=int)
168
+
169
+ self.pos = 0
170
+
171
+ cv2.setMouseCallback(WINDOW_NAME, self.onMouse)
172
+
173
+
174
+
175
+ def add(self, x, y):
176
+
177
+ if self.pos < self.npoints:
178
+
179
+ self.ptlist[self.pos, :] = [x, y]
180
+
181
+ self.pos += 1
182
+
183
+ return True
184
+
185
+ return False
186
+
187
+
188
+
189
+ def run(self):
190
+
191
+ while(self.video.isOpened()):
192
+
193
+ end_flag, self.frame = self.video.read()
194
+
195
+ if not end_flag: # EOF
196
+
197
+ break
198
+
199
+ self.frame_pre = self.frame.copy()
200
+
201
+
202
+
203
+ if(self.pos == self.npoints):
204
+
205
+ # コメントアウト
206
+
207
+ #print(self.ptlist)
208
+
209
+ cv2.line(self.frame, (self.ptlist[0][0], self.ptlist[0][1]),
210
+
211
+ (self.ptlist[1][0], self.ptlist[1][1]), (0, 255, 0), 3)
212
+
213
+ cv2.line(self.frame, (self.ptlist[1][0], self.ptlist[1][1]),
214
+
215
+ (self.ptlist[2][0], self.ptlist[2][1]), (0, 255, 0), 3)
216
+
217
+ cv2.line(self.frame, (self.ptlist[2][0], self.ptlist[2][1]),
218
+
219
+ (self.ptlist[3][0], self.ptlist[3][1]), (0, 255, 0), 3)
220
+
221
+ cv2.line(self.frame, (self.ptlist[3][0], self.ptlist[3][1]),
222
+
223
+ (self.ptlist[0][0], self.ptlist[0][1]), (0, 255, 0), 3)
224
+
225
+
226
+
227
+ color_diff = cv2.absdiff(self.frame_next, self.frame_pre) # フレーム間の差分計算
228
+
229
+ gray_diff = cv2.cvtColor(color_diff, cv2.COLOR_BGR2GRAY) # グレースケール変換
230
+
231
+ retval, black_diff = cv2.threshold(gray_diff,30, 255, cv2.THRESH_BINARY)
232
+
233
+
234
+
235
+ ball, dilation_img = detect(gray_diff)
236
+
237
+
238
+
239
+ self.frame = displayCircle(self.frame, ball, 2) # 丸で加工
240
+
241
+ cImage = blackToColor(dilation_img) # 2値化画像をカラーの配列サイズと同じにする
242
+
243
+ im1 = resizeImage(frame, 2, 2)
244
+
245
+ im2 = resizeImage(cImage, 2, 2)
246
+
247
+ im_h = cv2.hconcat([im1, im2]) # 画像を横方向に連結
248
+
249
+
250
+
251
+ cv2.imshow("Tracking", im_h) # フレームを画面表示
252
+
253
+ out.write(im_h)
254
+
255
+
256
+
257
+ self.frame_pre = self.frame_next.copy() # 次のフレームの読み込み
258
+
259
+
260
+
261
+ cv2.imshow(WINDOW_NAME, self.frame)
262
+
263
+ if cv2.waitKey(10) ==27: # Escキーで抜ける
264
+
265
+ break
266
+
267
+
268
+
269
+ def onMouse(self,event, x, y, flag, params):
270
+
271
+ if event == cv2.EVENT_MOUSEMOVE: # マウスが移動したときにx線とy線を更新する
272
+
273
+ self.frame2 = np.copy(self.frame)
274
+
275
+ h, w = self.frame2.shape[0], self.frame2.shape[1]
276
+
277
+ cv2.line(self.frame2, (x, 0), (x, h - 1), (255, 0, 0))
278
+
279
+ cv2.line(self.frame2, (0, y), (w - 1, y), (255, 0, 0))
280
+
281
+ cv2.imshow(WINDOW_NAME, self.frame2)
282
+
283
+
284
+
285
+ if event == cv2.EVENT_LBUTTONDOWN: # レフトボタンをクリックしたとき、ptlist配列にx,y座標を格納する
286
+
287
+ if self.add(x, y):
288
+
289
+ print('[%d] ( %d, %d )' % (ptlist.pos - 1, x, y))
290
+
291
+ cv2.circle(self.frame, (x, y), 3, (0, 0, 255), 3)
292
+
293
+ cv2.imshow(WINDOW_NAME, self.frame)
294
+
295
+ else:
296
+
297
+ print('All points have selected. Press ESC-key.')
298
+
299
+
300
+
301
+ if __name__ == '__main__':
302
+
303
+ cv2.namedWindow(WINDOW_NAME)
304
+
305
+ npoints = 4
306
+
307
+ ptlist = PointList(npoints)
308
+
309
+ ptlist.run()
310
+
311
+
312
+
313
+ ```
314
+
315
+
316
+
317
+ ### 質問内容
318
+
319
+ ・エラーの原因は何なのか?
320
+
321
+ ・元の2つのプログラムを組み合わせるにはどうしたらいいか?
322
+
323
+
324
+
325
+ 下記にプログラム作成に参考したプログラムとサイトページのリンクを載せます。
326
+
327
+ 回答の参考にしてください。
328
+
329
+
330
+
331
+ ### マウスで領域選択(元のプログラム)
332
+
333
+ [リンク内容](https://teratail.com/users/snake207/Question)
334
+
335
+
336
+
337
+ ### ボール軌道抽出(元のプログラム)
338
+
339
+ ```Python
340
+
19
341
  import cv2
20
342
 
21
-
22
-
23
-
24
-
25
- VIDEO_DATE = 'tennis.AVI'
343
+ import sys
26
-
344
+
27
- WINDOW_NAME = "MouseEvent"
345
+ import numpy as np
346
+
347
+
28
348
 
29
349
 
30
350
 
@@ -138,390 +458,122 @@
138
458
 
139
459
 
140
460
 
141
- class PointList():
142
-
143
- def __init__(self, npoints):
144
-
145
- self.video = cv2.VideoCapture(VIDEO_DATE)
146
-
147
- self.frame = None
148
-
149
- self.npoints = npoints
150
-
151
- self.ptlist = np.empty((npoints, 2), dtype=int)
152
-
153
- self.pos = 0
154
-
155
- cv2.setMouseCallback(WINDOW_NAME, self.onMouse)
156
-
157
-
158
-
159
- def add(self, x, y):
160
-
161
- if self.pos < self.npoints:
162
-
163
- self.ptlist[self.pos, :] = [x, y]
164
-
165
- self.pos += 1
166
-
167
- return True
168
-
169
- return False
170
-
171
-
172
-
173
- def run(self):
174
-
175
- while(self.video.isOpened()):
176
-
177
- end_flag, self.frame = self.video.read()
178
-
179
- if not end_flag: # EOF
180
-
181
- break
182
-
183
- if(self.pos == self.npoints):
184
-
185
- # コメントアウト
186
-
187
- #print(self.ptlist)
188
-
189
- cv2.line(self.frame, (self.ptlist[0][0], self.ptlist[0][1]),
190
-
191
- (self.ptlist[1][0], self.ptlist[1][1]), (0, 255, 0), 3)
192
-
193
- cv2.line(self.frame, (self.ptlist[1][0], self.ptlist[1][1]),
194
-
195
- (self.ptlist[2][0], self.ptlist[2][1]), (0, 255, 0), 3)
196
-
197
- cv2.line(self.frame, (self.ptlist[2][0], self.ptlist[2][1]),
198
-
199
- (self.ptlist[3][0], self.ptlist[3][1]), (0, 255, 0), 3)
200
-
201
- cv2.line(self.frame, (self.ptlist[3][0], self.ptlist[3][1]),
202
-
203
- (self.ptlist[0][0], self.ptlist[0][1]), (0, 255, 0), 3)
204
-
205
- color_diff = cv2.absdiff(frame_next, frame_pre) # フレーム間の差分計算
206
-
207
- gray_diff = cv2.cvtColor(color_diff, cv2.COLOR_BGR2GRAY) # グレースケール変換
208
-
209
- retval, black_diff = cv2.threshold(gray_diff, 30, 255, cv2.THRESH_BINARY)
210
-
211
-
212
-
213
- ball, dilation_img = detect(gray_diff)
214
-
215
-
216
-
217
- self.frame = displayCircle(self.frame, ball, 2) # 丸で加工
218
-
219
- cImage = blackToColor(dilation_img) # 2値化画像をカラーの配列サイズと同じする
220
-
221
- im1 = resizeImage(selg.frame, 2, 2)
222
-
223
- im2 = resizeImage(cImage, 2, 2)
224
-
225
- im_h = cv2.hconcat([im1, im2]) # 画像を横方向に連結
226
-
227
-
228
-
229
- cv2.imshow("Tracking", im_h) # フレームを画面表示
230
-
231
- out.write(im_h)
232
-
233
-
234
-
235
- cv2.imshow(WINDOW_NAME, self.frame)
236
-
237
- if cv2.waitKey(10) ==27: # Escキーで抜ける
238
-
239
- break
240
-
241
-
242
-
243
- def onMouse(self,event, x, y, flag, params):
244
-
245
- if event == cv2.EVENT_MOUSEMOVE: # マウスが移動したときにx線とy線を更新する
246
-
247
- self.frame2 = np.copy(self.frame)
248
-
249
- h, w = self.frame2.shape[0], self.frame2.shape[1]
250
-
251
- cv2.line(self.frame2, (x, 0), (x, h - 1), (255, 0, 0))
252
-
253
- cv2.line(self.frame2, (0, y), (w - 1, y), (255, 0, 0))
254
-
255
- cv2.imshow(WINDOW_NAME, self.frame2)
461
+
462
+
463
+ def run(input_video_path, output_video_path):
464
+
465
+ video = cv2.VideoCapture(input_video_path) # videoファイルを読み込む
466
+
467
+ # fourcc = cv2.VideoWriter_fourcc(*'MJPG')
468
+
469
+ fourcc = cv2.VideoWriter_fourcc(*'XVID')
470
+
471
+
472
+
473
+ if not video.isOpened(): # ファイルがオープンできない場合の処理.
474
+
475
+ print("Could not open video")
476
+
477
+ sys.exit()
478
+
479
+
480
+
481
+ vidw = video.get(cv2.CAP_PROP_FRAME_WIDTH)
482
+
483
+ vidh = video.get(cv2.CAP_PROP_FRAME_HEIGHT)
484
+
485
+ out = cv2.VideoWriter(output_video_path, fourcc, 20.0,
486
+
487
+ (int(vidw), int(vidh))) # 出力先のファイルを開く
488
+
489
+
490
+
491
+ ok, frame = video.read() # 最初のフレームを読み込む
492
+
493
+ if not ok:
494
+
495
+ print('Cannot read video file')
496
+
497
+ sys.exit()
498
+
499
+
500
+
501
+ frame_pre = frame.copy()
502
+
503
+
504
+
505
+ while True:
506
+
507
+ ok, frame = video.read() # フレームを読み込む
508
+
509
+ if not ok:
510
+
511
+ break
512
+
513
+ frame_next = frame.copy()
514
+
515
+
516
+
517
+ color_diff = cv2.absdiff(frame_next, frame_pre) # フレーム間の差分計算
518
+
519
+ gray_diff = cv2.cvtColor(color_diff, cv2.COLOR_BGR2GRAY) # グレースケール変換
520
+
521
+ retval, black_diff = cv2.threshold(
522
+
523
+ gray_diff, 30, 255, cv2.THRESH_BINARY)
524
+
525
+
526
+
527
+ ball, dilation_img = detect(gray_diff)
528
+
529
+
530
+
531
+ frame = displayCircle(frame, ball, 2) # 丸で加工
532
+
533
+ cImage = blackToColor(dilation_img) # 2値化画像をカラーの配列サイズと同じにする
534
+
535
+ im1 = resizeImage(frame, 2, 2)
536
+
537
+ im2 = resizeImage(cImage, 2, 2)
538
+
539
+ im_h = cv2.hconcat([im1, im2]) # 画像を横方向連結
540
+
541
+
542
+
543
+ cv2.imshow("Tracking", im_h) # フレームを画面表示
544
+
545
+ out.write(im_h)
546
+
547
+
548
+
549
+ frame_pre = frame_next.copy() # 次のフレームの読み込み
550
+
551
+
552
+
553
+ k = cv2.waitKey(1) & 0xff # ESCを押したら中止
554
+
555
+ if k == 27:
556
+
557
+ break
558
+
559
+
560
+
561
+ video.release()
562
+
563
+ out.release()
564
+
565
+ cv2.destroyAllWindows()
566
+
567
+
568
+
569
+
256
570
 
257
571
  if __name__ == '__main__':
258
572
 
259
- cv2.namedWindow(WINDOW_NAME)
260
-
261
- npoints = 4
262
-
263
- ptlist = PointList(npoints)
573
+ inputFile="tennis.avi"
264
-
574
+
265
- ptlist.run()
575
+ outputFile="output.mp4"
266
-
576
+
267
- cv2.destroyAllWindows()
577
+ run(inputFile, outputFile)
268
578
 
269
579
  ```
270
-
271
-
272
-
273
- ### 質問内容
274
-
275
- ・元の2つのプログラムを組み合わせるにはどうしたらいいか?
276
-
277
- 下記に1つにまとめたプログラムの元のプログラムである2つのプログラムも載せておきます。
278
-
279
- 回答の参考にしてください。
280
-
281
- ### ボール軌道抽出(元のプログラム)
282
-
283
- ```Python
284
-
285
- import cv2
286
-
287
- import sys
288
-
289
- import numpy as np
290
-
291
-
292
-
293
-
294
-
295
- def dilation(dilationSize, kernelSize, img): # 膨張した画像にして返す
296
-
297
- kernel = np.ones((kernelSize, kernelSize), np.uint8)
298
-
299
- element = cv2.getStructuringElement(
300
-
301
- cv2.MORPH_RECT, (2 * dilationSize + 1, 2 * dilationSize + 1), (dilationSize, dilationSize))
302
-
303
- dilation_img = cv2.dilate(img, kernel, element)
304
-
305
- return dilation_img
306
-
307
-
308
-
309
-
310
-
311
- def detect(gray_diff, thresh_diff=30, dilationSize=9, kernelSize=20): # 一定面積以上の物体を検出
312
-
313
- retval, black_diff = cv2.threshold(
314
-
315
- gray_diff, thresh_diff, 255, cv2.THRESH_BINARY) # 2値化
316
-
317
- dilation_img = dilation(dilationSize, kernelSize, black_diff) # 膨張処理
318
-
319
- img = dilation_img.copy()
320
-
321
- image, contours, hierarchy = cv2.findContours(
322
-
323
- dilation_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 境界線検出
324
-
325
-
326
-
327
- ball_pos = []
328
-
329
-
330
-
331
- for i in range(len(contours)): # 重心位置を計算
332
-
333
- count = len(contours[i])
334
-
335
- area = cv2.contourArea(contours[i]) # 面積計算
336
-
337
- x, y = 0.0, 0.0
338
-
339
- for j in range(count):
340
-
341
- x += contours[i][j][0][0]
342
-
343
- y += contours[i][j][0][1]
344
-
345
-
346
-
347
- x /= count
348
-
349
- y /= count
350
-
351
- x = int(x)
352
-
353
- y = int(y)
354
-
355
- ball_pos.append([x, y])
356
-
357
-
358
-
359
- return ball_pos, img
360
-
361
-
362
-
363
-
364
-
365
- def displayCircle(image, ballList, thickness=5):
366
-
367
- for i in range(len(ballList)):
368
-
369
- x = int(ballList[i][0])
370
-
371
- y = int(ballList[i][1])
372
-
373
- cv2.circle(image, (x, y), 10, (0, 0, 255), thickness)
374
-
375
- return image
376
-
377
-
378
-
379
-
380
-
381
- def resizeImage(image, w=2, h=2):
382
-
383
- height = image.shape[0]
384
-
385
- width = image.shape[1]
386
-
387
- resizedImage = cv2.resize(image, (int(width / w), int(height / h)))
388
-
389
- return resizedImage
390
-
391
-
392
-
393
-
394
-
395
- def blackToColor(bImage):
396
-
397
- colorImage = np.array((bImage, bImage, bImage))
398
-
399
- colorImage = colorImage.transpose(1, 2, 0)
400
-
401
- return colorImage
402
-
403
-
404
-
405
-
406
-
407
- def run(input_video_path, output_video_path):
408
-
409
- video = cv2.VideoCapture(input_video_path) # videoファイルを読み込む
410
-
411
- # fourcc = cv2.VideoWriter_fourcc(*'MJPG')
412
-
413
- fourcc = cv2.VideoWriter_fourcc(*'XVID')
414
-
415
-
416
-
417
- if not video.isOpened(): # ファイルがオープンできない場合の処理.
418
-
419
- print("Could not open video")
420
-
421
- sys.exit()
422
-
423
-
424
-
425
- vidw = video.get(cv2.CAP_PROP_FRAME_WIDTH)
426
-
427
- vidh = video.get(cv2.CAP_PROP_FRAME_HEIGHT)
428
-
429
- out = cv2.VideoWriter(output_video_path, fourcc, 20.0,
430
-
431
- (int(vidw), int(vidh))) # 出力先のファイルを開く
432
-
433
-
434
-
435
- ok, frame = video.read() # 最初のフレームを読み込む
436
-
437
- if not ok:
438
-
439
- print('Cannot read video file')
440
-
441
- sys.exit()
442
-
443
-
444
-
445
- frame_pre = frame.copy()
446
-
447
-
448
-
449
- while True:
450
-
451
- ok, frame = video.read() # フレームを読み込む
452
-
453
- if not ok:
454
-
455
- break
456
-
457
- frame_next = frame.copy()
458
-
459
-
460
-
461
- color_diff = cv2.absdiff(frame_next, frame_pre) # フレーム間の差分計算
462
-
463
- gray_diff = cv2.cvtColor(color_diff, cv2.COLOR_BGR2GRAY) # グレースケール変換
464
-
465
- retval, black_diff = cv2.threshold(
466
-
467
- gray_diff, 30, 255, cv2.THRESH_BINARY)
468
-
469
-
470
-
471
- ball, dilation_img = detect(gray_diff)
472
-
473
-
474
-
475
- frame = displayCircle(frame, ball, 2) # 丸で加工
476
-
477
- cImage = blackToColor(dilation_img) # 2値化画像をカラーの配列サイズと同じにする
478
-
479
- im1 = resizeImage(frame, 2, 2)
480
-
481
- im2 = resizeImage(cImage, 2, 2)
482
-
483
- im_h = cv2.hconcat([im1, im2]) # 画像を横方向に連結
484
-
485
-
486
-
487
- cv2.imshow("Tracking", im_h) # フレームを画面表示
488
-
489
- out.write(im_h)
490
-
491
-
492
-
493
- frame_pre = frame_next.copy() # 次のフレームの読み込み
494
-
495
-
496
-
497
- k = cv2.waitKey(1) & 0xff # ESCを押したら中止
498
-
499
- if k == 27:
500
-
501
- break
502
-
503
-
504
-
505
- video.release()
506
-
507
- out.release()
508
-
509
- cv2.destroyAllWindows()
510
-
511
-
512
-
513
-
514
-
515
- if __name__ == '__main__':
516
-
517
- inputFile="tennis.avi"
518
-
519
- outputFile="output.mp4"
520
-
521
- run(inputFile, outputFile)
522
-
523
- ```
524
-
525
- ### 参考サイト
526
-
527
- [リンク内容](http://datatennis.net/archives/4024/)

3

プログラム転記漏れの追記

2018/09/13 12:08

投稿

snake207
snake207

スコア13

test CHANGED
File without changes
test CHANGED
@@ -254,6 +254,18 @@
254
254
 
255
255
  cv2.imshow(WINDOW_NAME, self.frame2)
256
256
 
257
+ if __name__ == '__main__':
258
+
259
+ cv2.namedWindow(WINDOW_NAME)
260
+
261
+ npoints = 4
262
+
263
+ ptlist = PointList(npoints)
264
+
265
+ ptlist.run()
266
+
267
+ cv2.destroyAllWindows()
268
+
257
269
  ```
258
270
 
259
271
 
@@ -509,3 +521,7 @@
509
521
  run(inputFile, outputFile)
510
522
 
511
523
  ```
524
+
525
+ ### 参考サイト
526
+
527
+ [リンク内容](http://datatennis.net/archives/4024/)

2

1つにまとめたプログラムの追記

2018/09/08 08:18

投稿

snake207
snake207

スコア13

test CHANGED
File without changes
test CHANGED
@@ -1,18 +1,14 @@
1
1
  ### やりたいこと
2
2
 
3
- テニスボールのバウンド位置を検出し、マウスで選択したテニスコートの領域内に
4
-
5
- ボールが落ちたのかを判断するプログラムを作成しようとしています。
6
-
7
- 今現在、動画からボールの軌道を抽出するプログラムと
3
+ 動画からボールの軌道を抽出するプログラムと
8
-
4
+
9
- 動画にマウスで領域の4隅を選択すると線が引かれて領域を囲むプログラムを作成しました。
5
+ 動画にマウスで領域の4隅を選択すると線が引かれて領域を囲むプログラムを作成した。
10
-
6
+
11
- この2つのプログラムを組み合わせ、領域を選択してからボールの軌道を抽出するプログラムを作成したいです
7
+ この2つのプログラムを組み合わせ、領域を選択してからボールの軌道を抽出するプログラムを作成したい。
12
8
 
13
9
  ###実行結果
14
10
 
15
- 作成した2つのプログラムを1つにまとめたのですが、何も画面に表示されませんでした。
11
+ 作成した2つのプログラムを1つにまとめたのですが、何も画面に表示されなかった。
16
12
 
17
13
  ```Python
18
14
 
@@ -32,6 +28,114 @@
32
28
 
33
29
 
34
30
 
31
+ def dilation(dilationSize, kernelSize, img): # 膨張した画像にして返す
32
+
33
+ kernel = np.ones((kernelSize, kernelSize), np.uint8)
34
+
35
+ element = cv2.getStructuringElement(
36
+
37
+ cv2.MORPH_RECT, (2 * dilationSize + 1, 2 * dilationSize + 1), (dilationSize, dilationSize))
38
+
39
+ dilation_img = cv2.dilate(img, kernel, element)
40
+
41
+ return dilation_img
42
+
43
+
44
+
45
+
46
+
47
+ def detect(gray_diff, thresh_diff=30, dilationSize=9, kernelSize=20): # 一定面積以上の物体を検出
48
+
49
+ retval, black_diff = cv2.threshold(
50
+
51
+ gray_diff, thresh_diff, 255, cv2.THRESH_BINARY) # 2値化
52
+
53
+ dilation_img = dilation(dilationSize, kernelSize, black_diff) # 膨張処理
54
+
55
+ img = dilation_img.copy()
56
+
57
+ image, contours, hierarchy = cv2.findContours(
58
+
59
+ dilation_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 境界線検出
60
+
61
+
62
+
63
+ ball_pos = []
64
+
65
+
66
+
67
+ for i in range(len(contours)): # 重心位置を計算
68
+
69
+ count = len(contours[i])
70
+
71
+ area = cv2.contourArea(contours[i]) # 面積計算
72
+
73
+ x, y = 0.0, 0.0
74
+
75
+ for j in range(count):
76
+
77
+ x += contours[i][j][0][0]
78
+
79
+ y += contours[i][j][0][1]
80
+
81
+
82
+
83
+ x /= count
84
+
85
+ y /= count
86
+
87
+ x = int(x)
88
+
89
+ y = int(y)
90
+
91
+ ball_pos.append([x, y])
92
+
93
+
94
+
95
+ return ball_pos, img
96
+
97
+
98
+
99
+
100
+
101
+ def displayCircle(image, ballList, thickness=5):
102
+
103
+ for i in range(len(ballList)):
104
+
105
+ x = int(ballList[i][0])
106
+
107
+ y = int(ballList[i][1])
108
+
109
+ cv2.circle(image, (x, y), 10, (0, 0, 255), thickness)
110
+
111
+ return image
112
+
113
+
114
+
115
+
116
+
117
+ def resizeImage(image, w=2, h=2):
118
+
119
+ height = image.shape[0]
120
+
121
+ width = image.shape[1]
122
+
123
+ resizedImage = cv2.resize(image, (int(width / w), int(height / h)))
124
+
125
+ return resizedImage
126
+
127
+
128
+
129
+
130
+
131
+ def blackToColor(bImage):
132
+
133
+ colorImage = np.array((bImage, bImage, bImage))
134
+
135
+ colorImage = colorImage.transpose(1, 2, 0)
136
+
137
+ return colorImage
138
+
35
139
 
36
140
 
37
141
  class PointList():
@@ -98,6 +202,36 @@
98
202
 
99
203
  (self.ptlist[0][0], self.ptlist[0][1]), (0, 255, 0), 3)
100
204
 
205
+ color_diff = cv2.absdiff(frame_next, frame_pre) # フレーム間の差分計算
206
+
207
+ gray_diff = cv2.cvtColor(color_diff, cv2.COLOR_BGR2GRAY) # グレースケール変換
208
+
209
+ retval, black_diff = cv2.threshold(gray_diff, 30, 255, cv2.THRESH_BINARY)
210
+
211
+
212
+
213
+ ball, dilation_img = detect(gray_diff)
214
+
215
+
216
+
217
+ self.frame = displayCircle(self.frame, ball, 2) # 丸で加工
218
+
219
+ cImage = blackToColor(dilation_img) # 2値化画像をカラーの配列サイズと同じにする
220
+
221
+ im1 = resizeImage(selg.frame, 2, 2)
222
+
223
+ im2 = resizeImage(cImage, 2, 2)
224
+
225
+ im_h = cv2.hconcat([im1, im2]) # 画像を横方向に連結
226
+
227
+
228
+
229
+ cv2.imshow("Tracking", im_h) # フレームを画面表示
230
+
231
+ out.write(im_h)
232
+
233
+
234
+
101
235
  cv2.imshow(WINDOW_NAME, self.frame)
102
236
 
103
237
  if cv2.waitKey(10) ==27: # Escキーで抜ける
@@ -120,21 +254,247 @@
120
254
 
121
255
  cv2.imshow(WINDOW_NAME, self.frame2)
122
256
 
123
-
124
-
125
- if event == cv2.EVENT_LBUTTONDOWN: # レフトボタンをクリックしたとき、ptlist配列にx,y座標を格納する
126
-
127
- if self.add(x, y):
128
-
129
- print('[%d] ( %d, %d )' % (ptlist.pos - 1, x, y))
130
-
131
- cv2.circle(self.frame, (x, y), 3, (0, 0, 255), 3)
132
-
133
- cv2.imshow(WINDOW_NAME, self.frame)
134
-
135
- else:
136
-
137
- print('All points have selected. Press ESC-key.')
257
+ ```
258
+
259
+
260
+
261
+ ### 質問内容
262
+
263
+ ・元の2つのプログラムを組み合わせるにはどうしたらいいか?
264
+
265
+ 下記に1つにまとめたプログラムの元のプログラムである2つのプログラムも載せておきます。
266
+
267
+ 回答の参考にしてください。
268
+
269
+ ### ボール軌道抽出(元のプログラム)
270
+
271
+ ```Python
272
+
273
+ import cv2
274
+
275
+ import sys
276
+
277
+ import numpy as np
278
+
279
+
280
+
281
+
282
+
283
+ def dilation(dilationSize, kernelSize, img): # 膨張した画像にして返す
284
+
285
+ kernel = np.ones((kernelSize, kernelSize), np.uint8)
286
+
287
+ element = cv2.getStructuringElement(
288
+
289
+ cv2.MORPH_RECT, (2 * dilationSize + 1, 2 * dilationSize + 1), (dilationSize, dilationSize))
290
+
291
+ dilation_img = cv2.dilate(img, kernel, element)
292
+
293
+ return dilation_img
294
+
295
+
296
+
297
+
298
+
299
+ def detect(gray_diff, thresh_diff=30, dilationSize=9, kernelSize=20): # 一定面積以上の物体を検出
300
+
301
+ retval, black_diff = cv2.threshold(
302
+
303
+ gray_diff, thresh_diff, 255, cv2.THRESH_BINARY) # 2値化
304
+
305
+ dilation_img = dilation(dilationSize, kernelSize, black_diff) # 膨張処理
306
+
307
+ img = dilation_img.copy()
308
+
309
+ image, contours, hierarchy = cv2.findContours(
310
+
311
+ dilation_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 境界線検出
312
+
313
+
314
+
315
+ ball_pos = []
316
+
317
+
318
+
319
+ for i in range(len(contours)): # 重心位置を計算
320
+
321
+ count = len(contours[i])
322
+
323
+ area = cv2.contourArea(contours[i]) # 面積計算
324
+
325
+ x, y = 0.0, 0.0
326
+
327
+ for j in range(count):
328
+
329
+ x += contours[i][j][0][0]
330
+
331
+ y += contours[i][j][0][1]
332
+
333
+
334
+
335
+ x /= count
336
+
337
+ y /= count
338
+
339
+ x = int(x)
340
+
341
+ y = int(y)
342
+
343
+ ball_pos.append([x, y])
344
+
345
+
346
+
347
+ return ball_pos, img
348
+
349
+
350
+
351
+
352
+
353
+ def displayCircle(image, ballList, thickness=5):
354
+
355
+ for i in range(len(ballList)):
356
+
357
+ x = int(ballList[i][0])
358
+
359
+ y = int(ballList[i][1])
360
+
361
+ cv2.circle(image, (x, y), 10, (0, 0, 255), thickness)
362
+
363
+ return image
364
+
365
+
366
+
367
+
368
+
369
+ def resizeImage(image, w=2, h=2):
370
+
371
+ height = image.shape[0]
372
+
373
+ width = image.shape[1]
374
+
375
+ resizedImage = cv2.resize(image, (int(width / w), int(height / h)))
376
+
377
+ return resizedImage
378
+
379
+
380
+
381
+
382
+
383
+ def blackToColor(bImage):
384
+
385
+ colorImage = np.array((bImage, bImage, bImage))
386
+
387
+ colorImage = colorImage.transpose(1, 2, 0)
388
+
389
+ return colorImage
390
+
391
+
392
+
393
+
394
+
395
+ def run(input_video_path, output_video_path):
396
+
397
+ video = cv2.VideoCapture(input_video_path) # videoファイルを読み込む
398
+
399
+ # fourcc = cv2.VideoWriter_fourcc(*'MJPG')
400
+
401
+ fourcc = cv2.VideoWriter_fourcc(*'XVID')
402
+
403
+
404
+
405
+ if not video.isOpened(): # ファイルがオープンできない場合の処理.
406
+
407
+ print("Could not open video")
408
+
409
+ sys.exit()
410
+
411
+
412
+
413
+ vidw = video.get(cv2.CAP_PROP_FRAME_WIDTH)
414
+
415
+ vidh = video.get(cv2.CAP_PROP_FRAME_HEIGHT)
416
+
417
+ out = cv2.VideoWriter(output_video_path, fourcc, 20.0,
418
+
419
+ (int(vidw), int(vidh))) # 出力先のファイルを開く
420
+
421
+
422
+
423
+ ok, frame = video.read() # 最初のフレームを読み込む
424
+
425
+ if not ok:
426
+
427
+ print('Cannot read video file')
428
+
429
+ sys.exit()
430
+
431
+
432
+
433
+ frame_pre = frame.copy()
434
+
435
+
436
+
437
+ while True:
438
+
439
+ ok, frame = video.read() # フレームを読み込む
440
+
441
+ if not ok:
442
+
443
+ break
444
+
445
+ frame_next = frame.copy()
446
+
447
+
448
+
449
+ color_diff = cv2.absdiff(frame_next, frame_pre) # フレーム間の差分計算
450
+
451
+ gray_diff = cv2.cvtColor(color_diff, cv2.COLOR_BGR2GRAY) # グレースケール変換
452
+
453
+ retval, black_diff = cv2.threshold(
454
+
455
+ gray_diff, 30, 255, cv2.THRESH_BINARY)
456
+
457
+
458
+
459
+ ball, dilation_img = detect(gray_diff)
460
+
461
+
462
+
463
+ frame = displayCircle(frame, ball, 2) # 丸で加工
464
+
465
+ cImage = blackToColor(dilation_img) # 2値化画像をカラーの配列サイズと同じにする
466
+
467
+ im1 = resizeImage(frame, 2, 2)
468
+
469
+ im2 = resizeImage(cImage, 2, 2)
470
+
471
+ im_h = cv2.hconcat([im1, im2]) # 画像を横方向に連結
472
+
473
+
474
+
475
+ cv2.imshow("Tracking", im_h) # フレームを画面表示
476
+
477
+ out.write(im_h)
478
+
479
+
480
+
481
+ frame_pre = frame_next.copy() # 次のフレームの読み込み
482
+
483
+
484
+
485
+ k = cv2.waitKey(1) & 0xff # ESCを押したら中止
486
+
487
+ if k == 27:
488
+
489
+ break
490
+
491
+
492
+
493
+ video.release()
494
+
495
+ out.release()
496
+
497
+ cv2.destroyAllWindows()
138
498
 
139
499
 
140
500
 
@@ -142,416 +502,10 @@
142
502
 
143
503
  if __name__ == '__main__':
144
504
 
145
- cv2.namedWindow(WINDOW_NAME)
146
-
147
- npoints = 4
148
-
149
- ptlist = PointList(npoints)
505
+ inputFile="tennis.avi"
150
-
506
+
151
- ptlist.run()
507
+ outputFile="output.mp4"
152
-
508
+
153
- cv2.destroyAllWindows()
509
+ run(inputFile, outputFile)
154
510
 
155
511
  ```
156
-
157
-
158
-
159
- ### 質問内容
160
-
161
- ・元の2つのプログラムを組み合わせるにはどうしたらいいか?
162
-
163
- ・テニスボールのバウンド位置を検出する方法は何かあるのか?
164
-
165
- 下記に1つにまとめたプログラムの元のプログラムである2つのプログラムも載せておきます。
166
-
167
- 回答の参考にしてください。
168
-
169
- ### ボール軌道抽出(元のプログラム)
170
-
171
- ```Python
172
-
173
- import cv2
174
-
175
- import sys
176
-
177
- import numpy as np
178
-
179
-
180
-
181
-
182
-
183
- def dilation(dilationSize, kernelSize, img): # 膨張した画像にして返す
184
-
185
- kernel = np.ones((kernelSize, kernelSize), np.uint8)
186
-
187
- element = cv2.getStructuringElement(
188
-
189
- cv2.MORPH_RECT, (2 * dilationSize + 1, 2 * dilationSize + 1), (dilationSize, dilationSize))
190
-
191
- dilation_img = cv2.dilate(img, kernel, element)
192
-
193
- return dilation_img
194
-
195
-
196
-
197
-
198
-
199
- def detect(gray_diff, thresh_diff=30, dilationSize=9, kernelSize=20): # 一定面積以上の物体を検出
200
-
201
- retval, black_diff = cv2.threshold(
202
-
203
- gray_diff, thresh_diff, 255, cv2.THRESH_BINARY) # 2値化
204
-
205
- dilation_img = dilation(dilationSize, kernelSize, black_diff) # 膨張処理
206
-
207
- img = dilation_img.copy()
208
-
209
- image, contours, hierarchy = cv2.findContours(
210
-
211
- dilation_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 境界線検出
212
-
213
-
214
-
215
- ball_pos = []
216
-
217
-
218
-
219
- for i in range(len(contours)): # 重心位置を計算
220
-
221
- count = len(contours[i])
222
-
223
- area = cv2.contourArea(contours[i]) # 面積計算
224
-
225
- x, y = 0.0, 0.0
226
-
227
- for j in range(count):
228
-
229
- x += contours[i][j][0][0]
230
-
231
- y += contours[i][j][0][1]
232
-
233
-
234
-
235
- x /= count
236
-
237
- y /= count
238
-
239
- x = int(x)
240
-
241
- y = int(y)
242
-
243
- ball_pos.append([x, y])
244
-
245
-
246
-
247
- return ball_pos, img
248
-
249
-
250
-
251
-
252
-
253
- def displayCircle(image, ballList, thickness=5):
254
-
255
- for i in range(len(ballList)):
256
-
257
- x = int(ballList[i][0])
258
-
259
- y = int(ballList[i][1])
260
-
261
- cv2.circle(image, (x, y), 10, (0, 0, 255), thickness)
262
-
263
- return image
264
-
265
-
266
-
267
-
268
-
269
- def resizeImage(image, w=2, h=2):
270
-
271
- height = image.shape[0]
272
-
273
- width = image.shape[1]
274
-
275
- resizedImage = cv2.resize(image, (int(width / w), int(height / h)))
276
-
277
- return resizedImage
278
-
279
-
280
-
281
-
282
-
283
- def blackToColor(bImage):
284
-
285
- colorImage = np.array((bImage, bImage, bImage))
286
-
287
- colorImage = colorImage.transpose(1, 2, 0)
288
-
289
- return colorImage
290
-
291
-
292
-
293
-
294
-
295
- def run(input_video_path, output_video_path):
296
-
297
- video = cv2.VideoCapture(input_video_path) # videoファイルを読み込む
298
-
299
- # fourcc = cv2.VideoWriter_fourcc(*'MJPG')
300
-
301
- fourcc = cv2.VideoWriter_fourcc(*'XVID')
302
-
303
-
304
-
305
- if not video.isOpened(): # ファイルがオープンできない場合の処理.
306
-
307
- print("Could not open video")
308
-
309
- sys.exit()
310
-
311
-
312
-
313
- vidw = video.get(cv2.CAP_PROP_FRAME_WIDTH)
314
-
315
- vidh = video.get(cv2.CAP_PROP_FRAME_HEIGHT)
316
-
317
- out = cv2.VideoWriter(output_video_path, fourcc, 20.0,
318
-
319
- (int(vidw), int(vidh))) # 出力先のファイルを開く
320
-
321
-
322
-
323
- ok, frame = video.read() # 最初のフレームを読み込む
324
-
325
- if not ok:
326
-
327
- print('Cannot read video file')
328
-
329
- sys.exit()
330
-
331
-
332
-
333
- frame_pre = frame.copy()
334
-
335
-
336
-
337
- while True:
338
-
339
- ok, frame = video.read() # フレームを読み込む
340
-
341
- if not ok:
342
-
343
- break
344
-
345
- frame_next = frame.copy()
346
-
347
-
348
-
349
- color_diff = cv2.absdiff(frame_next, frame_pre) # フレーム間の差分計算
350
-
351
- gray_diff = cv2.cvtColor(color_diff, cv2.COLOR_BGR2GRAY) # グレースケール変換
352
-
353
- retval, black_diff = cv2.threshold(
354
-
355
- gray_diff, 30, 255, cv2.THRESH_BINARY)
356
-
357
-
358
-
359
- ball, dilation_img = detect(gray_diff)
360
-
361
-
362
-
363
- frame = displayCircle(frame, ball, 2) # 丸で加工
364
-
365
- cImage = blackToColor(dilation_img) # 2値化画像をカラーの配列サイズと同じにする
366
-
367
- im1 = resizeImage(frame, 2, 2)
368
-
369
- im2 = resizeImage(cImage, 2, 2)
370
-
371
- im_h = cv2.hconcat([im1, im2]) # 画像を横方向に連結
372
-
373
-
374
-
375
- cv2.imshow("Tracking", im_h) # フレームを画面表示
376
-
377
- out.write(im_h)
378
-
379
-
380
-
381
- frame_pre = frame_next.copy() # 次のフレームの読み込み
382
-
383
-
384
-
385
- k = cv2.waitKey(1) & 0xff # ESCを押したら中止
386
-
387
- if k == 27:
388
-
389
- break
390
-
391
-
392
-
393
- video.release()
394
-
395
- out.release()
396
-
397
- cv2.destroyAllWindows()
398
-
399
-
400
-
401
-
402
-
403
- if __name__ == '__main__':
404
-
405
- inputFile="tennis.avi"
406
-
407
- outputFile="output.mp4"
408
-
409
- run(inputFile, outputFile)
410
-
411
- ```
412
-
413
- ### マウスで領域を選択(元のプログラム)
414
-
415
- ```Python
416
-
417
- # -*- coding: utf-8 -*-
418
-
419
- import numpy as np
420
-
421
- import cv2
422
-
423
-
424
-
425
-
426
-
427
- VIDEO_DATE = 'tennis.AVI'
428
-
429
- WINDOW_NAME = "MouseEvent"
430
-
431
-
432
-
433
-
434
-
435
- class PointList():
436
-
437
- def __init__(self, npoints):
438
-
439
- self.video = cv2.VideoCapture(VIDEO_DATE)
440
-
441
- self.frame = None
442
-
443
- self.npoints = npoints
444
-
445
- self.ptlist = np.empty((npoints, 2), dtype=int)
446
-
447
- self.pos = 0
448
-
449
- cv2.setMouseCallback(WINDOW_NAME, self.onMouse)
450
-
451
-
452
-
453
- def add(self, x, y):
454
-
455
- if self.pos < self.npoints:
456
-
457
- self.ptlist[self.pos, :] = [x, y]
458
-
459
- self.pos += 1
460
-
461
- return True
462
-
463
- return False
464
-
465
-
466
-
467
- def run(self):
468
-
469
- while(self.video.isOpened()):
470
-
471
- end_flag, self.frame = self.video.read()
472
-
473
- if not end_flag: # EOF
474
-
475
- break
476
-
477
- if(self.pos == self.npoints):
478
-
479
- # コメントアウト
480
-
481
- #print(self.ptlist)
482
-
483
- cv2.line(self.frame, (self.ptlist[0][0], self.ptlist[0][1]),
484
-
485
- (self.ptlist[1][0], self.ptlist[1][1]), (0, 255, 0), 3)
486
-
487
- cv2.line(self.frame, (self.ptlist[1][0], self.ptlist[1][1]),
488
-
489
- (self.ptlist[2][0], self.ptlist[2][1]), (0, 255, 0), 3)
490
-
491
- cv2.line(self.frame, (self.ptlist[2][0], self.ptlist[2][1]),
492
-
493
- (self.ptlist[3][0], self.ptlist[3][1]), (0, 255, 0), 3)
494
-
495
- cv2.line(self.frame, (self.ptlist[3][0], self.ptlist[3][1]),
496
-
497
- (self.ptlist[0][0], self.ptlist[0][1]), (0, 255, 0), 3)
498
-
499
- cv2.imshow(WINDOW_NAME, self.frame)
500
-
501
- if cv2.waitKey(10) ==27: # Escキーで抜ける
502
-
503
- break
504
-
505
-
506
-
507
- def onMouse(self,event, x, y, flag, params):
508
-
509
- if event == cv2.EVENT_MOUSEMOVE: # マウスが移動したときにx線とy線を更新する
510
-
511
- self.frame2 = np.copy(self.frame)
512
-
513
- h, w = self.frame2.shape[0], self.frame2.shape[1]
514
-
515
- cv2.line(self.frame2, (x, 0), (x, h - 1), (255, 0, 0))
516
-
517
- cv2.line(self.frame2, (0, y), (w - 1, y), (255, 0, 0))
518
-
519
- cv2.imshow(WINDOW_NAME, self.frame2)
520
-
521
-
522
-
523
- if event == cv2.EVENT_LBUTTONDOWN: # レフトボタンをクリックしたとき、ptlist配列にx,y座標を格納する
524
-
525
- if self.add(x, y):
526
-
527
- print('[%d] ( %d, %d )' % (ptlist.pos - 1, x, y))
528
-
529
- cv2.circle(self.frame, (x, y), 3, (0, 0, 255), 3)
530
-
531
- cv2.imshow(WINDOW_NAME, self.frame)
532
-
533
- else:
534
-
535
- print('All points have selected. Press ESC-key.')
536
-
537
-
538
-
539
-
540
-
541
- if __name__ == '__main__':
542
-
543
- cv2.namedWindow(WINDOW_NAME)
544
-
545
- npoints = 4
546
-
547
- ptlist = PointList(npoints)
548
-
549
- ptlist.run()
550
-
551
- cv2.destroyAllWindows()
552
-
553
- ```
554
-
555
- ### 参考サイト
556
-
557
- https://qiita.com/otakoma/items/04216c60fa31eae60947

1

1つにまとめたプログラムの追記

2018/09/08 05:35

投稿

snake207
snake207

スコア13

test CHANGED
File without changes
test CHANGED
@@ -10,18 +10,154 @@
10
10
 
11
11
  この2つのプログラムを組み合わせて、領域を選択してからボールの軌道を抽出するプログラムを作成したいです。
12
12
 
13
- ###試したこと
13
+ ###実行結果
14
14
 
15
15
  作成した2つのプログラムを1つにまとめたのですが、何も画面に表示されませんでした。
16
16
 
17
-
17
+ ```Python
18
+
19
+ # -*- coding: utf-8 -*-
20
+
21
+ import numpy as np
22
+
23
+ import cv2
24
+
25
+
26
+
27
+
28
+
29
+ VIDEO_DATE = 'tennis.AVI'
30
+
31
+ WINDOW_NAME = "MouseEvent"
32
+
33
+
34
+
35
+
36
+
37
+ class PointList():
38
+
39
+ def __init__(self, npoints):
40
+
41
+ self.video = cv2.VideoCapture(VIDEO_DATE)
42
+
43
+ self.frame = None
44
+
45
+ self.npoints = npoints
46
+
47
+ self.ptlist = np.empty((npoints, 2), dtype=int)
48
+
49
+ self.pos = 0
50
+
51
+ cv2.setMouseCallback(WINDOW_NAME, self.onMouse)
52
+
53
+
54
+
55
+ def add(self, x, y):
56
+
57
+ if self.pos < self.npoints:
58
+
59
+ self.ptlist[self.pos, :] = [x, y]
60
+
61
+ self.pos += 1
62
+
63
+ return True
64
+
65
+ return False
66
+
67
+
68
+
69
+ def run(self):
70
+
71
+ while(self.video.isOpened()):
72
+
73
+ end_flag, self.frame = self.video.read()
74
+
75
+ if not end_flag: # EOF
76
+
77
+ break
78
+
79
+ if(self.pos == self.npoints):
80
+
81
+ # コメントアウト
82
+
83
+ #print(self.ptlist)
84
+
85
+ cv2.line(self.frame, (self.ptlist[0][0], self.ptlist[0][1]),
86
+
87
+ (self.ptlist[1][0], self.ptlist[1][1]), (0, 255, 0), 3)
88
+
89
+ cv2.line(self.frame, (self.ptlist[1][0], self.ptlist[1][1]),
90
+
91
+ (self.ptlist[2][0], self.ptlist[2][1]), (0, 255, 0), 3)
92
+
93
+ cv2.line(self.frame, (self.ptlist[2][0], self.ptlist[2][1]),
94
+
95
+ (self.ptlist[3][0], self.ptlist[3][1]), (0, 255, 0), 3)
96
+
97
+ cv2.line(self.frame, (self.ptlist[3][0], self.ptlist[3][1]),
98
+
99
+ (self.ptlist[0][0], self.ptlist[0][1]), (0, 255, 0), 3)
100
+
101
+ cv2.imshow(WINDOW_NAME, self.frame)
102
+
103
+ if cv2.waitKey(10) ==27: # Escキーで抜ける
104
+
105
+ break
106
+
107
+
108
+
109
+ def onMouse(self,event, x, y, flag, params):
110
+
111
+ if event == cv2.EVENT_MOUSEMOVE: # マウスが移動したときにx線とy線を更新する
112
+
113
+ self.frame2 = np.copy(self.frame)
114
+
115
+ h, w = self.frame2.shape[0], self.frame2.shape[1]
116
+
117
+ cv2.line(self.frame2, (x, 0), (x, h - 1), (255, 0, 0))
118
+
119
+ cv2.line(self.frame2, (0, y), (w - 1, y), (255, 0, 0))
120
+
121
+ cv2.imshow(WINDOW_NAME, self.frame2)
122
+
123
+
124
+
125
+ if event == cv2.EVENT_LBUTTONDOWN: # レフトボタンをクリックしたとき、ptlist配列にx,y座標を格納する
126
+
127
+ if self.add(x, y):
128
+
129
+ print('[%d] ( %d, %d )' % (ptlist.pos - 1, x, y))
130
+
131
+ cv2.circle(self.frame, (x, y), 3, (0, 0, 255), 3)
132
+
133
+ cv2.imshow(WINDOW_NAME, self.frame)
134
+
135
+ else:
136
+
137
+ print('All points have selected. Press ESC-key.')
138
+
139
+
140
+
141
+
142
+
143
+ if __name__ == '__main__':
144
+
145
+ cv2.namedWindow(WINDOW_NAME)
146
+
147
+ npoints = 4
148
+
149
+ ptlist = PointList(npoints)
150
+
151
+ ptlist.run()
152
+
153
+ cv2.destroyAllWindows()
154
+
155
+ ```
18
156
 
19
157
 
20
158
 
21
159
  ### 質問内容
22
160
 
23
- ・なぜ、何も画面に表示されないのか?
24
-
25
161
  ・元の2つのプログラムを組み合わせるにはどうしたらいいか?
26
162
 
27
163
  ・テニスボールのバウンド位置を検出する方法は何かあるのか?