OpenCVでボールの軌道描画

前回まで、OpenCVでボールを認識させるプログラムを書きました。

今度はボールの軌道を描画します。

環境・バージョン

Windows10
Python 3.6.1
OpenCV 3.3.1

ボール軌道に点を打つ

先に出力結果です。

赤いボールが通った道に、ピンクの点が描かれます。
(素材動画のコマ落ちで、点が一つ抜けています。)

なお、マニアックですが・・・この動画は、ボッチャの「クッションボール」という技の軌道を表したものです。

他のボールに当てて軌道を変え、ターゲットの白いボールに近づけています。

ボール軌道描画のコード

毎フレーム、ボールの座標を配列に記録し、forで配列の分だけ円(点)を描画する流れです。(もっと賢い書き方がありそう・・・)

import cv2
import numpy as np

cap = cv2.VideoCapture('xxxxx.mp4') # 任意の動画

# 動画出力設定
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out = cv2.VideoWriter('output.avi',fourcc, 23.0, (1280,720))

orbit = []

while(1):
    _, frame = cap.read()

    #マスク画像取得
    def getMask(l, u):
        # HSVに変換
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

        lower = np.array(l)
        upper = np.array(u)
        if lower[0] >= 0:
            mask = cv2.inRange(hsv, lower, upper)
        else:
            #赤用(彩度、明度判定は簡略化)
            h = hsv[:, :, 0]
            s = hsv[:, :, 1]
            mask = np.zeros(h.shape, dtype=np.uint8)
            mask[((h < lower[0]*-1) | (h > upper[0])) & (s > lower[1])] = 255

        return cv2.bitwise_and(frame,frame, mask= mask)

    # 輪郭取得
    def getContours(img,t,r,drawOrbit):
        gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
        ret, thresh = cv2.threshold(gray, t, 255, cv2.THRESH_BINARY)
        imgEdge, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

        # 一番大きい輪郭を抽出
        contours.sort(key=cv2.contourArea, reverse=True)
        cnt = contours[0]

        # 円描画
        (x,y), radius = cv2.minEnclosingCircle(cnt)
        center = (int(x),int(y))
        radius = int(radius)

        if radius > r:
            if drawOrbit == 1:
                orbit.append(center)
                for j in orbit:
                    cv2.circle(frame,j,10,(128,128,255),-1) # 軌道描画
            return cv2.circle(frame,center,radius,(0,255,0),2) # 最小外接円描画
        else:
            return frame

    # 白・赤マスク
    res_white = getMask([0,0,100], [180,45,255])
    res_red = getMask([-10,45,30], [170,255,255])

    # 輪郭取得
    getContours(res_white, 45, 75, 0) # (画像, 明度閾値, 最小半径, 軌道描画 0=なし 1=あり)
    contours_frame = getContours(res_red, 45, 75 ,1)

    # 動画書き込み
    out.write(contours_frame)

    # 再生
    cv2.imshow('video',contours_frame)
    k = cv2.waitKey(46) & 0xFF

    #Q で終了
    if k == ord('q'):
        break

out.release()
cv2.destroyAllWindows()

軌道描画の他、動画をAVIで保存するように改修しています。

軌道描画の使い道

ボールの軌道を可視化することで、自分の投球のブレや距離を分析し、技術向上に使えます。

また将棋の「棋譜」のように記録していけば、うまい選手の戦術・戦略を学習できそうです。

初心者のために使うのであれば、戦術・技を教えるときに、可視化されていれば、理解が深まるでしょう。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)