LoginSignup
2
2

More than 1 year has passed since last update.

OpenCV2で背景差分法 〜 動いている物体は白色、動かない物体は黒色のモノクロ画像に変換した

Last updated at Posted at 2021-08-17

選択したアルゴリズム

OpenCV2の組込み関数

  • createBackgroundSubtractorMOG

結果(一部)

他のフレーム画像は、こちらに掲載しました。
画像に続けて、考察を掲載しています。

前方走行車のテールランプが光った瞬間

数フレーム前に、テールランプが光り始めた後、1秒ほど光り『続けている』シーン

(光り続けており、直前のフレームと同じ状態が継続しているので、黒く消えている。)

(なぜ??)
前のフレームと比べて(ほとんど)変化していないはずの地上の設置物が、白く映っている。

(なぜ??)
前のフレームと比べて(ほとんど)変化していないはずの地上のレーン両端の設置物が、白く映っている。

(なぜ??)
前のフレームと比べて大きく変化しているはずの胸と肩が、白く映っていない。

(なぜ??)
前のフレームと比べて大きく変化しているはずの腕や手のひらが、白く映っていない。

(なぜ??)
前のフレームと比べて、位置や姿勢が激しく変化しているはずの人物が、白く映っていない。

(なぜ??)
前のフレームと比べて、位置や姿勢が激しく変化しているはずの人物が、白く映っていない。

(なぜ??)
前のフレームと比べて、位置や姿勢が激しく変化しているはずの人物が、白く映っていない。

シーンが切り替わった直後

似たシーンが続いた後

シーンが切り替わった直後

似たシーンが続いた後

気づいたこと

  1. 直前のフレームと比較して、位置と形が大きく変わっている領域は、綺麗に白色表示された
  2. 上で白くなった部分も、1秒程度、前のフレームからの変化が乏しくなると、急速に黒色に塗り潰されていく
  3. 動いている部分に隣接する「動きのない」領域は、黒になる

「1」の例 

  • 速い速度で上下左右に平行移動している物体
  • 早い速度で、回転したり、斜め方向や円・楕円運動で位置を変えている物体
  • まったく異なるシーンに切り替わった直後 (画像全体が、直前のフレームとは様変わりしている)

「3」の例 

  • 人間の身体のうち、数秒間にわたって動いていない部位 (手は動いているが、腕や肩や胸は動いていない、など)

不思議な点

  • 直前のフレームばかりか、過去数秒間に表示されたすべてのフレーム画像と比較して動いていない部分で、白く表示される領域があった。(例: F1レーズ会場の背景の看板の文字、レース会場の道路に設置されたフェンスや側溝)
  • 直前のフレームばかりか、過去数秒間に表示されたすべてのフレーム画像と比較して、大きく動いている部分で、黒く表示される領域があった。(例: 滑走路を移動中の戦闘機の両翼や尾翼の縁の内部 (縁だけ、白い線で表示されていた)

なお、人物は、上記の一つ目に該当する領域が、複数の異なる動画で共通して多くみられた。

  • 直前のフレームばかりか、過去数秒間に表示されたすべてのフレーム画像と比較して動いていない部分で、白く表示される領域があった。(例: F1レーズ会場の背景の看板の文字、レース会場の道路に設置されたフェンスや側溝)

上記の初見は、今回採用したOpenCV2のcreateBackgroundSubtractorMOGメソッドに特有のものなのだろうか。

アルゴリズム以外にも、モデル学習時に用いたデータも、関わっているかもしれない。(正解データの作成仕様など)

アルゴリズムの出典論文

実装コード

次のウェブサイトを参考にしました。

display_moving_objects_erase_background_success_2divided_window.py
import numpy as np
import cv2
import argparse
from copy import copy
from copy import deepcopy

#(参考)https://pystyle.info/opencv-background-substraction/
# 動画ファイル名をコマンドライン引数から受け取る
parser = argparse.ArgumentParser(description='')    #
parser.add_argument('--file_name')
args = parser.parse_args()

movie_file = args.file_name

cap = cv2.VideoCapture(movie_file)
#cap = cv2.VideoCapture("kawaguchi_haruna_nomu_cm.mp4")
wait_secs = int(1000 / cap.get(cv2.CAP_PROP_FPS))

model = cv2.bgsegm.createBackgroundSubtractorMOG()

while True:
    ret, frame = cap.read()
    frame_copy = frame.copy()
    #frame_copy = frame.deepcopy()

    if not ret:
        break

    mask = model.apply(frame_copy)

    #cv2.imshow("Mask", mask)
    #cv2.imshow("Original", frame)

    #https://qiita.com/hibit/items/82de8422c7ec3a1aa774
    #https://qiita.com/Makano/items/3148d568e4a523ee7cf8
    #
    mask = cv2.cvtColor(mask,cv2.COLOR_GRAY2BGR)

    left_image = np.array(mask)
    #left_image = left_image.astype('float32')
    right_image = np.array(frame)
    #right_image = right_image.astype('float32')

    # 左右の画像の縦横サイズを揃える
    height = right_image.shape[0]
    width = right_image.shape[1]

    resized_right_image = cv2.resize(right_image, (int(2.0*width), int(2.0*height)))
    resized_left_image = cv2.resize(left_image, (int(2.0*width), int(2.0*height)))

    merged_image = cv2.hconcat((resized_left_image, resized_right_image))

    merged_height = merged_image.shape[0]
    merged_width = merged_image.shape[1]
    #resized_merged_image = cv2.resize(merged_image, (int(10.0*merged_width), int(10.0*merged_height)))

    cv2.namedWindow("Window", cv2.WINDOW_NORMAL)
    cv2.imshow("Window", merged_image)
    #cv2.imshow("Window", resized_merged_image)

    cv2.waitKey(wait_secs)

cap.release()
cv2.destroyAllWindows()

実行コードの例

Terminal
% python3 display_moving_objects_erase_background_success_2divided_window.py --file_name indian_dance.mp4
2
2
1

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
2
2