前提・実現したいこと
移動しているボール(ジャグリングなど)を検出して円を描くプログラムです。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