Skip to content

Instantly share code, notes, and snippets.

@mrgloom
Created May 6, 2015 21:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrgloom/691df379c79b37710595 to your computer and use it in GitHub Desktop.
Save mrgloom/691df379c79b37710595 to your computer and use it in GitHub Desktop.
hog + linear svm testing
#include "CsvWriter.h"
#include <windows.h>
#include <time.h> // for random number generator
#include <string>
#include <vector>
#include <fstream> // std::ofstream
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
//Constants
const Size winSize = Size(64,128); //detector window size
string int2string(int x)
{
stringstream ss;
ss << x;
string s = ss.str();
return s;
}
//Windows specific code and also it works only when we compiling with MBCS(Multi-Byte Character Set) (VS2010 project option)
vector<string> GetFilesInDir(const string &path, const string &ext)
{
vector<string> names;
HANDLE dir;
WIN32_FIND_DATA w32fd;
if ((dir = FindFirstFile((path + ext).c_str(), &w32fd)) != INVALID_HANDLE_VALUE)
{
do {
const string fileName = w32fd.cFileName;
const string fullFileName = path + "/" + fileName;
const bool is_directory = (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
if (fileName[0] == '.')
continue;
if (is_directory)
continue;
names.push_back(fullFileName);
} while (FindNextFile(dir, &w32fd));
FindClose(dir);
}
return names;
}
Mat ComputeHogDescriptor(const Mat &gray)
{
// This are default values for HOGDescriptor:
// WinSize – new Size(64,128)
// BlockSize – new Size(64,128)
// BlockStride – new Size(64,128)
// CellSize – new Size(64,128)
// NumBins - 9
// DerivApertrure - 1
// WinSigma - -1
// L2HysTreshold – 0.2
// GammaCorrection – true
HOGDescriptor hog;
hog.winSize = winSize;
vector< Point > location; //?
vector< float > descriptors;
hog.compute( gray, descriptors, Size( 8, 8 ), Size( 0, 0 ), location );
Mat features(descriptors);
transpose(features,features);
//#ifdef _DEBUG
// imshow( "gradient", get_hogdescriptor_visu( img->clone(), descriptors, size ) );
// waitKey( 10 );
//#endif
return features;
}
vector<Mat> DataAugumentation(const Mat &img)
{
vector<Mat> vec;
//flip on X axis
Mat res;
flip(img,res,1); // 0 means X axis
vec.push_back(img);
vec.push_back(res);
//imwrite("1.png",img);
//imwrite("2.png",res);
return vec;
}
Mat ComputePositiveExamples(const vector<string> &names)
{
Mat features;
clock_t start;
double duration;
start = clock();
int counter=0;
for(int i=0;i<names.size();++i)
{
Mat gray= imread(names[i],0);
vector<Mat> imgs= DataAugumentation(gray);
for(int i=0;i<imgs.size();++i)
{
Mat descriptor= ComputeHogDescriptor(gray);
features.push_back(descriptor);
counter++;
}
}
cout<< counter << endl;
duration = ( clock() - start ) / (double) CLOCKS_PER_SEC;
cout<<"ComputeHogFeatures: "<< duration <<'\n';
////ver2
////save features
//CsvWriter f_writer("data/pos/hog.csv");
//f_writer.writeMat(features);
////save labels
//CsvWriter l_writer("data/pos/labels.csv");
//Mat labels= Mat::ones(features.rows,1,CV_8UC1);
//l_writer.writeMat(labels);
//ver1 - opencv have a bug in 2.4.10?
////save features
//ofstream ofs;
//ofs.open("pos/hog.csv");
//ofs << cv::format(features, "csv") << std::endl;
//ofs.close();
////save labels
//
//ofs.open("pos/labels.csv");
//ofs << cv::format(labels, "csv") << std::endl;
//ofs.close();
return features;
}
Mat ComputeNegativeExamples(const vector<string> &names,int n_samples)
{
int counter=0;
clock_t start;
double duration;
start = clock();
Rect box;
box.width = winSize.width;
box.height = winSize.height;
Mat features;
srand( (unsigned int)time( NULL ) );
for(size_t i=0;i<names.size();++i)
{
for(size_t k=0;k<n_samples;++k)
{
Mat gray= imread(names[i],0);
box.x = rand() % (gray.cols - box.width);
box.y = rand() % (gray.rows - box.height);
Mat descriptor= ComputeHogDescriptor(gray(box));
#ifdef _DEBUG
imwrite("train_negatives/"+
int2string(i)+"_"+
int2string(k)+".png",
gray(box));
#endif
features.push_back(descriptor);
counter++;
//#ifdef _DEBUG
//imshow( "img", gray(box) );
//waitKey( 10 );
//#endif
}
}
cout<< counter << endl;
duration = ( clock() - start ) / (double) CLOCKS_PER_SEC;
cout<<"ComputeNegativeExamples: "<< duration <<'\n';
////save features
//CsvWriter f_writer("data/neg/hog.csv");
//f_writer.writeMat(features);
////save labels
//CsvWriter l_writer("data/neg/labels.csv");
//Mat labels= Mat::zeros(features.rows,1,CV_8UC1);
//l_writer.writeMat(labels);
return features;
}
void TrainSVM(const Mat &features, const Mat &labels)
{
cout << "Start training..." << endl;
clock_t start;
start = clock();
// Set up SVM's parameters
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
SVM svm;
svm.train(features, labels);
double duration = ( clock() - start ) / (double) CLOCKS_PER_SEC;
cout<<"TrainSVM: "<< duration <<'\n';
svm.save( "my_people_detector.yml" );
}
Mat TestSVM(const Mat &features)
{
Mat pred_labels(features.rows,1,CV_32FC1);
cout << "Start testing..." << endl;
clock_t start;
start = clock();
SVM svm;
svm.load("my_people_detector.yml");
//for (size_t i=0;i<features.rows;++i)
for (int i=0;i<features.rows;++i)
{
float pred_class= svm.predict(features.row(i));
pred_labels.at<float>(i,0)= pred_class;
}
double duration = ( clock() - start ) / (double) CLOCKS_PER_SEC;
cout<<"TestSVM: "<< duration <<'\n';
return pred_labels;
}
vector<int> GetErrorIdx(Mat &xor)
{
vector<int> idx;
for (size_t i=0;i<xor.rows;++i)
{
if(xor.at<float>(i,0)==1)
idx.push_back(i);
}
return idx;
}
void TestOnPositives(vector<string> &names)
{
SVM svm;
svm.load("my_people_detector.yml");
int counter=0;
clock_t start;
double duration;
start = clock();
for(int i=0;i<names.size();++i)
{
Mat gray= imread(names[i],0);
Mat descriptor= ComputeHogDescriptor(gray);
float label= svm.predict(descriptor);
if(int(label)==0)
{
string stri = int2string(i);
imwrite("hard_positives/"+stri+".png", gray);
counter++;
}
//else if(int(label)==1)
//{
// int f=0;
//}
}
cout<< counter <<'\n';
duration = ( clock() - start ) / (double) CLOCKS_PER_SEC;
cout<<"TestOnPositives: "<< duration <<'\n';
}
Mat MiningHardNegatives(vector<string> &names)
{
Mat features;
SVM svm;
svm.load("my_people_detector.yml");
const int n_samples= 3;
Rect box;
box.width = winSize.width;
box.height = winSize.height;
srand( (unsigned int)time( NULL ) );
int counter=0;
for(size_t i=0;i<names.size();++i)
{
for(size_t k=0;k<n_samples;++k)
{
Mat gray= imread(names[i],0);
box.x = rand() % (gray.cols - box.width);
box.y = rand() % (gray.rows - box.height);
Mat descriptor= ComputeHogDescriptor(gray(box));
//Mat descriptor= ComputeHogDescriptor(gray);
float label= svm.predict(descriptor);
if(int(label)==1)
{
string strk = int2string(k);
string stri = int2string(i);
imwrite("hard_negatives/"+stri+"_"
+strk
+".png", gray(box));
features.push_back(descriptor);
counter++;
}
}
}
cout<< counter << endl;
return features;
}
vector<Rect> DetectObjects(Mat &img)
{
vector<Rect> rcs;
int strideX=64;
int strideY=128;
SVM svm;
svm.load("my_people_detector.yml");
for(int y=0;y<img.rows-winSize.height;y+=strideY)
{
for(int x=0;x<img.cols-winSize.width;x+=strideX)
{
Rect rc= Rect(x,y,winSize.width,winSize.height);
Mat features= ComputeHogDescriptor(img(rc));
if(svm.predict(features)==1)
{
rcs.push_back(rc);
string strx = int2string(x);
string stry = int2string(y);
imwrite("tmp/crop_"+strx+"_"+stry+".png", img(rc));
}
else if(svm.predict(features)==0)
{
int f=0;
}
}
}
#ifdef _DEBUG
for (int i=0;i<rcs.size();++i)
{
rectangle(img, rcs[i], Scalar(0,255,0));
}
imshow( "img", img );
waitKey( 10 );
#endif
return rcs;
}
void CompareLabels(const Mat &labels, const Mat &pred_labels)
{
int counter=0;
for(int y=0;y<labels.rows;++y)
{
if(labels.at<float>(y)!=pred_labels.at<float>(y))
counter++;
}
cout<< counter << endl;
}
void GeTrainTestSplit(Mat &data, Mat &labels,
Mat &train_data, Mat &train_labels,Mat &test_data, Mat &test_labels)
{
//80-20 splits
int y= data.rows*0.8;
train_data= data(Rect(0,0,data.cols,y));
train_labels= labels(Rect(0,0,1,y));
test_data= data(Rect(0,y,data.cols,data.rows-y));
test_labels= labels(Rect(0,y,1,data.rows-y));
int f=0;
}
//наверно оверфит из-за того что кол-во сэмплов меньше чем размерность вектора?
//все классифицирует как 1, но на том что трейнилось работает идеально.
//а если много негативов, то наоборот все классифицирается как фон.
//или дело просто в том, что другой мастаб у двух других выборок, и надо не ресайзить, а кропать
//и вообще надо было сделать пропорцию 80-20 для теста
//или использовать и inria dataset для обучения.
int main()
{
Mat features;
Mat labels;
//dir with positive examples
vector<string> pos_names= GetFilesInDir("C:/Users/user/Desktop/pedestrtian_detection/datasets/pedestrians128x64/", "*.png");
Mat pos= ComputePositiveExamples(pos_names);
features.push_back(pos);
Mat pos_labels= Mat::ones(pos.rows,1,CV_32FC1);
labels.push_back(pos_labels);
//get negative examples by sampling
vector<string> neg_names= GetFilesInDir("C:/Users/user/Desktop/pedestrtian_detection/datasets/INRIAPerson/Test/neg/", "*.png");
int n_samples_per_image= 2*pos_names.size()/neg_names.size()+1;
Mat neg= ComputeNegativeExamples(neg_names, n_samples_per_image);
features.push_back(neg);
Mat neg_labels= Mat::zeros(neg.rows,1,CV_32FC1);
labels.push_back(neg_labels);
Mat train_data;
Mat train_labels;
Mat test_data;
Mat test_labels;
GeTrainTestSplit(features, labels,
train_data, train_labels, test_data, test_labels);
TrainSVM(train_data, train_labels);
Mat pred_labels= TestSVM(test_data);
//Mat xor;
//bitwise_xor(labels, pred_labels, xor);
//int errors= countNonZero(xor);
//cout<< "errors: " << errors <<endl;
CompareLabels(test_labels, pred_labels);
//vector<int> idx= GetErrorIdx(xor);
//////retrain
//////vector<string> neg_names= GetFilesInDir("C:/Users/user/Desktop/pedestrtian_detection/code/HogDetector/HogDetector/train_negatives/", "*.png");
//////vector<string> neg_names= GetFilesInDir("C:/Users/user/Desktop/pedestrtian_detection/datasets/INRIAPerson/Test/neg/", "*.png");
////vector<string> neg_names= GetFilesInDir("C:/Users/user/Desktop/pedestrtian_detection/datasets/INRIAPerson/Train/neg/", "*.png");
////MiningHardNegatives(neg_names);
////vector<string> pos_names= GetFilesInDir("C:/Users/user/Desktop/pedestrtian_detection/datasets/pedestrians128x64/", "*.png");
////vector<string> pos_names= GetFilesInDir("C:/Users/user/Desktop/pedestrtian_detection/datasets/INRIAPerson/70X134H96/Test/pos/128x64/","*.png");
//vector<string> pos_names= GetFilesInDir("C:/Users/user/Desktop/pedestrtian_detection/datasets/INRIAPerson/96X160H96/Train/pos/64x128/","*.png");
//TestOnPositives(pos_names);
//
////Mat img= imread("C:/Users/user/Desktop/pedestrtian_detection/datasets/INRIAPerson/Test/pos/crop001504.png",0);
////DetectObjects(img);
cout<<"all done!";
getchar();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment