OpenCVの画像処理をお手軽に ― OpenCVフィルター処理ライブラリ cvImagePipeline のご紹介
OpenCVの画像処理をお手軽にできるC++向けフィルター処理ライブラリ cvImagePipeline のご紹介。
画像処理の流れや各モジュールのパラメータの指定をXMLで記述できますので、画像処理の処理順の変更やパラメーター調整作業がはかどります。 複数のフィルターを組み合わせて独自のフィルターも作れます。
背景除去のサンプルプログラム
以下の画像は、ライブラリに含まれているサンプルプログラムの実行中画面です。
単純な背景除去の実装実験を行っている画面です。 入力画像や前処理中の画像などを、6分割した画面に統合して表示しています。 (カメラ入力や画面の分割、Window表示もそれぞれ、このライブラリのフィルターです。)
左上から順に、
- キャプチャ画像(の鏡像)
- 1をグレイスケールに変換
- 2に対して、ヒストグラム均一化とガウシアンブラーを適用
- 3の過去18000フレーム分を平均
- 3と4の差分(絶対値差分)
- 5の二値化
このあと、6の二値化画像に対して、膨張(dilate)と縮小(erode)を適当に繰り返してから元画像(1の画像)をマスクすれば背景と前景に分離できそうです。
処理は全てsample.xml
(↓)に記述しており、参考として下に掲載しているC++のコード(capture.cpp
)で読み込んで処理させています。
このためビルド無しで処理を変更可能です。(XMLを読み込む処理は複数のフィルターをまとめるImgProcSet
の機能です)
sample.xml
- 背景除去するXML
<cvImagePipeline name="testProcessor"> <Processor class="VideoCapture" name="cap"> <Property name="deviceIndex" value="0"/> </Processor> <Processor class="Flipper" name="fripHoriz"> <Property name="flipDir" value="1"/> </Processor> <Processor class="ImagePoint" name="raw"/> <Processor class="ColorConverter" name="grayscale"/> <Processor class="EqualizeHist" name="equalizeHist"/> <Processor class="GaussianBlur" name="blur"/> <Processor class="DepthTo32F" name="depth32F"/> <Processor class="ImagePoint" name="pp"/> <Processor class="RunningAvg" name="background"> <Property name="averageCount" value="18000"/> </Processor> <Processor class="AbsDiff" name="diff" autoBind="false"> <Input to="src1" from="pp"/> <Input to="src2" from="background"/> </Processor> <Processor class="Convert" name="to8UC"> <Property name="rtype" value="0"/> <Property name="alpha" value="255"/> <Property name="beta" value="0"/> </Processor> <Processor class="Threshold" name="binary"> <Property name="type" value="CV_THRESH_BINARY"/> <!-- CV_THRESH_BINARY CV_THRESH_BINARY_INV CV_THRESH_TRUNC CV_THRESH_TOZERO CV_THRESH_TOZERO_INV --> <Property name="otsu" value="1"/> <Property name="thresh" value="50"/> <Property name="maxval" value="255"/> </Processor> <Processor class="FitInGrid" name="integratedImage" autoBind="false"> <Property name="width" value="960"/> <Property name="height" value="480"/> <Property name="cols" value="3"/> <Property name="rows" value="2"/> <Property name="interleave" value="0"/> <Input to="0" from="raw"/> <Input to="1" from="grayscale"/> <Input to="2" from="blur"/> <Input to="3" from="background"/> <Input to="4" from="diff"/> <Input to="5" from="binary"/> </Processor> <Processor class="ImageWindow" name="window"> <Property name="windowName" value="cvImagePipeline"/> <Property name="showFPS" value="1"/> </Processor> </cvImagePipeline>
capture.cpp
- XMLを処理するプログラム
#include "stdafx.h" #if defined(_MSC_VER) #include <windows.h> #else #include <unistd.h> #define Sleep(millisec) usleep(millisec * 1000) #endif #include <opencv2/opencv.hpp> #include "cvImagePipeline.h" using namespace cvImagePipeline; using namespace cvImagePipeline::Filter; #if defined(_MSC_VER) int _tmain(int argc, _TCHAR* argv[]) #else int main(int argc, char* argv[]) #endif { cvInitSystem(argc, argv); ImgProcSet processors; std::string xml_filename("sample.xml"); if (argc > 1) { xml_filename = argv[1]; } if (!processors.loadXml(xml_filename)) { std::cerr << "ファイル読み込み失敗 ファイル名:" << xml_filename << std::endl; return -1; } Sleep(2000); while(true) { processors.execute(); int ch = cvWaitKeyEx(1); if (ch == '\x1b') { fprintf(stderr, "exit.\n"); break; } } cvDestroyAllWindows(); return 0; }
リポジトリ
上の例も含めて、その他詳細は下記リポジトリのREADMEを参照してください。
実を言うと、このリポジトリ、1年以上放置しているんですねえ。 しかし今でも Clone してくださる方が月に数人いらっしゃるようです。 READMEが古くなっていて申し訳ないですから、これを機にキチンとメンテしようと思ってはいますが・・・。
そういや以下の記事でもシレッと使っていますねw
今後の課題
今考えつく今後の課題は以下の様なことです。放置している場合ではないなあ。
- OpenCV 3.0以上での動作確認。
- Windows 10 での動作確認。
- 基本フィルタと他のサンプルフィルタの分離。
- 追加実装のしやすさを追求。
- XMLをXAML的文法に変更(記述量を少なくできそう)。
- XMLのビジュアルな編集。
- デバッグ機能の充実。
- 実行中のフィルタのバイパスやパラメータの変更機能。
- Pythonから利用できるインタフェース。C++はやっぱり敷居が高いかも。
- 妙に凝った変な名称のフィルタを改名するw