__前に書いた記事__でうまく動いたスクリプトを微修正して、次の3つのWindowに、OpenCV2の物体追跡の異なる出力結果を出してみました。
前回の記事に引き続いて、次の記事で公開されているコードを参考にしました。
##今回、出力した3つの画面
( Window )
通常、OpenCV2から出力されるのは、この画面です。
( Window 2 )
ある時点で読み込まれたフレーム画像に対して、OpenCV2が検出した特徴点を円い点で表示した画像です。
( Window 3 )
OpenCVが、__このタイムフレーム時点までに認識した(各特徴点の)軌道線(feature points trejectory)__です。
###( 後日追記 )
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