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

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

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

Anacondaは、Python本体とPythonで利用されるライブラリを一括でインストールできるパッケージです。環境構築が容易になるため、Python開発者間ではよく利用されており、商用目的としても利用できます。

OpenCV

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

Python

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

Q&A

1回答

2006閲覧

卓球ボールの追跡がしたい

max1013

総合スコア0

Anaconda

Anacondaは、Python本体とPythonで利用されるライブラリを一括でインストールできるパッケージです。環境構築が容易になるため、Python開発者間ではよく利用されており、商用目的としても利用できます。

OpenCV

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

Python

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

0グッド

0クリップ

投稿2021/12/02 08:16

編集2021/12/02 08:36

前提・実現したいこと

Pythonプログラミング初心者です。
AnacondaのspyderでPythonとOpencvを用いて青い卓球台上での橙色の卓球ボールのラリーを追跡するシステムを作成しております。手法といたしましてはHSV表色系により橙色を指定して追跡するカラートラッキングとフレーム間差分を用いて追跡を試みたいと考えております。

手順といたしましては、
1、卓球の動画を読み込む
2、前フレームと後フレームの差分画像を作成
3、差分画像から橙色の物体を検知し、追跡する
という手順です。

発生している問題・エラーメッセージ

まず試しに、橙色を指定したカラートラッキングのみでの追跡、フレーム間差分のみでの追跡それぞれ各自でプログラムを組んで実行したら、エラーが出ずに正常に動かすことができたのですが、どちらの追跡もまだまだノイズが多い状況です。そこで自分なりに試行錯誤してカラートラッキングとフレーム間差分の二つのプログラムを合体させて実行しようと試みているのですが、なかなかうまくいきません。

大変困っている状況です。下の二つのプログラムをどのように組み合わせればうまくいくのかアドバイス頂けると非常に幸いです。

エラーメッセージ

該当のソースコード

Python

1 2# フレーム間差分のプログラム 3import cv2 4import sys 5import numpy as np 6 7 8def dilation(dilationSize, kernelSize, img): # 膨張した画像にして返す 9 kernel = np.ones((kernelSize, kernelSize), np.uint8) 10 element = cv2.getStructuringElement( 11 cv2.MORPH_RECT, (2 * dilationSize + 1, 2 * dilationSize + 1), (dilationSize, dilationSize)) 12 dilation_img = cv2.dilate(img, kernel, element) 13 return dilation_img 14 15 16def detect(gray_diff, thresh_diff=20, dilationSize=9, kernelSize=20): # 一定面積以上の物体を検出 17 retval, black_diff = cv2.threshold( 18 gray_diff, thresh_diff, 150, cv2.THRESH_BINARY) # 2値化 19 dilation_img = dilation(dilationSize, kernelSize, black_diff) # 膨張処理 20 img = dilation_img.copy() 21 contours, hierarchy = cv2.findContours( 22 dilation_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 境界線検出 23 24 ball_pos = [] 25 26 for i in range(len(contours)): # 重心位置を計算 27 count = len(contours[i]) 28 area = cv2.contourArea(contours[i]) # 面積計算 29 x, y = 0.0, 0.0 30 for j in range(count): 31 x += contours[i][j][0][0] 32 y += contours[i][j][0][1] 33 34 x /= count 35 y /= count 36 x = int(x) 37 y = int(y) 38 ball_pos.append([x, y]) 39 40 return ball_pos, img 41 42 43def displayCircle(image, ballList, thickness=5): 44 for i in range(len(ballList)): 45 x = int(ballList[i][0]) 46 y = int(ballList[i][1]) 47 cv2.circle(image, (x, y), 10, (0, 200, 0), thickness) 48 return image 49 50 51def resizeImage(image, w=2, h=2): 52 height = image.shape[0] 53 width = image.shape[1] 54 resizedImage = cv2.resize(image, (int(width / w), int(height / h))) 55 return resizedImage 56 57 58def blackToColor(bImage): 59 colorImage = np.array((bImage, bImage, bImage)) 60 colorImage = colorImage.transpose(1, 2, 0) 61 return colorImage 62 63 64def run(input_video_path, output_video_path): 65 video = cv2.VideoCapture(input_video_path) # videoファイルを読み込む 66 # fourcc = cv2.VideoWriter_fourcc(*'MJPG') 67 fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') 68 69 if not video.isOpened(): # ファイルがオープンできない場合の処理. 70 print("Could not open video") 71 sys.exit() 72 73 fps = int(video.get(cv2.CAP_PROP_FPS)) 74 vidw = video.get(cv2.CAP_PROP_FRAME_WIDTH) 75 vidh = video.get(cv2.CAP_PROP_FRAME_HEIGHT) 76 out = cv2.VideoWriter(output_video_path, fourcc, fps, 77 (int(vidw), int(vidh))) # 出力先のファイルを開く 78 79 ok, frame = video.read() # 最初のフレームを読み込む 80 if not ok: 81 print('Cannot read video file') 82 sys.exit() 83 84 frame_pre = frame.copy() 85 86 while True: 87 ok, frame = video.read() # フレームを読み込む 88 if not ok: 89 break 90 frame_next = frame.copy() 91 92 color_diff = cv2.absdiff(frame_next, frame_pre) # フレーム間の差分計算 93 gray_diff = cv2.cvtColor(color_diff, cv2.COLOR_BGR2GRAY) # グレースケール変換 94 retval, black_diff = cv2.threshold( 95 gray_diff, 20, 150, cv2.THRESH_BINARY) 96 97 ball, dilation_img = detect(gray_diff) 98 99 frame = displayCircle(frame, ball, 2) # 丸で加工 100 cImage = blackToColor(dilation_img) # 2値化画像をカラーの配列サイズと同じにする 101 102 103 cv2.imshow("threshold", cImage) 104 105 cv2.imshow("Tracking", frame) # フレームを画面表示 106 out.write(frame) 107 108 frame_pre = frame_next.copy() # 次のフレームの読み込み 109 110 k = cv2.waitKey(1) & 0xff # ESCを押したら中止 111 if k == 27: 112 break 113 114 video.release() 115 out.release() 116 cv2.destroyAllWindows() 117 118 119if __name__ == '__main__': 120 inputFile="/Users/max/python-opencv/pinpon.mov" 121 outputFile="pinpon.mp4" 122 run(inputFile, outputFile) 123----------------------------------------------------- 124#橙色のカラートラッキングのプログラム 125import cv2 126import numpy as np 127 128def orange_detect(img): 129 # HSV色空間に変換 130 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 131 132 # オレンジのHSVの値域1 133 hsv_min = np.array([15,40,170])#動画により値を変更する 134 hsv_max = np.array([16,45,255])#動画により値を変更する 135 mask1 = cv2.inRange(hsv, hsv_min, hsv_max) 136 137 138 return mask1 139 140# ブロブ解析 141def analysis_blob(binary_img): 142 # 2値画像のラベリング処理 143 label = cv2.connectedComponentsWithStats(binary_img) 144 145 # ブロブ情報を項目別に抽出 146 n = label[0] - 1 147 data = np.delete(label[2], 0, 0) 148 center = np.delete(label[3], 0, 0) 149 150 # ブロブ面積最大のインデックス 151 max_index = np.argmax(data[:, 4]) 152 153 # 面積最大ブロブの情報格納用 154 maxblob = {} 155 156 # 面積最大ブロブの各種情報を取得 157 maxblob["upper_left"] = (data[:, 0][max_index], data[:, 1][max_index]) # 左上座標 158 maxblob["width"] = data[:, 2][max_index] # 幅 159 maxblob["height"] = data[:, 3][max_index] # 高さ 160 maxblob["area"] = data[:, 4][max_index] # 面積 161 maxblob["center"] = center[max_index] # 中心座標 162 163 return maxblob 164 165def main(): 166 videofile_path = "/Users/max/python-opencv/pinpon.mov" 167 168 # カメラのキャプチャ 169 cap = cv2.VideoCapture(videofile_path) 170 171 fps = int(cap.get(cv2.CAP_PROP_FPS)) 172 w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) 173 h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) 174 fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') 175 out = cv2.VideoWriter('pinpon.mp4', fourcc, fps, (w, h)) 176 177 while(cap.isOpened()): 178 # フレームを取得 179 ret, frame = cap.read() 180 181 # オレンジ色検出 182 mask = orange_detect(frame) 183 184 # マスク画像をブロブ解析(面積最大のブロブ情報を取得) 185 target = analysis_blob(mask) 186 187 # 面積最大ブロブの中心座標を取得 188 center_x = int(target["center"][0]) 189 center_y = int(target["center"][1]) 190 191 # フレームに面積最大ブロブの中心周囲を円で描く 192 cv2.circle(frame, (center_x, center_y), 30, (0, 200, 0), 193 thickness=3, lineType=cv2.LINE_AA) 194 195 # 結果表示 196 cv2.imshow("Frame", frame) 197 cv2.imshow("Mask", mask) 198 199 out.write(frame) 200 201 # qキーが押されたら途中終了 202 if cv2.waitKey(25) & 0xFF == ord('q'): 203 break 204 205 cap.release() 206 cv2.destroyAllWindows() 207 208 209if __name__ == '__main__': 210 main()

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

1T2R3M4

2021/12/02 08:22

質問は何でしょうか。
max1013

2021/12/02 08:37

カラートラッキングとフレーム間差分を用いて卓球ボールの追跡を行いたいのですが、上の二つのプログラムをどのように組み合わせれば良いかアドバイス頂けると幸いです。
fana

2021/12/02 09:12

> 卓球の動画 というのは… ・撮影しているカメラ位置は動くのでしょうか? それとも定点から撮影している想定でしょうか?  また,どこから撮影している感じなのでしょうか(台を真上から見てるだとか,選手の肩越しに見てる感じだとか)? ・フレーム間でボールの位置はどのくらい変わるのでしょう?(例えば,ボールの像の直径の何倍くらいは動くよ,とかそういう感じで)
max1013

2021/12/02 09:23

撮影に関しては定点で台の真横から行っております。 フレーム間でボールの位置は直径の3倍くらいは動きます。
max1013

2021/12/05 02:41

meanshiftでは卓球ボールの動きに適用できませんでした。 なるべく軽い処理で実行したいです。 上の二つのプログラムをうまく組み合わせる方法もしわかれば教えていただきたいです。
guest

回答1

0

定点撮影であれば,
フレーム間差分 ではなくて 背景差分 の利用を考えることができるかもしれません.

「ボールの色」という利用可能な既知情報に関しては,例えば,
あるフレーム画像を用いて背景情報を更新する際にそのフレーム画像の「橙色(ボールの色)に近い箇所は積極的に用いない」といった使い方ができるかもしれませんね.

投稿2021/12/03 01:49

fana

総合スコア11658

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

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

max1013

2021/12/05 02:39

複雑な背景にも対応できるようにしたいので,フレーム間差分を用いた手法でアドバイスいただけると幸いです。
fana

2021/12/06 01:49 編集

「とりあえず脳死で2つの処理結果のANDでも取ってみればよいのでは?」とか思いますが…… そんな単純な話ではなくて何らかの「情報をうまいこと組み合わたアルゴリズム」的な話が欲しいのであれば, そういうことを明記された方が良いように思います. > 複雑な背景 というのが具体的にどのような話かはわかりませんが,懸念事項が見えているならば,それを質問文でしっかりと示すとよいのではないでしょうか. (それであなたの役に立つ回答が付くかどうかはわかりませんが,少なくとも要らない話での余計なやりとりを防止できるでしょう)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問