python

動画処理その1

色検出

動画の中から、指定した色のみを検出しマスクをかけてみます。
動画のサンプルは下記のサイトなどで取得できます。
https://wedistill.io/

import cv2
import numpy as np

file_path = 'State-Fair-2013-HD.mp4'
delay = 1
window_name = 'frame'

cap = cv2.VideoCapture('State-Fair-2013-HD.mp4')

while True:
    cv2.namedWindow('img', cv2.WINDOW_NORMAL)
    cv2.resizeWindow('img', 640, 480)
    ret, frame = cap.read()
    if ret == False:
        break 
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    lower = np.array([0, 0, 0]) # ここのパラメータは要調整=>色の指定
    upper = np.array([25, 255, 255]) # ここのパラメータは要調整=>色の指定
    frame_mask = cv2.inRange(hsv, lower, upper)
    dst = cv2.bitwise_and(frame, frame, mask=frame_mask) # 2値画像の論理積
    cv2.imshow('img', dst)
    if cv2.waitKey(delay) & 0xFF == ord('q'):
        break
        
cv2.waitKey(0) & 0xFF
cv2.destroyAllWindows()
cv2.waitKey(1)
cap.release()

オプティカルフロー

オプティカルフローとは、特徴点を見つけて、その特徴点を時間的に追いかけてく画像処理です。
流れとしては、
1、特徴点を見つける
2、特徴点とその周りは同じ方向を向くとして、流れを出す
3、1と2を繰り返す
特徴点を見つける関数は実装されており、それを使用してフローベクトルを求めます。これはモノは物理法則に従って動くという規則性を元に計算されます。

フローベクトルの求め方は数学の知識が必要になってきます。具体的にはTaylor展開について知っておく必要があります。
オプティカルフローを使う分には分からなくても問題ないので、興味がある人だけみておいてください。

import cv2

cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cv2.resizeWindow('img', 1200, 800)
COUNT = 500 # 検出する特徴点の数
criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 40, 0.1) # 収束条件
lk_params = dict(winSize=(10, 10), maxLevel=4, criteria=criteria)
cap = cv2.VideoCapture('161212_031_Vietnam_1080p96fps.mp4')
ret, frame = cap.read()
frame_pre = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
while True:
    ret, frame = cap.read()
    if ret == False:
        break
    frame_now = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    feature_pre = cv2.goodFeaturesToTrack(frame_pre, COUNT, 0.002, 5)
    if feature_pre is None:
        continue
    feature_now, status, err = cv2.calcOpticalFlowPyrLK(frame_pre, frame_now, feature_pre, None, **lk_params)
    for i in range(COUNT):
        pre_x = feature_pre[i][0][0] # x座標
        pre_y = feature_pre[i][0] # y座標
        now_x = feature_now[i][0] # x座標
        now_y = feature_now[i][0] # y座標
        cv2.line(frame, (pre_x,pre_y), (now_x, now_y), (255, 0, 0), 3)
        
    cv2.imshow('img', frame)
    frame_pre = frame_now.copy()
    if cv2.waitKey(20) & 0xFF == ord('q'):
        break
    
cv2.waitKey(0) & 0xFF
cv2.destroyAllWindows()
cv2.waitKey(1)
cap.release()