0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

OpenCV2で物体追跡 〜 特徴点の移動軌跡をフレーム画像から切離してウインドウに動画出力

Last updated at Posted at 2021-07-18

__前に書いた記事__でうまく動いたスクリプトを微修正して、次の3つのWindowに、OpenCV2の物体追跡の異なる出力結果を出してみました。

前回の記事に引き続いて、次の記事で公開されているコードを参考にしました。

##今回、出力した3つの画面

( Window )

通常、OpenCV2から出力されるのは、この画面です。

スクリーンショット 2021-07-18 15.21.26.png

( Window 2 )

ある時点で読み込まれたフレーム画像に対して、OpenCV2が検出した特徴点を円い点で表示した画像です。

スクリーンショット 2021-07-18 15.21.45.png

( Window 3 )

OpenCVが、__このタイムフレーム時点までに認識した(各特徴点の)軌道線(feature points trejectory)__です。

スクリーンショット 2021-07-18 15.21.33.png

###( 後日追記 )

3つの画像を1つのウィンドウに出力してみました。
(4分割画面の右下は黒画面)

##( 実装コード )

new_optical_flow2.py
import numpy as np
import cv2
import argparse    

# 動画ファイル名をコマンドライン引数から受け取る
parser = argparse.ArgumentParser(description='')    #
parser.add_argument('file_name')  
args = parser.parse_args()  

movie_file = args.file_name
print('次の動画ファイルを解析します。 :' + movie_file)
cap = cv2.VideoCapture(movie_file)

# Shi-Tomasiのコーナー検出パラメータ
feature_params = dict( maxCorners = 100,
                    qualityLevel = 0.3,
                    minDistance = 7,
                    blockSize = 7 )

# Lucas-Kanade法のパラメータ
lk_params = dict( winSize  = (15,15),
                  maxLevel = 2,
                  criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# ランダムに色を100個生成(値0~255の範囲で100行3列のランダムなndarrayを生成)
color = np.random.randint(0, 255, (100, 3))

# 最初のフレームの処理
end_flag, frame = cap.read()
gray_prev = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
feature_prev = cv2.goodFeaturesToTrack(gray_prev, mask = None, **feature_params)
mask = np.zeros_like(frame)

while(end_flag):
    if feature_prev is None:
	    print("フレームに追跡すべき特徴点が見つかりませんでした。")
	    break
    
    # グレースケールに変換
    gray_next = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    
    # オプティカルフロー検出
    feature_next, status, err = cv2.calcOpticalFlowPyrLK(gray_prev, gray_next, feature_prev, None, **lk_params)
    
    # フレーム前後でトラックが成功した特徴点のみを
    if feature_next is None:
        print("フレームに追跡すべき特徴点が見つからなくなりました。")
        break

    # オプティカルフローを検出した特徴点を選別(0:検出せず、1:検出した)
    good_prev = feature_prev[status == 1]
    good_next = feature_next[status == 1]
    
    # オプティカルフローを描画
    for i, (next_point, prev_point) in enumerate(zip(good_next, good_prev)):
        prev_x, prev_y = prev_point.ravel()
        next_x, next_y = next_point.ravel()
        mask = cv2.line(mask, (int(next_x), int(next_y)), (int(prev_x), int(prev_y)), color[i].tolist(), 2)
        frame = cv2.circle(frame, (int(next_x), int(next_y)), 5, color[i].tolist(), -1)
    
    img = cv2.add(frame, mask)

    # ウィンドウに表示
    cv2.imshow('window', img)
    cv2.imshow('window2', frame)
    cv2.imshow('window3', mask)

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

    # 次のフレーム、ポイントの準備
    gray_prev = gray_next.copy()
    feature_prev = good_next.reshape(-1, 1, 2)
    end_flag, frame = cap.read()

# 終了処理
cv2.destroyAllWindows()
cap.release()

##実行画面

Terminal
electron@diynoMacBook-Pro optical_flow % python3 new_optical_flow2.py dance.mp4                             
次の動画ファイルを解析します。 :dance.mp4
^Z
zsh: suspended  python3 new_opt.py dance.mp4
electron@diynoMacBook-Pro optical_flow % exit

###使った動画ファイル(MP4)

Terminal
electron@diynoMacBook-Pro % youtube-dl -F https://youtu.be/T0valuAksuo                    
[youtube] T0valuAksuo: Downloading webpage
[info] Available formats for T0valuAksuo:
format code  extension  resolution note
249          webm       audio only tiny   52k , webm_dash container, opus @ 52k (48000Hz), 1.29MiB
250          webm       audio only tiny   68k , webm_dash container, opus @ 68k (48000Hz), 1.70MiB
140          m4a        audio only tiny  129k , m4a_dash container, mp4a.40.2@129k (44100Hz), 3.20MiB
251          webm       audio only tiny  134k , webm_dash container, opus @134k (48000Hz), 3.33MiB
394          mp4        256x144    144p   70k , mp4_dash container, av01.0.00M.08@  70k, 30fps, video only, 1.74MiB
278          webm       256x144    144p   92k , webm_dash container, vp9@  92k, 30fps, video only, 2.28MiB
160          mp4        256x144    144p  104k , mp4_dash container, avc1.4d400c@ 104k, 30fps, video only, 2.59MiB
395          mp4        426x240    240p  153k , mp4_dash container, av01.0.00M.08@ 153k, 30fps, video only, 3.80MiB
242          webm       426x240    240p  216k , webm_dash container, vp9@ 216k, 30fps, video only, 5.34MiB
133          mp4        426x240    240p  243k , mp4_dash container, avc1.4d4015@ 243k, 30fps, video only, 6.01MiB
396          mp4        640x360    360p  329k , mp4_dash container, av01.0.01M.08@ 329k, 30fps, video only, 8.14MiB
243          webm       640x360    360p  396k , webm_dash container, vp9@ 396k, 30fps, video only, 9.80MiB
134          mp4        640x360    360p  588k , mp4_dash container, avc1.4d401e@ 588k, 30fps, video only, 14.53MiB
397          mp4        854x480    480p  611k , mp4_dash container, av01.0.04M.08@ 611k, 30fps, video only, 15.10MiB
244          webm       854x480    480p  734k , webm_dash container, vp9@ 734k, 30fps, video only, 18.14MiB
135          mp4        854x480    480p 1007k , mp4_dash container, avc1.4d401f@1007k, 30fps, video only, 24.88MiB
398          mp4        1280x720   720p 1246k , mp4_dash container, av01.0.05M.08@1246k, 30fps, video only, 30.80MiB
247          webm       1280x720   720p 1472k , webm_dash container, vp9@1472k, 30fps, video only, 36.38MiB
136          mp4        1280x720   720p 1963k , mp4_dash container, avc1.4d401f@1963k, 30fps, video only, 48.49MiB
399          mp4        1920x1080  1080p 2326k , mp4_dash container, av01.0.08M.08@2326k, 30fps, video only, 57.47MiB
248          webm       1920x1080  1080p 2588k , webm_dash container, vp9@2588k, 30fps, video only, 63.92MiB
137          mp4        1920x1080  1080p 4141k , mp4_dash container, avc1.640028@4141k, 30fps, video only, 102.30MiB
18           mp4        640x360    360p  742k , avc1.42001E, 30fps, mp4a.40.2 (44100Hz), 18.35MiB (best)
electron@diynoMacBook-Pro optical_flow % 
Terminal
electron@diynoMacBook-Pro optical_flow % youtube-dl -f18 -o dance.mp4 https://youtu.be/T0valuAksuo
[youtube] T0valuAksuo: Downloading webpage
[download] Destination: dance.mp4
[download] 100% of 18.35MiB in 00:02
electron@diynoMacBook-Pro optical_flow % ls
768x576.avi		fi.mp4			opt_flow_test.py	test.py			trump.mp4
dance.mp4		new_opt.py		optical_flow.py		trial.py
doraemon.mp4		olynpic.mp4		pedestrian.mp4		trump.avi
electron@diynoMacBook-Pro optical_flow % 
electron@diynoMacBook-Pro optical_flow % python3 new_opt.py dance.mp4                             
次の動画ファイルを解析します。 :dance.mp4
^Z
zsh: suspended  python3 new_opt.py dance.mp4
electron@diynoMacBook-Pro optical_flow % exit

##( 4分割ウィンドウ出力版の実装コード )

new_optical_flow3.py
import numpy as np
import cv2
import argparse    

# 動画ファイル名をコマンドライン引数から受け取る
parser = argparse.ArgumentParser(description='')    #
parser.add_argument('file_name')  
args = parser.parse_args()  

movie_file = args.file_name
print('次の動画ファイルを解析します。 :' + movie_file)
cap = cv2.VideoCapture(movie_file)

# Shi-Tomasiのコーナー検出パラメータ
feature_params = dict( maxCorners = 100,
                    qualityLevel = 0.3,
                    minDistance = 7,
                    blockSize = 7 )

# Lucas-Kanade法のパラメータ
lk_params = dict( winSize  = (15,15),
                  maxLevel = 2,
                  criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# ランダムに色を100個生成(値0~255の範囲で100行3列のランダムなndarrayを生成)
color = np.random.randint(0, 255, (100, 3))

# 最初のフレームの処理
end_flag, frame = cap.read()
gray_prev = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
feature_prev = cv2.goodFeaturesToTrack(gray_prev, mask = None, **feature_params)
mask = np.zeros_like(frame)

while(end_flag):
    if feature_prev is None:
        print("フレームに追跡すべき特徴点が見つかりませんでした。")
        break

    # グレースケールに変換
    gray_next = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # オプティカルフロー検出
    feature_next, status, err = cv2.calcOpticalFlowPyrLK(gray_prev, gray_next, feature_prev, None, **lk_params)

    # フレーム前後でトラックが成功した特徴点のみを
    if feature_next is None:
        print("フレームに追跡すべき特徴点が見つからなくなりました。")
        break

    # オプティカルフローを検出した特徴点を選別(0:検出せず、1:検出した)
    good_prev = feature_prev[status == 1]
    good_next = feature_next[status == 1]

    # オプティカルフローを描画
    for i, (next_point, prev_point) in enumerate(zip(good_next, good_prev)):
        prev_x, prev_y = prev_point.ravel()
        next_x, next_y = next_point.ravel()
        mask = cv2.line(mask, (int(next_x), int(next_y)), (int(prev_x), int(prev_y)), color[i].tolist(), 2)
        frame = cv2.circle(frame, (int(next_x), int(next_y)), 5, color[i].tolist(), -1)

    img = cv2.add(frame, mask)

    # 背景黒の画面。zerosの引数がheightが先になるので注意
    height_ = frame.shape[0]
    width_ = frame.shape[1]
    black_bachground_img = np.zeros((height_, width_, 3),np.uint8)

    # ウィンドウに表示
    #cv2.imshow('window', img)
    #cv2.imshow('window2', frame)
    #cv2.imshow('window3', mask)
    
    # 4つの画像を1つのウィンドウに組込む
    merged_image_group_1 = cv2.hconcat((frame, img))
    merged_image_group_2 = cv2.hconcat((mask, black_bachground_img))
    height = merged_image_group_1.shape[0]
    width = merged_image_group_1.shape[1]
    
    resized_output_img_1 = cv2.resize(merged_image_group_1, (int(1.7*width), int(1.7*height)))
    resized_output_img_2 = cv2.resize(merged_image_group_2, (int(1.7*width), int(1.7*height)))
    final_output_image = cv2.vconcat((resized_output_img_1, resized_output_img_2))
    
    cv2.namedWindow("Video", cv2.WINDOW_NORMAL)
    cv2.imshow("Video", final_output_image)

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

    # 次のフレーム、ポイントの準備
    gray_prev = gray_next.copy()
    feature_prev = good_next.reshape(-1, 1, 2)
    end_flag, frame = cap.read()

# 終了処理
cv2.destroyAllWindows()
cap.release()

####実行コード

Terminal
electron@diynoMacBook-Pro optical_flow % python3 new_optical_flow3.py dance.mp4
次の動画ファイルを解析します。 :dance.mp4

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?