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

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

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

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

Python 3.x

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

Q&A

1回答

2067閲覧

検出結果を修正・拡張したいです

退会済みユーザー

退会済みユーザー

総合スコア0

OpenCV

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

Python 3.x

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

1グッド

2クリップ

投稿2018/01/11 08:07

編集2022/01/12 10:55

前提・実現したいこと
移動しているボール(ジャグリングなど)を検出して円を描くプログラムです。OpenCVで移動体検出を使ったサンプルをいくつかつなぎ合わせたハリボテプログラムなので、余計な部分があるかもしれませんが、あまり気にしないでいただけると……
実現したいこととしては、
①余計に表示されてしまっている円をボール上だけにしたいこと(円の数を減らしたい)
②加えてボールの軌跡を描くこと(軌跡の描き方は分かっているのですが、それぞれのボール(円)ごとに区別するやりかたがわかりません)
の二つです。
どうかよろしくお願い致します。

###該当のソースコード

import cv2 import numpy as np from collections import deque import argparse import math kernel = np.ones((5,5),np.uint8) neiborhood4 = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]], np.uint8) ap = argparse.ArgumentParser() ap.add_argument("-v", "--video", help="path to the (optional) video file") ap.add_argument("-b", "--buffer", type=int, default=10, help="max buffer size") args = vars(ap.parse_args()) # フレーム差分の計算 def frame_sub(src1, src2, src3, th): # フレームの絶対差分 d1 = cv2.absdiff(src1, src2) d2 = cv2.absdiff(src2, src3) # 2つの差分画像の論理積 diff = cv2.bitwise_and(d1, d2) # 二値化処理 diff[diff < th] = 0 diff[diff >= th] = 255 # メディアンフィルタ処理(ゴマ塩ノイズ除去) mask = cv2.medianBlur(diff, 3) return mask def main(): pts1 = deque(maxlen=args["buffer"]) # カメラのキャプチャ cap = cv2.VideoCapture("動画ファイル") cv2.namedWindow("Frame2",cv2.WINDOW_NORMAL) cv2.namedWindow("Douga",cv2.WINDOW_NORMAL) # フレームを3枚取得してグレースケール変換 frame1 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) #frame2 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) while True: #(grabbed, frame) = cap.read() count=0 frame2_rgb = cap.read()[1] frame2 = cv2.cvtColor(frame2_rgb, cv2.COLOR_RGB2GRAY) #if not grabbed: # break # フレーム間差分を計算 mask = frame_sub(frame1, frame2, frame3, th=30) #太くして面積を広く mask = cv2.dilate(mask,neiborhood4,iterations = 1) #輪郭の取得 image, cnts, hierarchy = cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE) center=None if len(cnts) > 0: for i, contour in enumerate(cnts): # area:面積 area = cv2.contourArea(contour) if area < 100: continue # moments:重心 M = cv2.moments(contour) if M["m00"] != 0: cx = int(M["m10"] / M["m00"]) cy = int(M["m01"] / M["m00"]) else: cx, cy = 0, 0 # 最小外接円 (x, y), radius = cv2.minEnclosingCircle(contour) center = (int(x),int(y)) radius = int(radius) frame2_rgb = cv2.circle(frame2_rgb,center,radius,(255,255,0),2) pts1.appendleft(center) count=count+1 # 結果を表示 cv2.imshow("Frame2", frame2) cv2.imshow("Mask", mask) cv2.imshow("Douga",frame2_rgb) print(count) # 3枚のフレームを更新 frame1 = frame2 frame2 = frame3 frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY) # qキーが押されたら途中終了 key = cv2.waitKey(50) & 0xFF if key == ord("q"): break cap.release() cv2.destroyAllWindows() if __name__ == '__main__': main()

###試したこと
試しに、軌跡を描くプログラムを追加してみたのですが、中心の位置が区別できていないため、あっちこっちにぶれて描かれてしまいました。

###補足情報(言語/FW/ツール等のバージョンなど)
windows7/Anaconda3.4.4/Spyder3(Python3.5)/OpenCV 3.1.0

イメージ説明
イメージ説明
イメージ説明
イメージ説明
イメージ説明
イメージ説明

退会済みユーザー👍を押しています

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2018/01/12 10:23

動画だとTeratailにアップロードできませんので、かわりに検出前の動画から数フレーム分の画像をアップすることはできますか?
guest

回答1

0

余計に表示されてしまっている円をボール上だけにしたいこと(円の数を減らしたい)

ボールが緑色と決まりきっているのであれば、緑色のみを抽出すればよいですね。
以下の関数をframe2frame3に突っ込むことでだいぶ良くなると思います。

Python

1def color_binary(img): 2 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 3 lower_green = np.array([45,64,128]) 4 upper_green = np.array([100,255,180]) 5 6 mask = cv2.inRange(hsv, lower_green, upper_green) 7 res = cv2.cvtColor(cv2.bitwise_and(img,img, mask= mask), cv2.COLOR_RGB2GRAY) 8 _, res = cv2.threshold(res , 1,255, cv2.THRESH_BINARY) 9 return res

加えてボールの軌跡を描くこと(軌跡の描き方は分かっているのですが、それぞれのボール(円)ごとに区別するやりかたがわかりません)

terarailの過去の投稿に同じような問題がありました。
# 結果を表示の前に以下のコードを挟むとある程度動くと思います。
が、手元の6枚の写真から作った動画では動作確認ができる状態ではなかった(3フレームの差分を取るため、2フレームくらいしか出てこない)ので私にできるのはここまでです。ごめんなさい。

Python

1 # update the points queue 2 pts1.appendleft(center) 3 4 # loop over the set of tracked points 5 for i in range(1, len(pts1)): 6 # if either of the tracked points are None, ignore 7 # them 8 if pts1[i - 1] is None or pts1[i] is None: 9 continue 10 11 # otherwise, compute the thickness of the line and 12 # draw the connecting lines 13 thickness = int(np.sqrt(args["buffer"] / float(i + 1)) * 2.5) 14 cv2.line(frame2_rgb, pts1[i - 1], pts1[i], (0, 0, 255), thickness)

投稿2018/01/14 00:49

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2018/01/14 05:12

回答ありがとうございました。①の方は解決しましたが、②に関してはうまく動いてくれませんでした。 改めて実現したいことを書くと、中心点を区別して、円から伸びる軌跡が円ごとに独立して描かれてほしいです。 厚かましいとは思いますが、どうかよろしくおねがいします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問