2016年にCVPRで発表されたLSBP手法をGoogle Summer of Code(GSoC)で改良した背景差分の手法を用いる。
概要
背景差分法の説明
GSoCで開発された背景差分法がなんだかいいという噂を聞いた。別に従来の背景差分法でもなんら問題ない現象もあるが、高精度で動体を判別してくれるらしい。
他の手法との比較は、以下のサイトに詳しく書いてあったので、参考にするといい。
動体の検出と重ね合わせ
背景差分を用いることで、動体と静止背景を分離できる。これを用いて、もとの背景に動体を重ね合わせていくことを考える。
いわゆる陸上選手の走りの軌跡や、野球のボールの投球軌跡などを一枚の合成写真で見やすくした画像を生成する。
以下のリンク先にある、体操選手の試技の軌跡のようなものを最終的に作成する。
実装
それでは実装してみた。
#!/usr/bin/env python3 #! -*- coding: utf-8 import cv2 import numpy as np import sys from PIL import Image from argparse import ArgumentParser def get_option(): argparser = ArgumentParser() argparser.add_argument('input', type=str, help='Absolute/relative path to input file') argparser.add_argument('-f', '--frame', type=int, default=3, help='Number of interval frame') argparser.add_argument('-s', '--start', type=int, default=0, help='Time of union start') args = argparser.parse_args() return args def unimove(inputFile, frameNum, startTime): cap = cv2.VideoCapture(inputFile) bgs_gsoc = cv2.bgsegm.createBackgroundSubtractorGSOC() cap.set(0, startTime * 1000) i = 0 while(cap.isOpened()): ret, frame = cap.read() maskIm = bgs_gsoc.apply(frame) bg = bgs_gsoc.getBackgroundImage() fg = cv2.bitwise_and(frame,frame, mask=maskIm) cv2.imshow('fg', fg) cv2.imshow('bg', bg) if i == 0: union = frame elif i % frameNum == 0: union = unionFgBg(maskIm, fg, union) cv2.imshow('union', union) k = cv2.waitKey(1) & 0xFF if k == ord('q'): cv2.destroyAllWindows() exit() elif k == ord('w'): fileName = '../' + str(i) + '.jpg' cv2.imwrite(fileName, union) i += 1 def unionFgBg(mask, fg, union): notMask = cv2.bitwise_not(mask) maskedBg = cv2.bitwise_and(union, union, mask=notMask) res = fg + maskedBg return res if __name__ == '__main__': args = get_option() inputFile = args.input frame = args.frame startTime = args.start unimove(inputFile, frame, startTime)
セットアップと使い方
セットアップ
想定する使用環境は下記のとおりである。
OS: Ubuntu18.04 Python: 3.6, 3.7 OpenCV:3.4.3
pythonをインストールしていなかったら、下記の記事を参考にインストールしよう。
www.komee.org
そしてOpenCVをセットアップする必要がある。これは以前書いた記事を参考にインストールしよう。
www.komee.org
もしもう既にOpenCVはセットアップ済みで必要ないよ!という人も、opencv_contribという追加パッケージをインストールしてもらう必要がある。
次のコマンドでインストール。(以前書いた記事ではついでにインストールしてある)
$ pip3 install opencv-contrib-python
また、実行するに当たって必要なpythonパッケージもインストールする。
$ pip3 install Image
これで使用環境は整った。
使い方
$ python unimove.py [動画のパス] [ -f 合成するフレーム間隔のフレーム枚数] [ -s スタート時刻]
動画のパスは必須項目である。
フレーム枚数、スタート時刻に関してはそれぞれ-f
、-s
で指定して変更できるようにしてあるが、オプション引数である。何も指定しなかった場合、それぞれ3と0がセットされるようになっている。
動かしてみた
次の動画を素材にして、移動軌跡を合成してみた。
元画像
合成画像
精度はカメラの性能に応じて甘くなっているが、カメラの設定を変えたり、色しきい値でもう少しブラッシュアップすれば、よりよい移動軌跡を合成可能である。
まとめ
今回実装したソースコードは以下のgithubに公開している。
github.com
ソースコードを読むとわかるが、背景と全景の重ね合わせはあまり上手な方法では記述していない。というのも、やっつけで作ってしまったため、いい方法が思い浮かばず、気合で合成してしまったからである。
改良、改善はフォークして自由にやってほしいし、こうした方がいいんじゃない?というプルリクも大いにお待ちしております。