「HOG特徴量」の編集履歴(バックアップ)一覧に戻る

HOG特徴量 - (2010/09/08 (水) 13:50:12) のソース

**HOG特徴量(Histograms of Oriented Gradients)

 &big(){HOGは、画像の局所領域から輝度勾配・輝度強度を取り出す特徴量です。一般に歩行者や人工物など、物体を検出するために使われています。HOGでは、輝度勾配ヒストグラム(物体の見えから得られる角度毎のヒストグラムのこと。画素ごとに得られます。)の対応する要素に、輝度強度を累積します。さらに、正規化処理によりヒストグラムの形状を整えるので、明るさの変化に対応可能であると言われております。ステップは以下に示します。}

&sizex(4){Step.0}
&big(){局所領域をブロック・セルに分割(画像をブロックに分割します。さらにブロックを分割した領域がセルになります。)}

&sizex(4){Step.1}
&big(){ブロックを移動。セルの中における輝度勾配ヒストグラムを計算する。}

&sizex(4){Step.2}
&big(){ブロックごとに正規化する。}

&sizex(4){Step.3}
&big(){全てのヒストグラムを統合して特徴量とする。}

&big(){Step.1 と Step.2が繰り返し}

参考文献
-[[N.Dalal, B.Triggs,"Histograms of oriented gradients for human detection",Proc.of IEEE Conference on Computer Vision and Pattern Recognition (CVPR),pp.886-893,2005>>http://ljk.imag.fr/membres/Bill.Triggs/////////pubs/Dalal-cvpr05.pdf]]

C++,OpenCVによる実装例
----

&big(){・局所特徴量は大体において識別器を生成するアルゴリズム(SVM,AdaBoostなど)と組み合わせて使います。}

 /*                      HOG特徴量                           */
 // image:画像の配列
 // width:画像の幅
 // height:画像の高さ
 // histogram_dimension:ヒストグラムの要素数
 // cell_column:セルの列数(横方向に画像を何分割するか)
 // cell_row:セルの行数(縦方向の画像を何分割するか)
 // block_column:1ブロックの列数
 // block_row:1ブロックの行数
 // feature_vector:HOG特徴ベクトルの配列
 // feature_vector_dimension:HOG特徴ベクトルの次元数
 //histogram_dimension*block_column*block_row*(cell_row - block_row) * (cell_column - block_column)
 void HOG(IplImage *image, int width, int height, int histogram_dimension, int cell_column, int cell_row, int   block_column, int block_row, float *feature_vector, int feature_vector_dimension)
 {
    int x,y;     //繰り返し変数
    int bin;     //ビンの位置
    int cell_width = width / cell_column;  //セルサイズ(幅)
    int cell_height = height / cell_row;   //セルサイズ(高さ)
    int block_dimension = histogram_dimension * block_column * block_row; //ブロックの次元数
    float fu,fv;    
    float magnitude;     //輝度強度
    float direction;     //輝度勾配
    float norm;          //ノルム
    float epsilon = 1.0; //分母が0にならないように
    float *histogram;    //特徴ヒストグラム
    float *cell_feature_vector;  //セルのヒストグラム
    float *block_feature_vector; //ブロックのヒストグラム
	
    // ヒストグラムを計算する(対応する輝度勾配ヒストグラムのビンに強度を累積)
    histogram = new float [histogram_dimension];
    cell_feature_vector = new float [histogram_dimension * cell_row * cell_column];
    for (int i = 0; i < cell_row; i++) {
        for (int j = 0; j < cell_column; j++) {
            // セルごとにヒストグラムを計算する.
            memset(histogram, 0, histogram_dimension * sizeof(float));
            for (int v = 0; v < cell_height; v++) {
                y = i * cell_height + v;
                for (int u = 0; u < cell_width; u++) {
                    x = j * cell_width + u;
                    // 勾配強度・勾配方向を求める.
		    if ((x > 0) && (x < width) && (y > 0) && (y < height)) {
			fu = image->imageData[(image->width * y + (x + 1)) * 3] - image->imageData[(image->width * y + (x - 1)) * 3];
                        fv = image->imageData[(image->width * (y + 1) + x) * 3] - image->imageData[(image->width * (y - 1) + x) * 3];
                        magnitude = sqrt(fu * fu + fv * fv);   //輝度強度
                        direction = atan(fv / fu) + PI / 2.0;  //輝度勾配
                        // ヒストグラムに投票
                        bin = (int)floor( (direction * (180.0 / PI)) * ((float)(histogram_dimension - 1) / 180.0) );
                        histogram[bin] += magnitude;
                    }
                }
            }
            for (int d = 0; d < histogram_dimension; d++) {
                cell_feature_vector[(d * cell_row + i) * cell_column + j] = histogram[d];
            }
        }
    }
    delete [] histogram;   //不要なヒストグラムを解放
    // ブロックごとに正規化する
    block_feature_vector = new float [block_dimension];
    for (int i = 0; i < cell_row - block_row + 1; i++) {            //縦のセル数
        for (int j = 0; j < cell_column - block_column + 1; j++) {  //横のセル数
            for (int k = 0; k < block_row; k++) {               //ブロック数
                for (int l = 0; l < block_column; l++) {        //ブロック数
                    for (int d = 0; d < histogram_dimension; d++) {
			    block_feature_vector[(d * block_row + k) * block_column + l] 
                          = cell_feature_vector[(d * cell_row + (i + k)) * cell_column + (j + l)];
                    }
                }
            }
            norm = 0.0;  //ノルムの初期化
	    for (int d = 0; d < block_dimension; d++) {
                norm += block_feature_vector[d] * block_feature_vector[d];  //合計値を計算
            }
	    for (int d = 0; d < block_dimension; d++) {
	       //正規化処理
	       feature_vector[(d * (cell_row - block_row + 1) + i) * (cell_column - block_column + 1) + j] 
               = block_feature_vector[d] / sqrt(norm + epsilon * epsilon);
            }
        }
    }
    //ヒストグラムを解放
    delete [] cell_feature_vector;
    delete [] block_feature_vector;
 }

&big(){・不備がある可能性があります。あらかじめご了承ください。}

----