HOG特徴量(Histograms of Oriented Gradients)
HOGは,画像の局所領域から輝度勾配・輝度強度を取り出す特徴量です.物体の大まかな形状を表現可能です.一般に歩行者や人工物など,物体を検出するために使われています.HOGでは,輝度勾配ヒストグラム(物体の見えから得られる角度毎のヒストグラムのこと.画素ごとに得られます.)の対応する要素に,輝度強度を累積します.さらに,正規化処理によりヒストグラムの形状を整えるので,明るさの変化に対応可能であると言われております.ステップは以下に示します.
Step.0
局所領域をブロック・セルに分割(画像をブロックに分割します.さらにブロックを分割した領域がセルになります.)
Step.1
ブロックを移動.セルの中における輝度勾配ヒストグラムを計算する.
Step.2
ブロックごとに正規化する.
Step.3
全てのヒストグラムを統合して特徴量とする.
Step.1 と Step.2が繰り返し
参考文献
C++,OpenCVによる実装例
・HOGは一般的に学習器(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;
}
・不備がある可能性があります.あらかじめご了承ください.
最終更新:2011年03月04日 19:13