【C++】OpenCVを使った動画内動作検出の実用テクニック
C++とOpenCVを使うことで、動画内の微細な動きを捉えられる手法が実現できます。
オプティカルフローは画素の移動を追跡し、背景差分法は動く対象を抽出する仕組みです。
両手法の組み合わせにより、監視や産業用途に適した効率的な動きの検出が可能です。
オプティカルフローによる動画内動作検出
動作検出の基本原理
オプティカルフローは、連続する画像同士の間で各画素の動きを推定する技術です。
画素の輝度の変化から、動いている方向や速度を数値化することが可能です。
基本的な数式は
という関係や、微分を用いた
といった形で記述され、局所的な平滑性を仮定して計算が進む仕組みになっています。
実際の実装では、画像の階層表現(ピラミッド)を用いて、幅広い動きを扱えるように調整されています。
主要なアルゴリズム詳細
Lucas-Kanade法の流れ
Lucas-Kanade法は、特徴点の局所領域内で動きを検出する方法で、動きの小さい領域において高い精度が期待できる手法です。
最初に特徴点を抽出し、各特徴点の追跡対象となる近傍領域を設定して、輝度値の差分から動きを計算します。
例えば、以下のサンプルコードはcv::calcOpticalFlowPyrLK
関数を用いて、動画内の特徴点を追跡する例です。
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/video/tracking.hpp>
using namespace cv;
using namespace std;
int main() {
VideoCapture cap("input.mp4");
if (!cap.isOpened()) {
cout << "動画ファイルが開けませんでした" << endl;
return -1;
}
Mat frame, gray, prevGray;
vector<Point2f> prevPts, nextPts;
// 最初のフレームからグレースケール画像に変換し、特徴点を抽出
cap >> frame;
if (frame.empty()) {
cout << "フレームが空です" << endl;
return -1;
}
cvtColor(frame, prevGray, COLOR_BGR2GRAY);
goodFeaturesToTrack(prevGray, prevPts, 100, 0.3, 7);
while (true) {
cap >> frame;
if (frame.empty())
break;
cvtColor(frame, gray, COLOR_BGR2GRAY);
vector<uchar> status;
vector<float> err;
// オプティカルフローの計算で特徴点の移動を検出
calcOpticalFlowPyrLK(prevGray, gray, prevPts, nextPts, status, err);
// 追跡に成功した点に対して円を描画
for (size_t i = 0; i < nextPts.size(); i++) {
if (status[i]) {
circle(frame, nextPts[i], 3, Scalar(0, 255, 0), -1);
}
}
imshow("Optical Flow", frame);
if (waitKey(30) == 27)
break;
// 次のフレームのために更新
prevGray = gray.clone();
prevPts = nextPts;
}
cout << "光学フロー検出の処理が終了しました" << endl;
return 0;
}
動画ファイルが読み込まれ、ウィンドウに動きの検出結果が表示されます
ESCキーを押すと処理が終了します
光学フロー検出の処理が終了しました
Lucas-Kanade法は、比較的小さい動きを捉えやすく、リアルタイムな処理に適している点が魅力です。
特徴点抽出の方法や追跡精度の向上のために、パラメーターの調整が重要となります。
Horn-Schunck法の特徴
Horn-Schunck法は、画像全体の輝度変化に基づいて、すべての画素に対して連続的な動きのベクトルを求める手法です。
局所的な情報だけでなく、グローバルな平滑性の仮定を取り入れるため、ノイズの多い状況でも安定した結果が得られる可能性があります。
正則化項を導入することで、計算された動きのベクトルが滑らかに変化するように調整している点が特徴です。
特殊なシーンやカメラ動作の場合、Lucas-Kanade法では十分な結果が得られない場合に、Horn-Schunck法の採用を検討しても良いでしょう。
数式で示すと、正則化項付きの最適化問題は
という形になるため、制約条件の設定が計算結果に大きな影響を及ぼします。
パラメーター設定の工夫
ウィンドウサイズとピラミッドレベルの調整
オプティカルフローを実装する際、ウィンドウサイズやピラミッドレベルの設定は非常に大切です。
ウィンドウサイズが小さすぎると、局所的なノイズの影響が大きくなり、逆に大きすぎると細かい動きが見逃される可能性があります。
適切なピラミッドレベルを設定することで、広い範囲の動きを検出しながら細部の動きも正確に追跡できるようになるため、設定項目の調整が推奨されます。
- 小さいウィンドウサイズ:精細な動きを捉える反面、ノイズに敏感になる
- 大きいウィンドウサイズ:安定した追跡が可能だが、細部の動きが不明瞭になる場合あり
- ピラミッドレベル:画像の縮小比率と階層数を調整して、対象の動きの量に合わせる
計算精度と速度のバランス
リアルタイム処理では、計算速度と精度のバランスが重要です。
例えば、特徴点の数や追跡対象領域のサイズを調整することで、処理速度を向上させつつ、必要最低限の精度を確保することが可能になります。
処理負荷が大きい場合は、以下の点を検討することが有効です。
- 追跡する特徴点の数を絞る
- 画像解像度の低減による計算量削減
- マルチスレッド処理やGPU活用による並列計算
こうしたパラメーターの調整は、アプリケーションの目的や使用環境に合わせて最適化する必要があり、シーンごとに細かく設定を変更する工夫が求められます。
背景差分法による動画内動作検出
背景モデリングの考え方
背景差分法は、動画内の静的な背景と動いている前景を分離する技術です。
背景画像をモデル化し、各フレームと背景の差分を計算することで、動いている部分を抽出します。
多くの場合、背景の静止部分に対して確率的なモデルを構築することで、徐々に変化する環境にも対応するようになっています。
MOG2の仕組み
MOG2は、Gaussian混合モデルを利用して背景を表現する手法です。
各画素ごとに複数のガウス分布を用い、背景と前景の区別を行います。
MOG2は、照明変化や影の影響を受けにくい特徴があり、比較的複雑な背景環境でも安定した検出が可能です。
下記のサンプルコードは、cv::createBackgroundSubtractorMOG2
を利用した背景差分の実装例です。
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main() {
VideoCapture capture("input.mp4");
if (!capture.isOpened()) {
cout << "動画ファイルが開けませんでした" << endl;
return -1;
}
Ptr<BackgroundSubtractor> pBackSub;
pBackSub = createBackgroundSubtractorMOG2();
Mat frame, fgMask;
while (true) {
capture >> frame;
if (frame.empty())
break;
// 背景差分法で動いている部分を検出
pBackSub->apply(frame, fgMask);
// ノイズ除去のためGaussianBlurを適用
GaussianBlur(fgMask, fgMask, Size(5, 5), 0);
imshow("FG Mask MOG2", fgMask);
if (waitKey(30) == 27)
break;
}
cout << "背景差分法による動作検出が終了しました" << endl;
return 0;
}
動画ファイルが読み込まれ、ウィンドウに前景マスクが表示されます
ESCキーを押すと処理が終了します
背景差分法による動作検出が終了しました
MOG2は、動く物体の検出において高い柔軟性を持ち、背景の変化にも耐性を示す点が魅力です。
複数の分布を使うことで、環境の変化に順応しながら背景と前景を分離しやすい設計になっています。
KNNアルゴリズムの動作
KNN(k-Nearest Neighbors)アルゴリズムは、背景差分の手法の一つとして利用される場合があります。
KNNでは、過去のフレームから類似度の高い背景サンプルを探索し、現在のフレームと比較して差分を求めます。
この手法は、急激な照明変化や動的な背景に対しても柔軟に対応できるという利点があります。
KNNは、背景の更新頻度やサンプル数の調整によって、検出精度が大きく変動するため、使用する際はシーンに合わせたパラメーター調整が重要になります。
前処理とノイズ除去技術
動画から得られる各フレームは、カメラのノイズや照明条件の変化により多少の乱れが発生することが多いです。
こうしたノイズが動きの検出結果に影響を及ぼさないよう、前処理とノイズ除去が必要です。
主な技術として以下の方法が挙げられます。
- Gaussian Blurによる平滑化処理
差分処理を行う前に、画像全体のノイズを低減し、不要な小さな動きの誤検出を防ぐ効果があります。
- モルフォロジカル演算の活用
膨張処理や収縮処理を組み合わせることで、前景の輪郭がはっきりして、動いている領域の抽出精度が向上します。
- ヒストグラム均一化
明暗のばらつきを補正するために、画像全体の輝度分布を平坦化し、背景と前景の差分を明確にする方法も有用です。
こういった前処理を適切に行うことで、各アルゴリズムの性能がより安定し、実際のシーンに応じた結果が得られるようになります。
アルゴリズムの比較と選択基準
特性と適用シーンの比較
利点と制約
それぞれの手法には、利用する上でのメリットと制約が存在します。
以下は代表的な違いを箇条書きにしたものです。
- オプティカルフロー
- 瞬間的な動きをピンポイントで検出できる
- 計算速度が速く、リアルタイム処理に適用可能
- 特徴点が少ないシーンや急激な動きには弱い場合がある
- 背景差分法
- 動いている領域全体を抽出しやすい
- 照明条件や背景の変化に対する耐性がある
- 背景モデルの更新が遅れると、急激な変化に追随しにくい
これらの特徴を踏まえ、実際の適用場面では、監視カメラや交通量モニタリングなど目的に合わせた手法の選択が求められます。
シーン別の適用事例
シーンによっては、どちらかの手法がより有効に働く場合があります。
例えば、
- 屋内の一定の照明下や固定カメラでの監視には、オプティカルフローを用いると細かな動きの検出が可能です
- 屋外で背景が複雑な場合や、照明変化が頻繁に起こる環境には、背景差分法を導入することでより安定した動体検出が実現できる可能性があります
また、実際のシステムでは両者を組み合わせ、各手法の強みを生かす連携が行われるケースもあります。
精度向上のポイント
複数手法の連携
単一の手法では検出精度に限界が生じるケースもあるため、オプティカルフローと背景差分法を組み合わせる案も検討できます。
連携することで、片方が苦手とするノイズや環境変化について補完が期待でき、より安定した動作検出が実現可能です。
たとえば、背景差分法で大まかな前景を抽出し、オプティカルフローでその領域内の詳細な動きを解析する配置が考えられます。
パラメーター最適化
各アルゴリズムは、動作検出の精度に大きく影響するパラメーターを持っています。
手法ごとに最適なウィンドウサイズや学習率、背景更新の頻度などを実環境に合わせて調整することが肝心です。
以下のようなパラメーターの見直しが有効です。
- Lucas-Kanade法での特徴点抽出パラメーター(コーナー検出の閾値など)
- MOG2やKNNの背景更新率および履歴サンプル数
- 計算速度と精度のバランスを保つための、フレームレートや解像度の調整
実環境に合わせたカスタマイズ
実際にシステムを導入する際は、環境特性に合わせたカスタマイズが求められます。
例えば、カメラの設置場所や撮影条件に応じた明暗補正や色補正を事前に行うといった前処理を施すことで、アルゴリズムのパフォーマンスが向上します。
また、リアルタイム性が求められる場合は、可能な限り軽量な処理にするなど、システム全体の設計も合わせた最適化が推奨されます。
アルゴリズム適用時の注意点
光条件やカメラ特性の影響
動作検出の結果は、撮影される環境の光条件やカメラの特性に大きく左右されるため、こうした点へも注意が必要です。
明暗変化への対策
撮影環境での急激な明暗変化は、動体検出の精度に悪影響を及ぼす可能性があります。
- ヒストグラム均一化や輝度補正によって前処理を施す
- カメラの露出設定を固定することで明暗の変動を抑える
これらの工夫により、検出精度が安定しやすくなります。
動き検出の誤差原因
カメラのブレや、対象物の複雑な動きによって誤差や誤検出が発生するケースがあります。
- カメラの手ブレ補正機能を活用する
- 複数フレームの結果を統合して判断するなど、フィルタ処理の実装が有効です
こうした点に気を配り、システム全体で誤検出リスクを低減することが求められます。
処理負荷とパフォーマンス最適化
リアルタイム処理実現の工夫
動画処理においてリアルタイム性が求められる場合、各アルゴリズムの計算負荷が問題になることがあります。
- マルチスレッド処理やGPUを活用して計算量を分散する
- 不要な処理を省略するため、領域限定抽出(ROI)などを用いる
こうした工夫により、処理遅延の軽減とともに、スムーズな動作検出が期待できます。
計算コストの削減方法
計算負荷の高いアルゴリズムを用いる際には、パラメーターの調整やアルゴリズムの簡略化などによって、計算コストを下げる工夫が必要になります。
- 画像解像度を適切に下げることで、1フレームあたりの処理量を削減
- 特徴点の数や背景モデルの更新頻度を適切に調整する
このように、目的に合わせて必要な部分だけを厳選し、全体の最適化を図る工夫が効果的です。
まとめ
今回の記事では、オプティカルフローと背景差分法という2つの主要な動作検出手法について解説しました。
オプティカルフローは、特徴点の動きを細かく捉えることに優れており、Lucas-Kanade法とHorn-Schunck法という代表的な手法が存在します。
各手法におけるパラメーター調整の工夫が、処理の精度と速度のバランスを取る上で重要であることを理解していただけたら嬉しいです。
一方、背景差分法は、動いている前景と静的な背景を効果的に分離するために利用され、MOG2やKNNアルゴリズムが実装されています。
ノイズ除去や前処理技術を組み合わせることで、環境に応じた精度向上が期待できる点もご参考いただければと思います。
また、複数の手法を連携させたり、シーン別にカスタマイズすることで、より安定した動作検出システムが構築できる可能性があります。
光条件やカメラ特性への注意、さらには計算負荷の最適化など、実際のアプリケーションにおける注意点も各項目ごとに詳細に説明しました。
これらの工夫を取り入れることで、システム全体のパフォーマンスが向上し、用途に合わせた柔軟な対応が行えると思います。