質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Raspbian

Raspbianは、DebianベースのRaspberry Pi用ディストリビューション。ハードウェア浮動小数点演算を有効にすることが可能で、Webブラウズなどの速度を向上できます。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

5339閲覧

ボール判定するプログラム

snake207

総合スコア13

Raspbian

Raspbianは、DebianベースのRaspberry Pi用ディストリビューション。ハードウェア浮動小数点演算を有効にすることが可能で、Webブラウズなどの速度を向上できます。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/10/01 11:16

編集2018/10/07 03:33

目標(やりたいこと)

選択した範囲内にボールが入ったかどうか判定したい

質問内容

どのようにすれば、ボール判定できるか?

Python

1# -*- coding: utf-8 -*- 2 3import numpy as np 4 5import cv2 6 7from time import time 8 9import subprocess 10 11 12 13VIDEO_DATE = "tennis.AVI" 14 15WINDOW_NAME = "MouseEvent" 16 17 18 19def dilation(dilationSize, kernelSize, img): # 膨張した画像にして返す 20 21 kernel = np.ones((kernelSize, kernelSize), np.uint8) 22 23 element = cv2.getStructuringElement(cv2.MORPH_RECT, (2 * dilationSize + 1, 2 * dilationSize + 1), (dilationSize, dilationSize)) 24 25 dilation_img = cv2.dilate(img, kernel, element) 26 27 return dilation_img 28 29 30 31 32def detect(gray_diff, thresh_diff=95, dilationSize=9, kernelSize=20): # 一定面積以上の物体を検出 33 34 retval, black_diff = cv2.threshold(gray_diff, thresh_diff, 255, cv2.THRESH_BINARY) # 2値化 35 36 dilation_img = dilation(dilationSize, kernelSize, black_diff) # 膨張処理 37 38 img = dilation_img.copy() 39 40  image, contours, hierarchy = cv2.findContours(dilation_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 境界線検出 41 42 43  44 ball_pos = [] 45 46 47 48 for i in range(len(contours)): # 重心位置を計算 49 50 count = len(contours[i]) 51 52 53 area = cv2.contourArea(contours[i]) # 面積計算 54 55 x, y = 0.0, 0.0 56 57 for j in range(count): 58 59 x += contours[i][j][0][0] 60 61 y += contours[i][j][0][1] 62 63 64 65 66 x /= count 67 68 y /= count 69 70 x = int(x) 71 72 y = int(y) 73 74 ball_pos.append([x, y]) 75 76 77 return ball_pos, img 78 79 80 81 82def displayCircle(image, ballList, thickness=5): 83 84 for i in range(len(ballList)): 85 86 x = int(ballList[i][0]) 87 88 y = int(ballList[i][1]) 89 90 cv2.circle(image, (x, y), 10, (0, 0, 255), thickness) 91 92 return image 93 94 95 96 97def resizeImage(image, w=2, h=2): 98 99 height = image.shape[0] 100 101 width = image.shape[1] 102 103 resizedImage = cv2.resize(image, (int(width / w), int(height / h))) 104 105 return resizedImage 106 107 108 109 110def blackToColor(bImage): 111 112 colorImage = np.array((bImage, bImage, bImage)) 113 114 colorImage = colorImage.transpose(1, 2, 0) 115 116 return colorImage 117 118 119 120class PointList(): 121 122 def __init__(self, npoints): 123 124 self.video = cv2.VideoCapture(VIDEO_DATE) 125 126 self.frame = None 127 128 self.npoints = npoints 129 130 self.ptlist = np.empty((npoints, 2), dtype=int) 131 132 self.pos = 0 133 134 cv2.setMouseCallback(WINDOW_NAME, self.onMouse) 135 136 137 138 def add(self, x, y): 139 140 if self.pos < self.npoints: 141 142 self.ptlist[self.pos, :] = [x, y] 143 144 self.pos += 1 145 146 return True 147 148 return False 149 150 151 152 def run(self): 153 154 ok, self.frame = self.video.read() # 最初のフレームを読み込む 155 156 if not ok: 157 158 print('Cannot read video file') 159 160 sys.exit() 161 162 self.frame_pre = self.frame.copy() 163 164 165 166 while True: 167 168 ok, self.frame = self.video.read() # フレームを読み込む 169 170 if not ok: 171 172 break 173 174 self.frame_next = self.frame.copy() 175 176 177 178 if(self.pos == self.npoints): 179 180 cv2.line(self.frame, (self.ptlist[0][0], self.ptlist[0][1]), 181 182 (self.ptlist[1][0], self.ptlist[1][1]), (0, 255, 0), 3) 183 184 cv2.line(self.frame, (self.ptlist[1][0], self.ptlist[1][1]), 185 186 (self.ptlist[2][0], self.ptlist[2][1]), (0, 255, 0), 3) 187 188 cv2.line(self.frame, (self.ptlist[2][0], self.ptlist[2][1]), 189 190 (self.ptlist[3][0], self.ptlist[3][1]), (0, 255, 0), 3) 191 192 cv2.line(self.frame, (self.ptlist[3][0], self.ptlist[3][1]), 193 194 (self.ptlist[0][0], self.ptlist[0][1]), (0, 255, 0), 3) 195 196 color_diff = cv2.absdiff(self.frame_next, self.frame_pre) # フレーム間の差分計算 197 198 gray_diff = cv2.cvtColor(color_diff, cv2.COLOR_BGR2GRAY) # グレースケール変換 199 200 retval, black_diff = cv2.threshold(gray_diff,30, 255, cv2.THRESH_BINARY) 201 202 203 204 ball, dilation_img = detect(gray_diff) 205 206 207 208 self.frame = displayCircle(self.frame, ball, 2) # 丸で加工 209 210 cImage = blackToColor(dilation_img) # 2値化画像をカラーの配列サイズと同じにする 211 212 213 214 self.frame_pre = self.frame_next.copy() # 次のフレームの読み込み 215 216 217 218 cv2.imshow(WINDOW_NAME, self.frame) 219 220 if cv2.waitKey(10) ==27: # Escキーで抜ける 221 222 break 223 224 225 226 def onMouse(self,event, x, y, flag, params): 227 228 if event == cv2.EVENT_MOUSEMOVE: # マウスが移動したときにx線とy線を更新する 229 230 self.frame2 = np.copy(self.frame) 231 232 h, w = self.frame2.shape[0], self.frame2.shape[1] 233 234 cv2.line(self.frame2, (x, 0), (x, h - 1), (255, 0, 0)) 235 236 cv2.line(self.frame2, (0, y), (w - 1, y), (255, 0, 0)) 237 238 cv2.imshow(WINDOW_NAME, self.frame2) 239 240 241 242 if event == cv2.EVENT_LBUTTONDOWN: # レフトボタンをクリックしたとき、ptlist配列にx,y座標を格納する 243 244 if self.add(x, y): 245 246 print('[%d] ( %d, %d )' % (ptlist.pos - 1, x, y)) 247 248 cv2.circle(self.frame, (x, y), 3, (0, 0, 255), 3) 249 250 cv2.imshow(WINDOW_NAME, self.frame) 251 252 else: 253 254 print('All points have selected. Press ESC-key.') 255 256 257 258if __name__ == '__main__': 259 260 cv2.namedWindow(WINDOW_NAME) 261 262 npoints = 4 263 264 ptlist = PointList(npoints) 265 266 ptlist.run() 267 268 cv2.destroyAllWindows()

参考にした文献(URL)

マウスで範囲選択
ボールの軌道抽出

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

質問者さんが解決したいと推測される課題

ファイル名から類推するに、「テニスをプレイしている動画から、ボールがバウンドしたかどうかを判定したい」ということですね。
所感としてはかなり難しい部類の問題になるかと思います。

背景差分法で行う上での懸念

・目標を達成するにはどのような処理が必要なのか?(必要な関数など...) ・作成したプログラムにボール判定するために追加すべき処理はあるか?

現在、背景差分による方法を考えておられるようですが、以下の理由で難しいかもしれません。

他に思いつく手法

例えば、トラッキング系の手法を使うのはどうでしょうか。
アルゴリズムはわかりませんが、実際のテニスの試合ではラインのIn/Out 判定をするシステムが 実用化 されているようです。
ただ上記のシステムはスーパースローカメラを使っているとのことで、市販の30FPSぐらいのカメラでスピードの早いボールを追いきれるかという懸念もあります。

課題解決のために必要なこと

簡単な問題ではないので、先行研究の論文や Web 上の記事を調べてみるのがいいと思います。

検索ワード

  • 「スポーツ画像解析 OpenCV」
  • 「トラッキング OpenCV」
  • 「ボール トラッキング OpenCV」

投稿2018/10/01 16:19

tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

snake207

2018/10/01 22:23 編集

回答、ありがとうございます。 背景差分だと回答者さんが言われた通り、ボールだけを検知するのは難しいので、手法を変えてトラッキング系の手法について調べてみようと思います。
guest

0

他の方が既に述べられている通りに,撮影FPS(や撮影具合)次第な面が多そうですが…

オプティカルフローとか使えないでしょうか.
以下,推測ですが,

  • (判定したい状況下においては)ボールの速度は人間等の動きと比較すると十分に早い
  • 多くの場合,人間等の動きとボールの動きは独立している
  • {ボールのサイズ,ボールの存在しえる距離範囲}から,フローをクラスタリングした際の,ボールクラスタのサイズは限定できる

…みたいなことは無いでしょうか.

投稿2018/10/03 08:58

fana

総合スコア11654

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2018/10/03 09:03

後は,「ボールとそれ以外とでは,カメラの視界内での移動範囲が異なる」とか (ある程度長時間追跡しないと見えませんが) #このコメントと同一内容を間違って別の回答として投稿してしまいました.(削除リクエスト済み)
snake207

2018/10/03 11:43

オプティカルフローを使って、ボールを追跡するということでしょうか?
fana

2018/10/04 00:59

ざっくり言うと,(背景差分が候補に挙がるようなシーンなのであれば)求めたオプティカルフローを可視化(例えば真っ黒な画像上に白線で描画とか)しただけの映像を眺めたら「これがボール(の動き)なんじゃないの?」っていうのがわかるんじゃないかな? みたいな. もしそうであれば,あとはその特徴(の他物体との違い)をどうにかしてコードで表せば検出できるかな,と. 必要であれば追跡も可能でしょう.
snake207

2018/10/04 02:20

「ボールの特徴を最終的にコードで表せば検出できるのでは」ということですか?
fana

2018/10/04 04:08

場においてボールの動きというのが他の物の動きとは明らかに異なるということが"あるのならば", 映像の動きに着目したらボールが判別できるのでは? という話をしているだけです. もし時間(とわずかな労力)を割くことができるのなら,実際にフローを可視化した映像を作って見てみると良いかもしれません. 例えば,(検索して適当に見つけたやつですが) https://www.youtube.com/watch?v=Tqf2EzG0djQ みたいな感じのを.
snake207

2018/10/04 11:17

分かりました、一度実際にフローを可視化するプログラムを作成しようと思います。 わざわざ、参考になるものを見つけていただき、ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問