OpenCV 3.4.1で背景差分
背景差分
画像の前景と背景を分離する手法。2013年にOpenCV 2.4.7での背景差分の記事を書いたが、2018年になったいまOpenCV 3.4.1で背景差分を行おうとしたら使えるアルゴリズムが増えていたのでまとめておく。
アルゴリズム
MOG, MOG2, GMG
OpenCV 2.4.7でも使えた。以下のページに日本語でわかりやすい説明がある。
背景差分 — OpenCV-Python Tutorials
KNN
K近傍方に基づく背景差分。前景の画素数が少ない場合は効率が良いらしい。
CNT
低スペックな計算機でもほかのアルゴリズムより高速に処理ができる。CNTという名前は「CouNT」の省略らしい。Raspberry Pi3でのベンチマークではMOG2が41秒に対し、CNTは18秒。
https://sagi-z.github.io/BackgroundSubtractorCNT/
LSBP
Local SVG Binary Pattern。注目画素とその周辺画素の大小関係を符号化するLBP(Local Binary Pattern)は、高速に計算可能な画像特徴量として知られている。局所的なノイズや隣接画素が類似しているような場合にもロバストにするようにSVD(特異値分解)を使った特徴量で背景差分を行っているそう。ちゃんと勉強してないのでよくわらからない。
GSOC
LSBP特徴を使ってる。ノイズ除去とか穴埋めといった後処理をしているらしい。GSOC(Google Summer of Code)2017中で開発されたとかで元論文等はないらしいのでソースコードを読もう。
コード
実行にはopencv_contribが必要。
C++
opencv_contrib
をダウンロードし、opencv
のcmake
時に例えば以下のようにOPENCV_EXTRA_MODULES_PATH
オプションを指定してビルドする。
$ cmake -DOPENCV_EXTRA_MODULES_PATH=<opencv_contrib>/modules -DBUILD_opencv_legacy=OFF <opencv_source_directory>
ソースコード
#include <opencv2/opencv.hpp> #include <opencv2/core/utility.hpp> #include <opencv2/bgsegm.hpp> int main() { // 動画ファイルの読み込み cv::VideoCapture cap = cv::VideoCapture("video.mp4"); // 背景差分器の生成 cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::bgsegm::createBackgroundSubtractorGSOC(); //cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::bgsegm::createBackgroundSubtractorCNT(); //cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::bgsegm::createBackgroundSubtractorGMG(); //cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::bgsegm::createBackgroundSubtractorLSBP(); //cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::bgsegm::createBackgroundSubtractorMOG(); //cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::createBackgroundSubtractorMOG2(); //cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::createBackgroundSubtractorKNN(); while (cv::waitKey(1) == -1) { cv::Mat frame, foreGroundMask, segm; cap >> frame; if (frame.empty()) break; bgfs->apply(frame, foreGroundMask); frame.convertTo(segm, 0, 0.5); cv::add(frame, cv::Scalar(100, 100, 0), segm, foreGroundMask); cv::imshow("output", segm); } return 0; }
Python
pip
で管理している場合、以下のようにopencv-python
をアンインストール後にopencv-contrib-python
をインストールすればopencv_contrib
が使える。
pip uninstall opencv-python pip install opencv-contrib-python
ソースコード
import cv2 cap = cv2.VideoCapture('video.mp4') bgs = cv2.bgsegm.createBackgroundSubtractorLSBP() while(cap.isOpened()): ret, frame = cap.read() mask = bgs.apply(frame) bg = bgs.getBackgroundImage() cv2.imshow('mask', mask) cv2.imshow('bg', bg) if cv2.waitKey(1) != -1: break cap.release() cv2.destroyAllWindows()
適用結果
比較のために各アルゴリズムを並べてみた。パラメータ調整もしてないから比較もくそもない気はするけど。GSOCが綺麗。LSBPはあんまり
あと、背景差分やるだけだったらたぶん以下のページで紹介されているBGSLibraryを使ったほうが良さそうではある。