ヒストグラム

CvHistogram

CvHistogram

多次元ヒストグラム.

typedef struct CvHistogram
{
    int     type;
    CvArr*  bins;
    float   thresh[CV_MAX_DIM][2]; /* 一様分布ヒストグラム用 */
    float** thresh2; /* 非一様分布ヒストグラム用 */
    CvMatND mat; /* 内部で利用されるヒストグラム配列の行列ヘッダ */
}
CvHistogram;

cv::CalcBackProject

void cvCalcBackProject(IplImage** image, CvArr* back_project, const CvHistogram* hist)

バックプロジェクションを計算します.

パラメタ:
  • image – 入力画像(CvMat** の形式で渡される場合もあります)
  • back_project – 入力画像と同じ型のバックプロジェクション画像
  • hist – ヒストグラム

関数 cvCalcBackProject は,ヒストグラムのバックプロジェクションを求めます.この関数は,すべての入力画像(シングルチャンネル)上の同じ位置にあるピクセルのタプルに対して,そのタプルに対応したヒストグラムのビンの値を,出力画像のピクセル値としてセットします.統計学的には,出力画像の各ピクセル値は,与えられた分布(ヒストグラム)における観測タプルの出現確率であると言えます.例えば,画像中の赤い物体を見つけるためには,以下のような方法が考えられます:

  1. 画像にその物体だけが写っていると仮定し,その赤いオブジェクトの色相に関するヒストグラムを計算します.このヒストグラムは赤色に対して強い最大値を持つ傾向があります.
  2. ヒストグラムを利用し,物体を探索する画像の色相平面のバックプロジェクションを求めます.そして,その画像に閾値処理を施します.
  3. その結果画像から連結成分を探し,別の基準(例えば,最大の連結成分など)を利用して正しい成分を選択します.

これは,3番目のステップ以外は,Camshiftの色物体追跡器のアルゴリズムとほぼ同じです.Camshift追跡器では,この3番目のステップの代わりにCAMSHIFTアルゴリズムが用いられ,物体の前ステップでの位置が与えられると,バックプロジェクション上の物体の現在位置が求められます.

cv::CalcBackProjectPatch

void cvCalcBackProjectPatch(IplImage** images, CvArr* dst, CvSize patch_size, CvHistogram* hist, int method, float factor)

ヒストグラムを比較することで,画像中のテンプレート位置を求めます.

パラメタ:
  • images – 入力画像(CvMat** の形式で渡される場合もあります)
  • dst – 出力画像
  • patch_size – 入力画像上を移動するパッチのサイズ
  • hist – ヒストグラム
  • method – 比較手法.この値は CompareHist に渡されます(この関数の説明を参照してください)
  • factor – ヒストグラムの正規化係数.出力画像の正規化スケールに影響します.分からない場合には1を与えてください

関数 cvCalcBackProjectPatch は,与えられたヒストグラムと,入力画像の一部分のヒストグラムとを比較することで,バックプロジェクションを計算します.配列 image は,ある画像のROIを,様々な方法で評価した結果から構成されます.その評価結果は,色相, x 方向微分, y 方向微分,ラプラシアンフィルタ,Gaborフィルタなどの,1つあるいは複数かもしれません.各手法の評価出力は,個別に集められてそれぞれ別の画像となります.画像配列 image は,これらの評価画像の集合です.また,多次元ヒストグラム hist は,画像配列 image からサンプリングした結果です.最終的なヒストグラムは,正規化されます.また,ヒストグラム hist は,配列 image の要素数と同じだけの次元を持ちます.

新しい画像はまず評価され,そのROI全体が画像配列 image に変換されます.その部分的なヒストグラムは,以下の図にあるように,中心にアンカーを持つ「パッチ」と重なった部分にある画像 image から計算されます. hist と比較できるように,このヒストグラムは,パラメータ norm_factor を利用して正規化されます.求められたヒストグラムは,比較手法に method を指定した関数 cvCompareHist を利用して,モデルヒストグラム hist と比較されます.その出力結果は,確率画像 dst の,パッチのアンカーに対応する場所に格納されます.毎回パッチをずらして,最終的にROI全体に対して処理が終わるまで,これを繰り返します.ヒストグラムの反復更新は,パッチの端の重ならなくなった部分のピクセル値を引き,さらに新しく重なる部分のピクセル値を加えることで,大幅に処理を削減できる.しかし,まだこれは実装されていません.

パッチによる投影計算

_images/backprojectpatch.png

cv::CalcHist

void cvCalcHist(IplImage** image, CvHistogram* hist, int accumulate=0, const CvArr* mask=NULL)

画像のヒストグラムを求めます.

パラメタ:
  • image – 入力画像(CvMat** の形式で渡される場合もあります)
  • hist – ヒストグラムへのポインタ
  • accumulate – 累積フラグ.これが指定されている場合,関数の最初でヒストグラムがクリアされません.これによって,複数の画像から1つのヒストグラムを計算したり,毎回ヒストグラムを更新したりすることができます
  • mask – 処理マスク.入力画像のどのピクセルをカウントするかを決めます

この関数は,1つあるいは複数のシングルチャンネル画像のヒストグラムを求めます.ヒストグラムのビンの値を増加させる入力タプルの要素は,対応する(複数の)入力画像の同じ位置から取り出されます.

#include <cv.h>
#include <highgui.h>

int main( int argc, char** argv )
{
    IplImage* src;
    if( argc == 2 && (src=cvLoadImage(argv[1], 1))!= 0)
    {
        IplImage* h_plane = cvCreateImage( cvGetSize(src), 8, 1 );
        IplImage* s_plane = cvCreateImage( cvGetSize(src), 8, 1 );
        IplImage* v_plane = cvCreateImage( cvGetSize(src), 8, 1 );
        IplImage* planes[] = { h_plane, s_plane };
        IplImage* hsv = cvCreateImage( cvGetSize(src), 8, 3 );
        int h_bins = 30, s_bins = 32;
        int hist_size[] = {h_bins, s_bins};
        /* 色相は 0( 0 度,赤)から 180 ( 360 度,再び赤)まで変化します */
        float h_ranges[] = { 0, 180 };
        /* 彩度は 0(黒 - グレー - 白)から
                 255 (純粋なスペクトル色)まで変化します */
        float s_ranges[] = { 0, 255 };
        float* ranges[] = { h_ranges, s_ranges };
        int scale = 10;
        IplImage* hist_img =
            cvCreateImage( cvSize(h_bins*scale,s_bins*scale), 8, 3 );
        CvHistogram* hist;
        float max_value = 0;
        int h, s;

        cvCvtColor( src, hsv, CV_BGR2HSV );
        cvCvtPixToPlane( hsv, h_plane, s_plane, v_plane, 0 );
        hist = cvCreateHist( 2, hist_size, CV_HIST_ARRAY, ranges, 1 );
        cvCalcHist( planes, hist, 0, 0 );
        cvGetMinMaxHistValue( hist, 0, &max_value, 0, 0 );
        cvZero( hist_img );

        for( h = 0; h < h_bins; h++ )
        {
            for( s = 0; s < s_bins; s++ )
            {
                float bin_val = cvQueryHistValue_2D( hist, h, s );
                int intensity = cvRound(bin_val*255/max_value);
                cvRectangle( hist_img, cvPoint( h*scale, s*scale ),
                             cvPoint( (h+1)*scale - 1, (s+1)*scale - 1),
                             CV_RGB(intensity,intensity,intensity),
                             CV_FILLED );
            }
        }

        cvNamedWindow( "Source", 1 );
        cvShowImage( "Source", src );

        cvNamedWindow( "H-S Histogram", 1 );
        cvShowImage( "H-S Histogram", hist_img );

        cvWaitKey(0);
    }
}

cv::CalcProbDensity

void cvCalcProbDensity(const CvHistogram* hist1, const CvHistogram* hist2, CvHistogram* dst_hist, double scale=255)

あるヒストグラムを別のヒストグラムで割ります.

パラメタ:
  • hist1 – 1番目のヒストグラム(除数)
  • hist2 – 2番目のヒストグラム
  • dst_hist – 出力ヒストグラム
  • scale – 出力ヒストグラムに対するスケール係数

この関数は,2つのヒストグラムから物体の確率密度を求めます:

\texttt{dist\_hist} (I)= \forkthree{0}{if $\texttt{hist1}(I)=0$}{\texttt{scale}}{if $\texttt{hist1}(I) \ne 0$ and $\texttt{hist2}(I) > \texttt{hist1}(I)$}{\frac{\texttt{hist2}(I) \cdot \texttt{scale}}{\texttt{hist1}(I)}}{if $\texttt{hist1}(I) \ne 0$ and $\texttt{hist2}(I) \le \texttt{hist1}(I)$}

出力ヒストグラムのビンの値は, scale 未満です.

cv::ClearHist

void cvClearHist(CvHistogram* hist)

ヒストグラムをクリアします.

Parameter:hist – Histogram

この関数は,密な配列データをもつヒストグラムの場合はヒストグラムの全てのビンの値を 0にし,疎な配列データを持つヒストグラムの場合はヒストグラムの全てのビンを削除します.

cv::CompareHist

double cvCompareHist(const CvHistogram* hist1, const CvHistogram* hist2, int method)

2つの密なヒストグラムを比較します.

パラメタ:
  • hist1 – 1番目の密なヒストグラム
  • hist2 – 2番目の密なヒストグラム
  • method

    比較手法.以下のうちの1つ:

    • CV_COMP_CORREL 相関
    • CV_COMP_CHISQR カイ2乗
    • CV_COMP_INTERSECT 交差
    • CV_COMP_BHATTACHARYYA Bhattacharyya距離

この関数は,指定された手法を用いて2つの密なヒストグラムを比較します( H_1 は1番目のヒストグラムを, H_2 は2番目のヒストグラムを表します):

  • 相関 (method=CV_COMP_CORREL)

    d(H_1,H_2) =  \frac{\sum_I (H'_1(I) \cdot H'_2(I))}{\sqrt{\sum_I(H'_1(I)^2) \cdot \sum_I(H'_2(I)^2)}}

    ここで,

    H'_k(I) =  \frac{H_k(I) - 1}{N \cdot \sum_J H_k(J)}

    です.N はヒストグラムのビン数を表します.

  • カイ2乗 (method=CV_COMP_CHISQR)

    d(H_1,H_2) =  \sum _I  \frac{(H_1(I)-H_2(I))^2}{H_1(I)+H_2(I)}

  • 交差 (method=CV_COMP_INTERSECT)

    d(H_1,H_2) =  \sum _I  \min (H_1(I), H_2(I))

  • Bhattacharyya距離 (method=CV_COMP_BHATTACHARYYA)

    d(H_1,H_2) =  \sqrt{1 - \sum_I \frac{\sqrt{H_1(I) \cdot H_2(I)}}{ \sqrt{ \sum_I H_1(I) \cdot \sum_I H_2(I) }}}

この関数は, d(H_1, H_2) を返します.

注意:手法 CV_COMP_BHATTACHARYYA は,正規化されたヒストグラムでのみ動作します.

疎なヒストグラム,あるいはより一般的な構造である重み付き点群などを比較するためには,関数 CalcEMD2 の利用を検討してください.

cv::CopyHist

void cvCopyHist(const CvHistogram* src, CvHistogram** dst)

ヒストグラムをコピーします.

パラメタ:
  • src – コピー元ヒストグラムへのポインタ
  • dst – コピー先ヒストグラムへのダブルポインタ

この関数は,ヒストグラムのコピーを作成します.2番目のヒストグラムポインタ *dst がNULLならば, src と同じサイズのヒストグラムが新たに作成されます.NULLでない場合は,2つのヒストグラムは同じ型,同じサイズでなければいけません.この関数は,コピー元のヒストグラムのビンの値をコピー先のヒストグラムにコピーし,ビンの範囲も src と同じになるようにセットします.

cv::CreateHist

CvHistogram* cvCreateHist(int dims, int* sizes, int type, float** ranges=NULL, int uniform=1)

ヒストグラムを作成します.

パラメタ:
  • dims – ヒストグラムの次元数
  • sizes – ヒストグラムの各次元のサイズを示す配列
  • type – ヒストグラム表現フォーマット: CV_HIST_ARRAY は,ヒストグラムのデータが密な多次元配列 CvMatND で表現される事を意味します.また CV_HIST_SPARSE は,ヒストグラムのデータが疎な多次元配列 CvSparseMat で表される事を意味します
  • ranges – ヒストグラムのビンの範囲を示す配列.これの意味は,パラメータ uniform の値に依存します.これらの範囲は,ヒストグラムが計算される際や,どのヒストグラムのビンが入力画像中のどの値(あるいは,値のタプル)に対応するかを決定するバックプロジェクションの際に利用されます
  • uniform

    一様性を示すフラグ.これが0ではない場合,ヒストグラムは等間隔のビンをもち, ranges[i] 0<=i<cDims は2つの値,つまりヒストグラムのi番目の次元の下限値と上限値,からなる配列です.そして,それぞれのヒストグラムビンに対する i 番目の入力タプル値の範囲を決定するために,範囲全体 [lower, upper] が dims[i] 個に等分割されます. uniform=0 の場合, ranges 配列の i 番目の 要素は,次のような dims[i]+1 個の要素を含みます:

    \texttt{lower}_0, \texttt{upper}_0,
\texttt{lower}_1, \texttt{upper}_1 = \texttt{lower}_2,
...
\texttt{upper}_{dims[i]-1} ここで, \texttt{lower}_j\texttt{upper}_j

    はそれぞれ, j 番目のビンに対する i 番目の入力タプル値の下限および上限です.どちらの場合でも,ヒストグラムビンの指定範囲を超えるような入力値は, CalcHist ではカウントされず, CalcBackProject では0で埋められます

この関数は,指定されたサイズのヒストグラムを作成し,そのポインタを返します.配列 ranges が0の場合,後で関数 SetHistBinRanges によってヒストグラムのビンの範囲を指定しなければいけません.関数 CalcHist および CalcBackProject は,ビンの範囲を指定せずに8ビット画像を処理しますが,これは 0から255 までの等間隔のビンを仮定します.

cv::GetHistValue*D

float cvGetHistValue_1D(hist, idx0)
float cvGetHistValue_2D(hist, idx0, idx1)
float cvGetHistValue_3D(hist, idx0, idx1, idx2)
float cvGetHistValue_nD(hist, idx)

ヒストグラムのビンへのポインタを返します.

パラメタ:
  • hist – ヒストグラム
  • idx0, idx1, idx2, idx3 – ビンのインデックス
  • idx – インデックスの配列
#define cvGetHistValue_1D( hist, idx0 )
    ((float*)(cvPtr1D( (hist)->bins, (idx0), 0 ))
#define cvGetHistValue_2D( hist, idx0, idx1 )
    ((float*)(cvPtr2D( (hist)->bins, (idx0), (idx1), 0 )))
#define cvGetHistValue_3D( hist, idx0, idx1, idx2 )
    ((float*)(cvPtr3D( (hist)->bins, (idx0), (idx1), (idx2), 0 )))
#define cvGetHistValue_nD( hist, idx )
    ((float*)(cvPtrND( (hist)->bins, (idx), 0 )))

マクロ GetHistValue は,1次元,2次元,3次元,およびN-次元ヒストグラムの,指定されたビンへのポインタを返します.疎なヒストグラムにおいて,ヒストグラム中にビンが存在しない場合,この関数は新たにビンを作成し,その値を0にセットします.

cv::GetMinMaxHistValue

void cvGetMinMaxHistValue(const CvHistogram* hist, float* min_value, float* max_value, int* min_idx=NULL, int* max_idx=NULL)

最小値を持つビン,および最大値を持つビンを求めます.

パラメタ:
  • hist – ヒストグラムへのポインタ
  • min_value – ヒストグラムの最小値へのポインタ
  • max_value – ヒストグラムの最大値へのポインタ
  • min_idx – 最小値に対する座標値の配列
  • min_idx – 最大値に対する座標値の配列

この関数は,最小値を持つビン,および最大値を持つビンとそれぞれの位置を求めます.出力に利用されるすべての引数は,オプションです同じ値の最小値や最大値が複数存在する場合,(辞書順に並べた場合の)最小のインデックスを持つものが返されます.

cv::MakeHistHeaderForArray

CvHistogram* cvMakeHistHeaderForArray(int dims, int* sizes, CvHistogram* hist, float* data, float** ranges=NULL, int uniform=1)

配列からヒストグラムを作成します.

パラメタ:
  • dims – ヒストグラムの次元数
  • sizes – ヒストグラムの各次元のサイズを表す配列
  • hist – この関数によって初期化される,ヒストグラムのヘッダ
  • data – ヒストグラムのビンを保存するための配列
  • ranges – ヒストグラムのビンの範囲, CreateHist を参照
  • uniform – 一様性フラグ, CreateHist を参照

この関数は,ヒストグラムを初期化します.そのヘッダとビンはユーザによって確保されるものです.後で ReleaseHist を呼ぶ必要はありません.また,この方法で初期化できるのは,密なヒストグラムだけです.この関数は, hist を返します.

cv::NormalizeHist

void cvNormalizeHist(CvHistogram* hist, double factor)

ヒストグラムを正規化します.

パラメタ:
  • hist – ヒストグラムへのポインタ
  • factor – 正規化ファクタ

この関数は,ビンの値の合計が factor と等しくなるようにスケーリングを行うことで,ヒストグラムのビンの正規化を行います.

cv::QueryHistValue*D

float QueryHistValue_1D(CvHistogram hist, int idx0)

ヒストグラムのビンの値を取得します.

パラメタ:
  • hist – ヒストグラム
  • idx0, idx1, idx2, idx3 – ビンのインデックス
  • idx – インデックスの配列
#define cvQueryHistValue_1D( hist, idx0 ) \
    cvGetReal1D( (hist)->bins, (idx0) )
#define cvQueryHistValue_2D( hist, idx0, idx1 ) \
    cvGetReal2D( (hist)->bins, (idx0), (idx1) )
#define cvQueryHistValue_3D( hist, idx0, idx1, idx2 ) \
    cvGetReal3D( (hist)->bins, (idx0), (idx1), (idx2) )
#define cvQueryHistValue_nD( hist, idx ) \
    cvGetRealND( (hist)->bins, (idx) )

これらのマクロは,1次元,2次元,3次元,N次元ヒストグラムの指定したビンの値を返します.疎なヒストグラムにおいて指定されたビンが存在しない場合,新しいビンは作成されず,0が返されます.

cv::ReleaseHist

void cvReleaseHist(CvHistogram** hist)

ヒストグラムを解放します.

Parameter:hist – 解放されるヒストグラムへのダブルポインタ

この関数は,ヒストグラム(ヘッダとデータ)を解放します.この関数により,ヒストグラムへのポインタもクリアされます.ポインタ *hist が既に NULL の場合は,この関数は何もしません.

cv::SetHistBinRanges

void cvSetHistBinRanges(CvHistogram* hist, float** ranges, int uniform=1)

ヒストグラムのビンの上下限値をセットします.

パラメタ:
  • hist – ヒストグラムへのポインタ
  • ranges – ビン範囲の配列, CreateHist を参照してください
  • uniform – 一様性フラグ CreateHist を参照してください

この関数は,ヒストグラムのビンの範囲をセットするための,単独で動作する関数です.パラメータ rangesuniform のより詳しい説明は,同じように範囲を初期化できる関数 CreateHist を参照してください.ヒストグラムのビンの範囲は,ヒストグラムやヒストグラムのバックプロジェクションが計算されるよりも前にセットされていなければいけません.

cv::ThreshHist

void cvThreshHist(CvHistogram* hist, double threshold)

ヒストグラムの閾値処理を行います.

パラメタ:
  • hist – ヒストグラムへのポインタ
  • threshold – 閾値レベル

この関数は,指定した閾値以下のビンをクリアします.