画像処理のベストプラクティスを共有したいと思います。 最近、私は「スマートホーム」用のホームサーバーを作成し、ビデオ監視から始めました。
タスクはそれほど簡単ではありませんでした。 すべてのビデオ監視については、(誰かが興味を持っている場合)個別に記述します。次に、「2つのフレームの比較による動きを決定するアルゴリズム」というトピックに触れたいと思います。
このアルゴリズムは、カメラからのビデオの記録を有効(無効)にするために必要です。
ネット上でこのトピックに関する情報はあまりありません。 元のアルゴリズムは自分で発明しました(非常に単純です)。記事「ビデオ画像の影を検出するアルゴリズム」は、改善に役立ちました。
この記事では、アルゴリズムについてのみ説明します(プログラミング言語の例なし)。 アルゴリズム全体はサイクルに基づいており、すべてが基本であり、お気に入りのプログラミング言語で簡単に再作成できます。
アルゴリズムの説明に、「ライブ」テーブルと発明されたテーブルの両方の例を示します(理解のため)。
基本的なアルゴリズム
- 1.ビデオカメラから最後の2フレームを取得します。
フレーム1およびフレーム2。例として撮影した写真。 2番目のフレーム「太陽が出てきた」(明るさの増加)では、壁と床にグレアが現れました。 女の子がテーブルに座って、影が彼女から落ち始めました。
- 2.画像をブロックに分割し、それらの平均色値を取得します。
ブロックに分割する理由。 たとえば、640x480を10x10ブロックに分割し、各ブロックから25ピクセルを取得します)。 〜300,000ピクセルと反復の代わりに、合計〜3,000反復と〜75,000ピクセルの分析が得られます。 そのような単純化は、動きを決定するために許可される場合があります。
- 3.結果の2つのカラーテーブル(行列)を比較し、3番目のテーブルの各ブロックの色の差を取得します。
MoveMaskと呼びましょう
- 4. 3番目のテーブルをノイズからフィルタリングします。
これは、「デルタ」の選択を通じて行われます。 画像の変更箇所にあるそれらのブロックでフラグを取得しました。
(1)-「デルタ」の使用(この例では、2を引く)
(2)-完成したマスクへの移行
実際のフレームでのマスキング(画像の変更)の例。
- 5. MoveMaskを使用して、画像の変更の「強度」を考慮します。
これを行うには、隣接するブロックを水平方向に合計し(ノイズからのクリーニングに耐えた自立型ブロックを取り除きます)、同じアルゴリズムで行の合計をすでに垂直方向に合計します。 変更されたブロック(近く)の受信量と、「動きあり」フラグの選択されたしきい値に基づいて、トリガーが構成されます。
たとえば、このようなMoveMaskを計算しましょう
この例では、変更の「強度」は12です。同じ変更の「強度」は、ブロックのサイズに応じて異なります。 したがって、ブロックのサイズとしきい値(トリガーがトリガーされる「強制」の値)は、相互に相対的に設定されます。
このアルゴリズムの利点:プログラミングの容易さ、低リソース消費、優れた感度(わずかな動きを見逃しません)。
唯一の欠点があります-照明の変化でトリガーします。 アルゴリズム全体が色分析に基づいているため、曇りの天気では、雲の後ろから太陽が出て部屋が非常に明るくなることを簡単に監視できます。 この時点で、画像全体のブロックが処理されています。 アルゴリズムのステップ4で、過大評価された「デルタ」を持つマスクを示しました。 実際には、動作中のデルタを使用したこの例(p。1を参照)では、マスクはフレーム全体をほぼ閉じます。
(アルゴリズムのパラグラフ4のように)デルタが過大評価されている場合、これは感度に大きく影響し、モーションセンサーは薄暗いオブジェクトで動作しなくなる可能性があります。
したがって、私は問題の解決策を探し始め、喜びのためにハブにヒントを見つけました(本文の最初のリンクを参照)。 アルゴリズムがオブジェクト(透明ではない)でのみ動作するようにしたかったのですが、女の子からの透明な影と壁や床の光がモーションセンサーを動作させませんでした。
改善されたアルゴリズム
- 1.ビデオカメラから最後の2フレームを取得します。
フレーム1およびフレーム2
- 2.画像をブロックに分割し、それらの平均色値を取得します。
- 3.結果の2つのカラーテーブル(行列)を比較し、3番目のテーブルの各ブロックの色の差を取得します。
- 4. 3番目のテーブルをノイズからフィルタリングします。
結果のテーブルにMoveMaskという名前を付けましょう。
- 5.このステップでは、各ブロック付近の平均値の表を取得します (画像を参照)。
ポイントの周りの平均的な背景のようなものを取得します。
番号を持つブロックと隣接するブロックが合計されます(ドットでマークされています)。 より多くの隣接ブロックを取ることができます。 平均値は番号付きのブロックに配置されます。 テーブルはAvFrame(1および2)と呼ばれます。
- 6.手順5で取得した値の差の表を作成し、「デルタ」でフィルタリングします。
同様に、最初のアルゴリズムのパラグラフ3のフレームと同様。 そこの図を参照してください。
このマスクは実際のフレームで表示されます。
- 7.ここで、「相対相関」と呼ばれる乗算を行います (冒頭に示した記事を参照)。
セルに次の計算結果を書き込むテーブルを作成します| frame1 [x] [y] x AvFrame2 [x] [y]-frame2 [x] [y] x AvFrame1 [x] [y] |。 ここでも、「デルタ」でフィルタリングします。
つまり 最初のフレームのブロックの色に同じブロックの平均値を掛けますが、2番目のフレーム、同様に2番目のフレームのブロックの色に最初のフレームの平均を掛け、差を求めます。
このマスクは実際のフレーム上にあります。
- 8.ここで、p。6およびp。7の表を横断します。
両方のテーブルで正のセルにのみ、結果のテーブルに算術平均を入れます(MaskFilterと呼びましょう)。
こんな写真が撮れます
- 9. MoveMaskをMaskFilterフィルターでフィルター処理します。
MoveMaskには、MaskFilterの同じ位置にある(または並んでいる)ブロックのみを残します。
画像でフィルターされたMoveMask。 最初のアルゴリズムのパラグラフ4と比較してください。
- 10.さらに(オプション)、近隣が少ない(たとえば、4未満)ブロックを削除して、MoveMaskをフィルター処理することもできます。
マスクの最終的な外観。
- 11.最後に、完成したMoveMaskテーブルを使用した変更の「強度」を考慮します。
最初のアルゴリズムのパラグラフ5を参照してください。
MaskFilterフィルターでMoveMaskをフィルター処理するこのアルゴリズムでは、シャドウまたはグレアによってトリガーされるほとんどのブロックをMoveMaskから削除します。 センサーの誤動作を2倍以上減らすことができます。
欠点のうち、膨大な数の「デルタ」と、アルゴリズムのプログラミングと調整の両方の複雑さ。
基本的なアルゴリズムと改善されたアルゴリズム。
この例では、壁と窓の影、まぶしさは完全に除去されました。 床のまぶしさは「やり過ぎ」であり、消えませんでした。 しかし、おそらく、「デルタ」の1つを修正したこの部屋では、床からのフレアを無視するようにフィルターを構成できます。 異なる部屋-アルゴリズムの異なる調整。
他にどのようにアルゴリズムを改善できますか?
RGBをHSVに変換し、輝度チャンネルなしで動作させようとする場合、アルゴリズムの精度を上げることができます。 手はまだチェックしていません。
私の経験とこのアルゴリズムの説明が誰かに役立つことを願っています。 そして、補足、修正、提案があれば-聞いてうれしいです。