electronicsdiy / electronics_diy721

electronics_diy721's repository
0 stars 0 forks source link

Motion Vector Visualisation #6

Open electronicsdiy opened 3 years ago

electronicsdiy commented 3 years ago

Having refered to below websites, I just wrote one Python script file.

Output result is as shown below.

F-22 Fifhter movie

スクリーンショット 2021-08-13 1 11 35 スクリーンショット 2021-08-13 1 11 41 スクリーンショット 2021-08-13 1 11 54 スクリーンショット 2021-08-13 1 14 07 スクリーンショット 2021-08-13 1 16 22 スクリーンショット 2021-08-13 1 16 31 スクリーンショット 2021-08-13 1 17 46 スクリーンショット 2021-08-13 1 34 17 スクリーンショット 2021-08-13 1 34 48 スクリーンショット 2021-08-13 1 35 10 スクリーンショット 2021-08-13 1 35 18 スクリーンショット 2021-08-13 1 35 26 スクリーンショット 2021-08-13 1 35 33 スクリーンショット 2021-08-13 1 36 08 スクリーンショット 2021-08-13 1 36 16 スクリーンショット 2021-08-13 1 36 32

Human motion movie

スクリーンショット 2021-08-13 1 10 23

スクリーンショット 2021-08-13 0 58 10

スクリーンショット 2021-08-13 0 58 15 スクリーンショット 2021-08-13 0 58 23 スクリーンショット 2021-08-13 0 58 35 スクリーンショット 2021-08-13 0 58 58 スクリーンショット 2021-08-13 0 59 05 スクリーンショット 2021-08-13 0 59 14 スクリーンショット 2021-08-13 0 59 39

Olympic Equestrian movie

スクリーンショット 2021-08-13 1 05 36

スクリーンショット 2021-08-13 1 05 43

スクリーンショット 2021-08-13 1 06 02

Code to have been run

import numpy as np
import cv2, types, argparse

# https://emotionexplorer.blog.fc2.com/blog-entry-104.html
# https://emotionexplorer.blog.fc2.com/blog-entry-103.html

#以下、初期化定義されないまま使われている
start_sec = 1
end_sec = 100000

# 動画ファイルをコマンドライン引数で受け取るようにする
parser = argparse.ArgumentParser(description='Motion Vector Visualization')
parser.add_argument('--file_path', type=str, help='path to movie file', required=True)
parser.add_argument('--start_frame', type=str, help='frame_step_num to be analizedanalysis', default=1)
args = parser.parse_args()
file_path = args.file_path
start_frame = int(args.start_frame)

# 縮小画像取得
def grab(cap, sc):
    _, frame = cap.read()

    # 画像縮小
    resize_img = cv2.resize(frame, None, fx=sc, fy=sc, interpolation=cv2.INTER_CUBIC)
    return  resize_img

# オプティカルフロー解析描画
def drawOptFlow(img, gray, flow, step=16, dispsc=10):
    cimg    = img.copy()
    h, w    = img.shape[:2]
    y, x    = np.mgrid[step/2:h:step, step/2:w:step].reshape(2,-1).astype(int)
    dx, dy  = flow[y,x].T * dispsc
    dist = np.sqrt(dx**2+dy**2)

    idx     = np.where(3 < dist)
    x, y    = x[idx], y[idx]
    dx, dy  = dx[idx], dy[idx]
    lines = np.vstack([x, y, x+dx, y+dy]).T.reshape(-1, 2, 2)
    lines = lines.astype(np.int32)
    fx, fy = flow[y,x].T
    #print(x) #x, y, dx, dyはそれぞれ行列。空行列のときもある。
    #cv2.polylines(cimg, lines, False, (0, 0, 255),2)
    cv2.polylines(cimg, lines, False, (255, 0, 255), 1, 8)
    #cv2.arrowedLine(cimg, \
    #        pt1=(int(x), int(y)), \
    #        pt2=(int(x+dx), int(y+dy)), \
    #        color=(255, 0, 0),
    #        thickness=2,
    #        line_type=cv2.LINE_4,
    #        shift=0,
    #        tipLength=0.5)

    return cimg

# def optflow(cap, start_sec, end_sec):

def main():
    cap = cv2.VideoCapture(file_path)
    if not cap.isOpened():
        exit()

    # 動画開始フレーム指定(1フレーム30とする)
    fpos = start_frame*30+2
    cap.set(cv2.CAP_PROP_POS_FRAMES, fpos)

    # ShiTomasi cornerパラメータ定義
    feature_params = dict( maxCorners = 100,
                           qualityLevel = 0.2,
                           minDistance = 7,
                           blockSize = 7 )

    # lucas kanade オプティカルフローパラメータ
    lk_params = dict( winSize  = (30,30),
                    maxLevel = 2,
                    criteria=(cv2.TERM_CRITERIA_EPS|cv2.TERM_CRITERIA_COUNT, 10, 0.03))

    ###以上、1本目のサイトのmain()から移植
    ###以下、2本目のサイトのoptflow()から移植
    # 色
    color = np.random.randint(0,255,(100,3))

    # 縮小画像取得
    frame1 = grab(cap, 0.5)
    prvs = cv2.cvtColor(frame1,cv2.COLOR_BGR2GRAY)

    # 動画開始フレーム指定
    fpos = 30 * start_sec
    cap.set(cv2.CAP_PROP_POS_FRAMES, fpos)

    hsv = np.zeros_like(frame1)
    hsv[...,1] = 255

#    loopend = (end_sec - start_sec) * 30
#    for j in range(0, loopend):
    # While Trueに変更
    while True:
        # 縮小画像取得
        frame2 = grab(cap, 0.5)
        next = cv2.cvtColor(frame2,cv2.COLOR_BGR2GRAY)

        # オプティカルフロー解析
        flow = cv2.calcOpticalFlowFarneback(prvs,next, None, 0.5, 3, 15, 3, 5, 1.2, 0)

        # オプティカルフロー解析描画
        rgb2 = drawOptFlow(frame2, next, flow, 16)

        # ウィンドウのサイズが小さいので、大きくする
        height = rgb2.shape[0]
        width = rgb2.shape[1]
        resized_output_img = cv2.resize(rgb2, (int(3.0*width), int(3.0*height)))

        cv2.namedWindow("Video", cv2.WINDOW_NORMAL)
        cv2.imshow("Video", resized_output_img)

        # オプティカルフロー解析描画
        #cv2.imshow('Display',rgb2)

        # ESCキー押下で終了
        k = cv2.waitKey(30) & 0xff
        if k == 27:
            break
        prvs = next

    cap.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    main()