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

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

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

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

OpenCV

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

Python

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

受付中

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

max1013
max1013

総合スコア0

Anaconda

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

OpenCV

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

Python

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

1回答

0評価

0クリップ

328閲覧

投稿2021/12/02 08:16

編集2022/01/12 10:55

前提・実現したいこと

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

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

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

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

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

エラーメッセージ

該当のソースコード

Python

# フレーム間差分のプログラム import cv2 import sys import numpy as np def dilation(dilationSize, kernelSize, img): # 膨張した画像にして返す kernel = np.ones((kernelSize, kernelSize), np.uint8) element = cv2.getStructuringElement( cv2.MORPH_RECT, (2 * dilationSize + 1, 2 * dilationSize + 1), (dilationSize, dilationSize)) dilation_img = cv2.dilate(img, kernel, element) return dilation_img def detect(gray_diff, thresh_diff=20, dilationSize=9, kernelSize=20): # 一定面積以上の物体を検出 retval, black_diff = cv2.threshold( gray_diff, thresh_diff, 150, cv2.THRESH_BINARY) # 2値化 dilation_img = dilation(dilationSize, kernelSize, black_diff) # 膨張処理 img = dilation_img.copy() contours, hierarchy = cv2.findContours( dilation_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 境界線検出 ball_pos = [] for i in range(len(contours)): # 重心位置を計算 count = len(contours[i]) area = cv2.contourArea(contours[i]) # 面積計算 x, y = 0.0, 0.0 for j in range(count): x += contours[i][j][0][0] y += contours[i][j][0][1] x /= count y /= count x = int(x) y = int(y) ball_pos.append([x, y]) return ball_pos, img def displayCircle(image, ballList, thickness=5): for i in range(len(ballList)): x = int(ballList[i][0]) y = int(ballList[i][1]) cv2.circle(image, (x, y), 10, (0, 200, 0), thickness) return image def resizeImage(image, w=2, h=2): height = image.shape[0] width = image.shape[1] resizedImage = cv2.resize(image, (int(width / w), int(height / h))) return resizedImage def blackToColor(bImage): colorImage = np.array((bImage, bImage, bImage)) colorImage = colorImage.transpose(1, 2, 0) return colorImage def run(input_video_path, output_video_path): video = cv2.VideoCapture(input_video_path) # videoファイルを読み込む # fourcc = cv2.VideoWriter_fourcc(*'MJPG') fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') if not video.isOpened(): # ファイルがオープンできない場合の処理. print("Could not open video") sys.exit() fps = int(video.get(cv2.CAP_PROP_FPS)) vidw = video.get(cv2.CAP_PROP_FRAME_WIDTH) vidh = video.get(cv2.CAP_PROP_FRAME_HEIGHT) out = cv2.VideoWriter(output_video_path, fourcc, fps, (int(vidw), int(vidh))) # 出力先のファイルを開く ok, frame = video.read() # 最初のフレームを読み込む if not ok: print('Cannot read video file') sys.exit() frame_pre = frame.copy() while True: ok, frame = video.read() # フレームを読み込む if not ok: break frame_next = frame.copy() color_diff = cv2.absdiff(frame_next, frame_pre) # フレーム間の差分計算 gray_diff = cv2.cvtColor(color_diff, cv2.COLOR_BGR2GRAY) # グレースケール変換 retval, black_diff = cv2.threshold( gray_diff, 20, 150, cv2.THRESH_BINARY) ball, dilation_img = detect(gray_diff) frame = displayCircle(frame, ball, 2) # 丸で加工 cImage = blackToColor(dilation_img) # 2値化画像をカラーの配列サイズと同じにする cv2.imshow("threshold", cImage) cv2.imshow("Tracking", frame) # フレームを画面表示 out.write(frame) frame_pre = frame_next.copy() # 次のフレームの読み込み k = cv2.waitKey(1) & 0xff # ESCを押したら中止 if k == 27: break video.release() out.release() cv2.destroyAllWindows() if __name__ == '__main__': inputFile="/Users/max/python-opencv/pinpon.mov" outputFile="pinpon.mp4" run(inputFile, outputFile) ----------------------------------------------------- #橙色のカラートラッキングのプログラム import cv2 import numpy as np def orange_detect(img): # HSV色空間に変換 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # オレンジのHSVの値域1 hsv_min = np.array([15,40,170])#動画により値を変更する hsv_max = np.array([16,45,255])#動画により値を変更する mask1 = cv2.inRange(hsv, hsv_min, hsv_max) return mask1 # ブロブ解析 def analysis_blob(binary_img): # 2値画像のラベリング処理 label = cv2.connectedComponentsWithStats(binary_img) # ブロブ情報を項目別に抽出 n = label[0] - 1 data = np.delete(label[2], 0, 0) center = np.delete(label[3], 0, 0) # ブロブ面積最大のインデックス max_index = np.argmax(data[:, 4]) # 面積最大ブロブの情報格納用 maxblob = {} # 面積最大ブロブの各種情報を取得 maxblob["upper_left"] = (data[:, 0][max_index], data[:, 1][max_index]) # 左上座標 maxblob["width"] = data[:, 2][max_index] # 幅 maxblob["height"] = data[:, 3][max_index] # 高さ maxblob["area"] = data[:, 4][max_index] # 面積 maxblob["center"] = center[max_index] # 中心座標 return maxblob def main(): videofile_path = "/Users/max/python-opencv/pinpon.mov" # カメラのキャプチャ cap = cv2.VideoCapture(videofile_path) fps = int(cap.get(cv2.CAP_PROP_FPS)) w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') out = cv2.VideoWriter('pinpon.mp4', fourcc, fps, (w, h)) while(cap.isOpened()): # フレームを取得 ret, frame = cap.read() # オレンジ色検出 mask = orange_detect(frame) # マスク画像をブロブ解析(面積最大のブロブ情報を取得) target = analysis_blob(mask) # 面積最大ブロブの中心座標を取得 center_x = int(target["center"][0]) center_y = int(target["center"][1]) # フレームに面積最大ブロブの中心周囲を円で描く cv2.circle(frame, (center_x, center_y), 30, (0, 200, 0), thickness=3, lineType=cv2.LINE_AA) # 結果表示 cv2.imshow("Frame", frame) cv2.imshow("Mask", mask) out.write(frame) # qキーが押されたら途中終了 if cv2.waitKey(25) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() if __name__ == '__main__': main()

試したこと

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

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

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

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

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

まだ回答がついていません

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

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Anaconda

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

OpenCV

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

Python

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