【问题标题】:OpenCV HOG feature data layout?OpenCV HOG 特征数据布局?
【发布时间】:2012-11-01 08:39:24
【问题描述】:

我正在使用 OpenCV 的 CPU 版本的方向梯度直方图 (HOG)。我使用的是 32x32 图像,其中包含 4x4 单元格、4x4 块、块之间没有重叠和 15 个方向箱。 OpenCV 的 HOGDescriptor 给了我一个长度为 960 的一维特征向量。这是有道理的,因为(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;
}

相关资源: This StackOverflow postthis tutorial 帮助我开始使用 OpenCV HOGDescriptor。

【问题讨论】:

    标签: c++ opencv computer-vision histogram feature-extraction


    【解决方案1】:

    我相信你的想法是对的。

    在其原始论文Histograms of Oriented Gradients for Human Detection(第2页)中,它说

    [...] 检测器窗口平铺有重叠块的网格,其中提取了定向梯度特征向量的直方图。 [...]

    [...] 使用 HOG 描述符的密集(实际上是重叠的)网格平铺检测窗口和 使用组合特征向量 [...]

    它谈论的只是tiling他们在一起。尽管没有介绍如何将它们精确地平铺在一起的详细信息。我想这里不应该发生什么花哨的事情(否则他们会谈论它),即只是定期连接它们(从左到右,从上到下)。

    毕竟,这是合理且最简单的数据布局方式。


    编辑:如果您查看how people access and visualize the data,您将更能说服自己。

    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)
    

    【讨论】:

    • @solvingPuzzles 实际上是专栏专业。看看blocky 的循环是如何嵌套在blockx 的循环中的。
    猜你喜欢
    • 2012-07-22
    • 2014-03-16
    • 2011-11-11
    • 1970-01-01
    • 2014-08-11
    • 2014-01-01
    • 1970-01-01
    • 2015-09-15
    • 2014-05-15
    相关资源
    最近更新 更多