9

私は OpenCV の CPU バージョンの Oriented Gradients ( HOG ) のヒストグラムを使用しています。4x4 セル、4x4 ブロック、ブロック間のオーバーラップなし、および 15 個の方向ビンを含む 32x32 画像を使用しています。OpenCVHOGDescriptorでは、長さ 960 の 1D 特徴ベクトルが得られます。(32*32 ピクセル) * (15 方向) / (4*4 セル) = 960 であるため、これは理にかなっています。

ただし、これらの 960 の数値がメモリ内でどのように配置されているかはわかりません。私の推測では、次のようになります。

vector<float> descriptorsValues =
[15 bins for cell 0, 0] 
[15 bins for cell 0, 1]
...
[15 bins for cell 0, 7]
....
[15 bins for cell 7, 0] 
[15 bins for cell 7, 1]
...
[15 bins for cell 7, 7]

もちろん、これは 2D の問題を 1D にフラット化したものなので、実際には次のようになります。

[cell 0, 0] [cell 0, 1] ... [cell 7, 0] ... [cell 7, 7]

では、データ レイアウトについて正しい考えを持っているでしょうか。それとも別のものですか?


これが私のコード例です:

using namespace cv;

//32x32 image, 4x4 blocks, 4x4 cells, 4x4 blockStride
vector<float> hogExample(cv::Mat img)
{
    img = img.rowRange(0, 32).colRange(0,32); //trim image to 32x32
    bool gamma_corr = true;
    cv::Size win_size(img.rows, img.cols); //using just one window
    int c = 4;
    cv::Size block_size(c,c);
    cv::Size block_stride(c,c); //no overlapping blocks
    cv::Size cell_size(c,c);
    int nOri = 15; //number of orientation bins

    cv::HOGDescriptor d(win_size, block_size, block_stride, cell_size, nOri, 1, -1,
                              cv::HOGDescriptor::L2Hys, 0.2, gamma_corr, cv::HOGDescriptor::DEFAULT_NLEVELS);

    vector<float> descriptorsValues;
    vector<cv::Point> locations;
    d.compute(img, descriptorsValues, cv::Size(0,0), cv::Size(0,0), locations);

    printf("descriptorsValues.size() = %d \n", descriptorsValues.size()); //prints 960
    return descriptorsValues;
}

関連リソース: この StackOverflow の投稿このチュートリアルは、OpenCV HOGDescriptor を使い始めるのに役立ちました。

4

1 に答える 1

1

あなたの考えは正しかったと思います。

元の論文である人間検出のための方向付けられた勾配のヒストグラム(ページ 2) では、次のように述べています。

[...] 検出器ウィンドウは、方向勾配特徴ベクトルのヒストグラムが抽出された重複ブロックのグリッドでタイル張りされています。[...]

[...] HOG 記述子の密集した (実際にはオーバーラップしている) グリッドで検出ウィンドウをタイリングし、結合された特徴ベクトルを使用する [...]

それが話したのは、それらを一緒に並べることだけです。それらを正確に並べる方法についての詳細情報は紹介されていませんが。ここで派手なことが起こるべきではないと思います(そうでなければ、彼らはそれについて話します)、つまり、それらを定期的に連結するだけです(左から右、上から下)。

結局のところ、それは合理的で、データをレイアウトする最も簡単な方法です。


編集:人々がデータにアクセスして視覚化する方法を見れば、より納得できるでしょう。

for (int blockx=0; blockx<blocks_in_x_dir; blockx++)
{
    for (int blocky=0; blocky<blocks_in_y_dir; blocky++)            
    {
        for (int cellNr=0; cellNr<4; cellNr++)
        {
            for (int bin=0; bin<gradientBinSize; bin++)
            {
                float gradientStrength = descriptorValues[ descriptorDataIdx ];
                descriptorDataIdx++;

                // ... ...

            } // for (all bins)
        } // for (all cells)
    } // for (all block x pos)
} // for (all block y pos)
于 2014-01-16T06:00:16.530 に答える