Ask Your Question
1

Completely random result of HOGDescriptor

asked 2018-11-30 00:59:26 -0600

Morales1235 gravatar image

updated 2018-11-30 04:15:59 -0600

Using HOGDescriptor with C++. First of all, how can I identify class of detected object? There is no information in doc and example. I wrote simple program (according to train_HOG.cpp) and trained with vehicles and non-vehicles. So its "one-class"? How descriptor know it found vehicle or non-vehicle?

I did like in example, but it seems to not work (I hoped t see maybe higher density around cars - but it looks completely random! - so even heat map is impossible). One thing different is class name - I used 1 and 2 (for every class folder) but similar results are with classes like in example (-1 and 1). Tried different svm params (default and as in example...). The only thing I can do is show you my code :|

Example positives: image description image description

#include <HogClassifier.h>

#include <iostream>

#include <boost/filesystem.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/adaptor/indexed.hpp>
#include <boost/assert.hpp>

#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/core/ocl.hpp>

#include <opencv2/highgui.hpp>

namespace bfs = boost::filesystem;

HogClassifier::HogClassifier(cv::Size winSize)
{
    mHogs.winSize = winSize;
    //cv::ocl::setUseOpenCL(false);
}

auto HogClassifier::GetImages(std::vector<std::string> dirPaths, std::vector<int>& labels)
{
    int currClassDir = 0;
    std::vector<cv::Mat> images;

    for(auto& root: dirPaths)
    {
        if(bfs::is_directory(root))
        {
            for(const auto& record: boost::make_iterator_range(bfs::recursive_directory_iterator(root, {})))
                if(!bfs::is_directory(record))
                {
                    images.push_back(cv::imread(record.path().string()));
                    labels.push_back(currClassDir);
                }
        }
        else
        {
            std::cout << root << " is not a directory!" << std::endl;
        }
        ++currClassDir;
    }
    return images;
}

auto HogClassifier::GetDescriptors(const std::vector<cv::Mat> &images)
{
    std::vector<cv::Mat> allDdescriptors;
    std::vector<float> singleDescriptors;
    cv::Mat grayImage;

    for(const auto& img: images)
    {
        if(img.cols >= mHogs.winSize.width && img.rows >= mHogs.winSize.height)
        {
            cv::Rect extracted{(img.cols - mHogs.winSize.width) / 2,
                               (img.rows - mHogs.winSize.height) / 2,
                                mHogs.winSize.width, mHogs.winSize.height};
            cv::cvtColor(img(extracted), grayImage, cv::COLOR_BGR2GRAY);
            if(grayImage.data)
            {
                mHogs.compute(grayImage, singleDescriptors, cv::Size(4, 4), cv::Size(0, 0));
                allDdescriptors.push_back(cv::Mat{singleDescriptors}.clone());
            }
        }
    }
    return allDdescriptors;
}

auto HogClassifier::CumulateData(const std::vector<cv::Mat> &uncumulatedData)
{
    using namespace boost::adaptors;
    int columns = std::max(uncumulatedData.at(0).rows, uncumulatedData.at(0).cols);
    int rows = uncumulatedData.size();
    cv::Mat cumulatedData(rows, columns, CV_32F);
    cv::Mat temp(1, columns, CV_32F);

    for(const auto& sample: uncumulatedData | indexed(0))
    {
        if(sample.value().cols == 1)
        {
            cv::transpose(sample.value(), temp);
            temp.copyTo(cumulatedData.row(sample.index()));
        }
        else if(sample.value().rows == 1)
            sample.value().copyTo(cumulatedData.row(sample.index()));
        else
            std::cout << "Wrng data provided for cumulation" << std::endl;
    }

    return cumulatedData;
}

auto HogClassifier::GetSVM(SVMParams svmParams)
{
    auto svm = cv::ml::SVM::create();
    svm->setType(svmParams.type);
    svm->setKernel(svmParams.kernel);
    svm->setTermCriteria(svmParams.termCriteria);
    svm->setDegree(svmParams.degree);
    svm->setCoef0(svmParams.coef0);
    svm->setNu(svmParams.ny);
    svm->setP(svmParams.epsilon);
    svm->setC(svmParams.C);
    return svm;
}

auto HogClassifier::PrepateTrainingData(std::vector<std::string> dirPaths)
{
    std::vector<int> labels;

    auto images = GetImages(dirPaths, labels);
    auto uncumulatedData = GetDescriptors(images);
    auto trainingData = CumulateData(uncumulatedData);

    return std::make_tuple(trainingData, labels);
}

auto HogClassifier::TrainClassifier(cv::Ptr<cv::ml::SVM> svm ...
(more)
edit retag flag offensive close merge delete

Comments

how many train images do you have ?

How descriptor know it found vehicle or non-vehicle?

it's running a sliding window search over the image, computes hog features on that, and decides on candidates by calculating the dot product between the svm's support vector and the current hog feature

berak gravatar imageberak ( 2018-11-30 01:13:54 -0600 )edit
1

I have ~7.3k dataset found in the web. I dont't remember from where, but I did't find wrong photos there. @edit And by that question I mean how it knows which class is vehicle and which is ground?

Morales1235 gravatar imageMorales1235 ( 2018-11-30 01:18:14 -0600 )edit

could you upload a few examples of positive images? you can find some information here

sturkmen gravatar imagesturkmen ( 2018-11-30 03:43:50 -0600 )edit
Morales1235 gravatar imageMorales1235 ( 2018-11-30 04:02:21 -0600 )edit

could you upload here ( i can't access imgur)

sturkmen gravatar imagesturkmen ( 2018-11-30 04:10:56 -0600 )edit
1

Images pasted in main post. I've already read some articles on towardsdatascience. The only thing is another detailed code review with that.

Morales1235 gravatar imageMorales1235 ( 2018-11-30 04:32:05 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2018-11-30 21:52:29 -0600

although cv::HOGDescriptor is going to be a legacy, i like to play with train_HOG.cpp.

i downloaded OwnCollection.rarfrom http://www.gti.ssr.upm.es/data/Vehicl... (i suppose it is part of the dataset you have).

i used images from OwnCollection\vehicles\Far as positives ( 975 images )

for negative images i used images from INRIAPerson dataset ( 1218 images )

example_cpp_train_HOG -d -pd=E:/OwnCollection/vehicles/Far -nd=E:/INRIAPerson/Train/neg

program output:

Positive images are being loaded......[done]
Negative images are being loaded...libpng warning: iCCP: known incorrect sRGB profile
libpng warning: iCCP: known incorrect sRGB profile
.
.(warnings related to the png images)
. 
...[done]
Histogram of Gradients are being calculated for positive images......[done] ( positive count : 975 )
Histogram of Gradients are being calculated for negative images......[done] ( negative count : 1218 )
Training SVM......[done]
Testing trained detector on negative images. This may take a few minutes......[done]
Histogram of Gradients are being calculated for positive images......[done] ( positive count : 975 )
Histogram of Gradients are being calculated for negative images......[done] ( negative count : 8306 )
Training SVM again......[done]

you can test the output detector like example_cpp_train_HOG -t -tv=test_video.mp4 image description

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2018-11-30 00:52:25 -0600

Seen: 429 times

Last updated: Nov 30 '18