6

I am trying to calculate HOG features for block only. I explored hog.cpp listed under opencv/module/gpu/src/. Below is the code that I change to computer the features of block only.

void cv::gpu::HOGDescriptor::getDescriptors(const GpuMat& img, Size win_stride, GpuMat& descriptors, int descr_format)
{
    CV_Assert(win_stride.width % block_stride.width == 0 && win_stride.height % block_stride.height == 0);

    computeBlockHistograms(img);
    // give block back

/*
    const size_t block_hist_size = getBlockHistogramSize();
    Size blocks_per_win = numPartsWithin(win_size, block_size, block_stride);
    Size wins_per_img   = numPartsWithin(img.size(), win_size, win_stride);

    descriptors.create(wins_per_img.area(), static_cast<int>(blocks_per_win.area() * block_hist_size), CV_32F); */

    switch (descr_format)
    {
    case DESCR_FORMAT_ROW_BY_ROW:
        hog::extract_descrs_by_rows(win_size.height, win_size.width, block_stride.height, block_stride.width,
                                    win_stride.height, win_stride.width, img.rows, img.cols, block_hists.ptr<float>(), descriptors);
        break;
    case DESCR_FORMAT_COL_BY_COL:
        hog::extract_descrs_by_cols(win_size.height, win_size.width, block_stride.height, block_stride.width,
                                    win_stride.height, win_stride.width, img.rows, img.cols, block_hists.ptr<float>(), descriptors);
        break;
    default:
        CV_Error(CV_StsBadArg, "Unknown descriptor format");
    }
}

Here is the computeBlockHistograms code as well.

void cv::gpu::HOGDescriptor::computeBlockHistograms(const GpuMat& img)
{
    computeGradient(img, grad, qangle);

    size_t block_hist_size = getBlockHistogramSize();
    Size blocks_per_img = numPartsWithin(img.size(), block_size, block_stride);

    //   block_hists.create(1, block_hist_size * blocks_per_img.area(), CV_32F);
    block_hists = getBuffer(1, static_cast<int>(block_hist_size * blocks_per_img.area()), CV_32F, block_hists_buf);

    hog::compute_hists(nbins, block_stride.width, block_stride.height, img.rows, img.cols,
                        grad, qangle, (float)getWinSigma(), block_hists.ptr<float>());

    hog::normalize_hists(nbins, block_stride.width, block_stride.height, img.rows, img.cols,
                         block_hists.ptr<float>(), (float)threshold_L2hys);
}

EDIT: I am including getDescriptor function as well from hog.cpp

void cv::gpu::HOGDescriptor::getDescriptors(const GpuMat& img, Size win_stride, GpuMat& descriptors, int descr_format)
{
    CV_Assert(win_stride.width % block_stride.width == 0 && win_stride.height % block_stride.height == 0);

    computeBlockHistograms(img);

    const size_t block_hist_size = getBlockHistogramSize();
    Size blocks_per_win = numPartsWithin(win_size, block_size, block_stride);
    Size wins_per_img   = numPartsWithin(img.size(), win_size, win_stride);

    descriptors.create(wins_per_img.area(), static_cast<int>(blocks_per_win.area() * block_hist_size), CV_32F);

    switch (descr_format)
    {
    case DESCR_FORMAT_ROW_BY_ROW:
        hog::extract_descrs_by_rows(win_size.height, win_size.width, block_stride.height, block_stride.width,
                                    win_stride.height, win_stride.width, img.rows, img.cols, block_hists.ptr<float>(), descriptors);
        break;
    case DESCR_FORMAT_COL_BY_COL:
        hog::extract_descrs_by_cols(win_size.height, win_size.width, block_stride.height, block_stride.width,
                                    win_stride.height, win_stride.width, img.rows, img.cols, block_hists.ptr<float>(), descriptors);
        break;
    default:
        CV_Error(CV_StsBadArg, "Unknown descriptor format");
    }
}

Can someone help me to get the HOG features for block only. EDITED: I am only interested to calculat HOG features for different window size keeping features for cell and block same.

shah
  • 311
  • 3
  • 20
  • 1
    can you give an example what you want to achieve? I'm not so familiar with HoG, but afaik it doesnt compute FEATURES but DESCRIPTORS. So for example a HoG descriptor could be computed from a 64x128 pixel window. Within that window, blocks are evaluated by the algorithm. Do you want to change the 64x128 sized window to something different? You want to use the same block-size? (doesnt this change the size of the descriptor element?) – Micka Jul 03 '15 at 12:50
  • Thank you for responding. Actually I want to calculate HoG descriptors for only blocks as I have three different windows so I want to calculate HoG descriptors for blocks only once. If I calculate HoG descriptors for three different windown I be calculating HoG descriptor for block three times. I hope you got it now – shah Jul 03 '15 at 13:55
  • 1
    ah ok. do you have to use the gpu version or would cpu be ok too? – Micka Jul 03 '15 at 13:58
  • I want to use gpu version. thank you – shah Jul 03 '15 at 13:58
  • I spent quite quite a lot time in understanding and reverse engineering the code like hog::normalize_hists save normalize histogram in block_hists. I don't know how I can access block_hists in getDescriptors function to save blocks instead of windows. Do u got my point? – shah Jul 03 '15 at 14:01
  • @Micka, should I change my question to be more understanable? – shah Jul 03 '15 at 14:03
  • can you tell me where the results of computeBlockHistograms are saved to? is `cv::gpu::HOGDescriptor` some kind of object that encapsulates some kind of HOG pipeline and holds the result of `computeBlockHistograms`? If yes, you would probably remove only `computeBlockHistograms` line so you can call it independently from `getDescriptors` and then you can call `getDescriptors` for different win_sizes etc... but not sure whether this works out... Do you know whether the cpu version uses the same inner-class-structure? – Micka Jul 03 '15 at 14:08
  • Here is the complete code for hog.cpp http://sourceforge.net/p/emgucv/opencv/ci/4dfbf99dd5b5fe97128683f32e248f9cd99b46c7/tree/modules/gpu/src/hog.cpp – shah Jul 03 '15 at 14:15
  • `computeBlockHistograms` is function in `/module/gpu/src/`. I am not sure how it is holding the result. I gave the link for `hog.cpp` – shah Jul 03 '15 at 14:19
  • no sorry never used opencv gpu or HoG. Would have a look a HoG cpu code if I were you. – Micka Jul 06 '15 at 09:19
  • so, can you help for cpu version? – shah Jul 06 '15 at 09:26
  • 1
    no since I didnt use it, but probably it is easier to understand and to debug, so you can test with it and find out where the blocks are saved to reuse them. And probably the gpu version uses a similar mechanic so you can adapt your cpu solution to gpu, but that's just a guess. sorry that I have no more time for your in that problem. – Micka Jul 06 '15 at 09:30

1 Answers1

0

I modified the following functions to calculate HOG descriptors for blocks only.

void cv::gpu::HOGDescriptor::getDescriptorsBlock(const GpuMat& img, Size win_stride, GpuMat& descriptors, FileStorage fs3, string fileName, double scale, int width, int height, size_t lev)
{
    CV_Assert(win_stride.width % block_stride.width == 0 && win_stride.height % block_stride.height == 0);

    size_t block_hist_size = getBlockHistogramSize();
    computeBlockHistograms(img);
    Size blocks_per_img = numPartsWithin(img.size(), block_size, block_stride);

    // Size blocks_per_win = numPartsWithin(win_size, block_size, block_stride);
    // Size wins_per_img   = numPartsWithin(img.size(), win_size, win_stride);

    // copy block_hists from GPU to CPU/

    float dest_ptr[block_hist_size * blocks_per_img.area()];

    cudaMemcpy( &dest_ptr[0], block_hists.ptr<float>(), block_hist_size *blocks_per_img.area()*sizeof(CV_32F),        cudaMemcpyDeviceToHost); 

    std::cout<<"( "<<width<< " ," << height<< ")"<< std::endl;
    std::cout <<lev<< std::endl;

    // write to yml file

    int level = lev;

    fs3<<"Scale"<<scale;
    fs3 <<"Level"<<level;
    fs3<<"Width"<<width<<"Height"<<height;
    fs3 << "features" << "[";
    for (unsigned int i = 0; i < (block_hist_size * blocks_per_img.area()) ; i++ )
    {
     fs3  << dest_ptr[i];
    }
    fs3 << "]";
}

Below is the that calculate HOG descriptors for multi scale image.

void cv::gpu::HOGDescriptor::getDescriptorsMultiScale(const GpuMat& img,
                                              Size win_stride, double scale0, unsigned int count)
{

    CV_Assert(img.type() == CV_8UC1 || img.type() == CV_8UC4);

    vector<double> level_scale;
    double scale = 1.;
    int levels = 0;

    for (levels = 0; levels < nlevels; levels++)
    {
        level_scale.push_back(scale);
        if (cvRound(img.cols/scale) < win_size.width ||
            cvRound(img.rows/scale) < win_size.height || scale0 <= 1)
            break;
        scale *= scale0;
    }
    levels = std::max(levels, 1);
    level_scale.resize(levels);
    image_scales.resize(levels);

    // open yml file with image ID

    FileStorage fs3;
    char fileName[20];
    GpuMat descriptors;
    sprintf (fileName, "%04d", count);
    fs3.open(fileName, FileStorage::WRITE);

    for (size_t i = 0; i < level_scale.size(); i++)
    {
        scale = level_scale[i];
        Size sz(cvRound(img.cols / scale), cvRound(img.rows / scale));
        GpuMat smaller_img;

        if (sz == img.size())
            smaller_img = img;
        else
        {
            image_scales[i].create(sz, img.type());
            switch (img.type())
            {
                case CV_8UC1: hog::resize_8UC1(img, image_scales[i]); break;
                case CV_8UC4: hog::resize_8UC4(img, image_scales[i]); break;
            }
            smaller_img = image_scales[i];
        }
        std::cout<<"scale "<<level_scale[i]<<std::endl;

        // calculate descriptors for blocks 
        getDescriptorsBlock( smaller_img, win_stride, descriptors, fs3, fileName, scale, smaller_img.cols, smaller_img.rows, i);

        // detect(smaller_img, locations, hit_threshold, win_stride, padding);
    }
    // close yml file
    fs3.release();

} 

Don't forget to add definition of these two functions in opencv/modules/gpu/include/opencv2/gpu/gpu.hpp

shah
  • 311
  • 3
  • 20