Created
May 6, 2015 21:05
-
-
Save mrgloom/691df379c79b37710595 to your computer and use it in GitHub Desktop.
hog + linear svm testing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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