Completely random result of HOGDescriptor
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:
#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 ...
how many train images do you have ?
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
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?
could you upload a few examples of positive images? you can find some information here
https://imgur.com/k1hMggu, https://imgur.com/9bfsrWJ and that's hownegative looks: https://imgur.com/9bfsrWJ
could you upload here ( i can't access imgur)
Images pasted in main post. I've already read some articles on towardsdatascience. The only thing is another detailed code review with that.