OpenCV 5.0.0
Open Source Computer Vision
読み込み中...
検索中...
見つかりません
🤖 AIによる機械翻訳(非公式) — これは OpenCV 5.0.0 公式リファレンス(英語)を AI (Claude) で自動翻訳したものです。訳に誤りを含む場合があります。正確な情報は 公式英語版(原文) を参照してください。
バックプロジェクション

前のチュートリアル: ヒストグラムの比較
次のチュートリアル: テンプレートマッチング

原著者Ana Huamán
互換性OpenCV >= 3.0

目標

このチュートリアルでは以下を学ぶ:

  • バックプロジェクションとは何か、そしてなぜ有用なのか
  • バックプロジェクションを計算するためにOpenCVの関数 cv::calcBackProject を使う方法
  • OpenCVの関数 cv::mixChannels を使って画像の異なるチャンネルを混合する方法

理論

バックプロジェクションとは?

  • バックプロジェクションは、与えられた画像のピクセルがヒストグラムモデルのピクセル分布にどれだけ適合するかを記録する手法である。
  • より簡単に言うと: バックプロジェクションでは、ある特徴のヒストグラムモデルを計算し、それを使って画像内でその特徴を見つける。
  • 応用例: 肌の色のヒストグラム(たとえば色相-彩度ヒストグラム)を持っていれば、それを使って画像内の肌色の領域を見つけられる:

どのように動作するのか?

  • 肌の例を使ってこれを説明する:
  • 下の画像をもとに肌のヒストグラム (Hue-Saturation) が得られているとする。横に示すヒストグラムはモデルヒストグラム (肌の色合いのサンプルを表すと分かっているもの) となる。肌の領域のヒストグラムだけを取り出すために、あるマスクを適用している:

  • 次に、下のような別の手の画像 (テスト画像) が得られたとする (それぞれのヒストグラム付き):

  • What we want to do is to use our model histogram (that we know represents a skin tonality) to detect skin areas in our Test Image. Here are the steps
    1. テスト画像の各ピクセル (すなわち \(p(i,j)\) ) について、データを集め、そのピクセルに対応するビン位置 (すなわち \(( h_{i,j}, s_{i,j} )\) ) を求める。
    2. 対応するビン - \(( h_{i,j}, s_{i,j} )\) - についてモデルヒストグラムを参照し、そのビンの値を読み取る。
    3. このビンの値を新しい画像 (BackProjection) に格納する。また、テスト画像に対する出力が見やすくなるよう、あらかじめモデルヒストグラムを正規化しておくとよい。
    4. 上記の手順を適用すると、テスト画像に対して次のようなBackProjection画像が得られる:
  1. 統計的には、BackProjectionに格納された値は、使用するモデルヒストグラムに基づいて、テスト画像のピクセルが肌の領域に属する確率を表す。たとえば今回のテスト画像では、明るい領域ほど肌の領域である確率が高く (実際にそうである)、暗い領域ほど確率が低い (これらの「暗い」領域は影のかかった面に属しており、それが検出に影響していることに注意)。

コード

  • What does this program do?
    • 画像を読み込む
    • 元画像をHSV形式に変換し、ヒストグラムに使用するためにHueチャンネルだけを分離する (OpenCVの関数 cv::mixChannels を使用)
    • ヒストグラムの計算に使用するビン数をユーザーに入力させる。
    • 同じ画像のヒストグラム (ビンが変化したら更新する) とバックプロジェクションを計算する。
    • バックプロジェクションとヒストグラムをウィンドウに表示する。

説明

  • 入力画像を読み込む:

  • HSV形式に変換する:

  • 本チュートリアルでは、1次元ヒストグラムにHue値のみを使用する (より標準的なH-Sヒストグラムを使えばより良い結果が得られる。それを試したい場合は上記リンクの凝ったコードを参照):

  • as you see, we use the function cv::mixChannels to get only the channel 0 (Hue) from the hsv image. It gets the following parameters:
    • &hsv: チャンネルのコピー元となる元配列
    • 1: 元配列の数
    • &hue: コピーされたチャンネルの格納先配列
    • 1: 格納先配列の数
    • ch[] = {0,0}: チャンネルをどうコピーするかを示すインデックス対の配列。この場合、&hsv のHue(0)チャンネルが &hue (1チャンネル) の0チャンネルにコピーされる
    • 1: インデックス対の数
  • ユーザーがビン値を入力するためのトラックバーを作成する。トラックバーが変化するたびにコールバック関数 Hist_and_Backproj が呼び出される。

  • 画像を表示し、ユーザーがプログラムを終了するのを待つ:

  • Hist_and_Backproj関数: cv::calcHist に必要な引数を初期化する。ビン数はトラックバーから得られる:

  • ヒストグラムを計算し、範囲 \([0,255]\) に正規化する

  • 関数 cv::calcBackProject を呼び出して、同じ画像のバックプロジェクションを取得する

  • 引数はすべて既知である (ヒストグラムの計算に使ったものと同じ)。追加するのは backproj 行列だけで、これに元画像 (&hue) のバックプロジェクションが格納される
  • backprojを表示する:

  • 画像の1次元Hueヒストグラムを描画する:

結果

サンプル画像 (何だと思う? また別の手だ) を使った出力を以下に示す。ビン値を変えて遊んでみると、結果にどう影響するかが観察できる: