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


##選択したアルゴリズム

####OpenCV2の組込み関数

- createBackgroundSubtractorMOG

##結果（一部）

他のフレーム画像は、__[こちら](https://github.com/electronicsdiy/electronics_diy721/issues/10)__に掲載しました。
画像に続けて、__考察を掲載__しています。

![](https://user-images.githubusercontent.com/87643752/129712624-9fd3ad4c-9996-4748-ae2f-a5e01b2068c1.png)

![](https://user-images.githubusercontent.com/87643752/129712637-a132e1a5-150e-466b-b24e-9f42940c139f.png)

![](https://user-images.githubusercontent.com/87643752/129712748-89f3fcf8-ccc2-4cd7-91af-1a1474d9aa8a.png)

![](https://user-images.githubusercontent.com/87643752/129712779-dac3f733-31d5-4b20-b3d7-237c2a6c92c1.png)

![](https://user-images.githubusercontent.com/87643752/129712305-4bfe885d-7741-44a9-b782-e86ccefba7f7.png)

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

![](https://user-images.githubusercontent.com/87643752/129712376-cf272f46-dad3-439b-9f81-f8e88d01d0d0.png)

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

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

![](https://user-images.githubusercontent.com/87643752/129712356-33e5607a-8739-42f1-ae3e-ace0b0472c42.png)


![](https://user-images.githubusercontent.com/87643752/129712384-ccbbfe7a-9d45-4534-82ae-12ba3e3493a9.png)

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

![](https://user-images.githubusercontent.com/87643752/129712415-0292e844-5d9a-481b-882a-7e285bf02bb8.png)

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

![](https://user-images.githubusercontent.com/87643752/129712542-acda7ff6-7df2-4b3c-8190-49b90abaff83.png)

![](https://user-images.githubusercontent.com/87643752/129713155-6227c6b7-e073-42f9-967b-1893717ee585.png)

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

![](https://user-images.githubusercontent.com/87643752/129713094-e589b8d6-1f92-44f5-b6e4-906ac9ac34f4.png)

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

![](https://user-images.githubusercontent.com/87643752/129713119-0a538920-63d9-48dc-a868-56f7ffeea87f.png)

![](https://user-images.githubusercontent.com/87643752/129713240-1e463349-c38c-4cd0-9e3b-b8bcd5ae666c.png)

![](https://user-images.githubusercontent.com/87643752/129713338-115687d8-0d08-4e77-922a-b61cde0c6851.png)

![](https://user-images.githubusercontent.com/87643752/129713616-d5a96505-0f66-4d7f-9ae2-a2d44b64d865.png)


![](https://user-images.githubusercontent.com/87643752/129713625-ed72482c-c0dc-4dc3-b2e2-35e614fe591e.png)

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

![](https://user-images.githubusercontent.com/87643752/129713634-2291c1a3-6697-4b1e-9459-280620cd7c2a.png)

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

![](https://user-images.githubusercontent.com/87643752/129713668-f0ef772d-23d7-4656-8fc6-b37a98004ca5.png)

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

![](https://user-images.githubusercontent.com/87643752/129714454-3bc27e79-92ce-4bdd-bcb0-877ea1baf260.png)

![](https://user-images.githubusercontent.com/87643752/129714104-aa466665-2ffa-461f-a0b6-ca93954908ba.png)

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

![](https://user-images.githubusercontent.com/87643752/129714082-8487a02f-991e-4212-b495-785122bd849d.png)

__似たシーンが続いた後__

![](https://user-images.githubusercontent.com/87643752/129714068-87c5d3b6-5f8d-4245-8205-6fa22d25ed41.png)


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

![](https://user-images.githubusercontent.com/87643752/129714117-2b3a3437-a134-40fb-a7b7-1946362e3b61.png)

__似たシーンが続いた後__

![](https://user-images.githubusercontent.com/87643752/129714133-87602f33-1abe-4293-afa5-1be6f12da4bb.png)

##気づいたこと

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

#### 「１」の例　

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

#### 「３」の例　

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

#### 不思議な点

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

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

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

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

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

####アルゴリズムの出典論文

- [An Improved Adaptive Background Mixture Model for Realtime Tracking with Shadow Detection](http://personal.ee.surrey.ac.uk/Personal/R.Bowden/publications/avbs01/avbs01.pdf)

##実装コード

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

- [OpenCV – 背景差分で物体を検出する方法について](https://pystyle.info/opencv-background-substraction/)

```Python3: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()

```

###実行コードの例

```bash:Terminal
% python3 display_moving_objects_erase_background_success_2divided_window.py --file_name indian_dance.mp4
```