はじめに
OpenCV(Open Source Computer Vision Library)はBSDライセンスの映像/画像処理ライブラリ集です。画像のフィルタ処理、テンプレートマッチング、物体認識、映像解析、機械学習などのアルゴリズムが多数用意されています。
OpenCVを使った動体追跡の例 (OpenCV Google Summer of Code 2015)
https://www.youtube.com/watch?v=OUbUFn71S4s
インストールと簡単な使い方はこちら
OpenCV 3(core + contrib)をPython 3の環境にインストール&OpenCV 2とOpenCV 3の違い&簡単な動作チェック
静止画像のフィルター処理についてはこちら
OpenCVでエッジ検出してみる
動画ファイルの処理についてはこちら
OpenCVで動画をリアルタイムに変換してみる
OpenCVでWebカメラ/ビデオカメラの動画をリアルタイムに変換してみる
今回は、定点カメラで撮影した動画を使って背景と動体を分離してみます。
監視カメラで通りがかりの人を追跡するときに、人を抽出する方法として利用することができます。
アルゴリズム
-
背景の抽出方法
フレームに重みづけをしながら重ねていくと、動かない部分が浮かび上がってきます。
単純に足すのではなく、現在のフレームを足しこんだ分、背景のフレームから引き算します。
OpenCVでは、cv2.absdiff()を使います。また、重みづけ計算の誤差を減らすため、浮動小数点(np.float32)を用いて計算します。
- ゼロ埋めした背景フレームを用意する
- 新しい背景 = 背景 × (1 - 重み) + 現在のフレーム × 重み
- ステップ2を繰り返す
-
動体の抽出方法
差分の絶対値が動体フレームになります。
OpenCVでは、sv2.absdiff()を使います。動体フレーム = |現在のフレーム - 背景|
プログラム
import cv2
import numpy as np
# 定数定義
ESC_KEY = 27 # Escキー
INTERVAL= 33 # インターバル
FRAME_RATE = 30 # fps
WINDOW_ORG = "org"
WINDOW_BACK = "back"
WINDOW_DIFF = "diff"
FILE_ORG = "org_768x576.avi"
# ウィンドウの準備
cv2.namedWindow(WINDOW_ORG)
cv2.namedWindow(WINDOW_BACK)
cv2.namedWindow(WINDOW_DIFF)
# 元ビデオファイル読み込み
mov_org = cv2.VideoCapture(FILE_ORG)
# 最初のフレーム読み込み
has_next, i_frame = mov_org.read()
# 背景フレーム
back_frame = np.zeros_like(i_frame, np.float32)
# 変換処理ループ
while has_next == True:
# 入力画像を浮動小数点型に変換
f_frame = i_frame.astype(np.float32)
# 差分計算
diff_frame = cv2.absdiff(f_frame, back_frame)
# 背景の更新
cv2.accumulateWeighted(f_frame, back_frame, 0.025)
# フレーム表示
cv2.imshow(WINDOW_ORG, i_frame)
cv2.imshow(WINDOW_BACK, back_frame.astype(np.uint8))
cv2.imshow(WINDOW_DIFF, diff_frame.astype(np.uint8))
# Escキーで終了
key = cv2.waitKey(INTERVAL)
if key == ESC_KEY:
break
# 次のフレーム読み込み
has_next, i_frame = mov_org.read()
# 終了処理
cv2.destroyAllWindows()
mov_org.release()
実行結果
歩いている人をうまく抽出することができました。