码迷,mamicode.com
首页 > 其他好文 > 详细

hog+svm+检测人(代替默认的参数)

时间:2015-09-06 12:27:02      阅读:248      评论:0      收藏:0      [点我收藏+]

标签:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>
//#include <opencv2/gpu/gpu.hpp>
#include <fstream>
#include <iomanip>

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"

#define FEATURE_DIM 3780

using namespace std;
using namespace cv;


class MySVM : public CvSVM
{
public:
//获得SVM的决策函数中的alpha数组
double * get_alpha_vector()
{
return this->decision_func->alpha;
}

//获得SVM的决策函数中的rho参数,即偏移量
float get_rho()
{
return this->decision_func->rho;
}
};
int main()
{
#if 0
Mat image;
image = imread("D:\\dataset\\temp\\6.png");
HOGDescriptor hog;
vector<float> v_feature;
hog.compute(image, v_feature, cv::Size(8, 8));
//hog.compute(image, v_feature, cv::Size(16, 16));

int featureVecSize = v_feature.size();
cout << "****************************************haha****************" << endl;
cout << featureVecSize << endl;
#else
//***************************************************************************************************
// 初始化
//***************************************************************************************************

//char positivePath[256] = "D:\\dataset\\INRIAPerson\\Train\\pos\\"; //改路径
//char negativePath[256] = "D:\\dataset\\INRIAPerson\\Train\\neg\\";
//char testPath[256] = "D:\\dataset\\INRIAPerson\\Test\\pos\\";
char positivePath[256] = "D:\\dataset\\INRIAPerson\\train_64x128_H96\\pos\\";
char negativePath[256] = "D:\\dataset\\INRIAPerson\\train_64x128_H96\\neg\\";

//char testPath[256] = "D:\\dataset\\INRIAPerson\\70X134H96\\Test\\pos\\";
char testPath[256] = "D:\\dataset\\INRIAPerson\\test_64x128_H96\\pos\\";
//char testPath[256] = "D:\\dataset\\INRIAPerson\\test_64x128_H96\\neg\\";

char classifierSavePath[256] = "D:\\dataset\\INRIAPerson\\myResult";

int positiveSampleCount = 614; //改数据
int negativeSampleCount = 1218;
//int positiveSampleCount = 100;
//int negativeSampleCount = 100;
int totalSampleCount = positiveSampleCount + negativeSampleCount;
int testSampleCount = 1126;
//int testSampleCount = 100;

 

CvMat *sampleFeaturesMat = cvCreateMat(totalSampleCount, FEATURE_DIM, CV_32FC1); //改向量维数
cvSetZero(sampleFeaturesMat);
CvMat *sampleLabelMat = cvCreateMat(totalSampleCount, 1, CV_32FC1);
cvSetZero(sampleLabelMat);

//CvMat *testFeaturesMat = cvCreateMat(testSampleCount, FEATURE_DIM, CV_32FC1); //参数1764? 正288,负453
CvMat *testFeaturesMat = cvCreateMat(1, FEATURE_DIM, CV_32FC1); //参数1764? 正288,负453
cvSetZero(testFeaturesMat);
//CvMat *testLabelMat = cvCreateMat(testSampleCount, 1, CV_32FC1);//样本标识
//cvSetZero(testLabelMat);
float testLabelMat[288] = { 0.0 };
//Mat sampleFeaturesMat();

HOGDescriptor hog(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);//HOG检测器,用来计算HOG描述子的
vector<float> v_feature;


//***************************************************************************************************
// 正例的特征
//***************************************************************************************************
//positive文件读入
//ifstream fin(positivePath, ios::in);
//if (!fin)
//{
// cout << "positivePath can not open the file!" << endl;
// return -1;
//}
char positiveImage[256];
string path;
string s_positiveImage;
for (int i = 0; i < positiveSampleCount; i++)
{
//图片名修改
memset(positiveImage, ‘\0‘, sizeof(positiveImage));
sprintf(positiveImage, "%d.png", i + 1); //要改成.jpg吗
s_positiveImage = positiveImage;
path = positivePath + s_positiveImage;

Mat image = imread(path);
if (image.data == NULL)
{
cout << "positive image sample load error: " << i << " " << path << endl;
system("pause");
continue;
}
//hog特征提取
//gpu::HOGDescriptor hog(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9); //貌似还有一些参数,重载了?
//HOGDescriptor hog(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9);
//HOGDescriptor hog;
// vector<float> v_feature;
image = image(Rect(16, 16, 64, 128));
hog.compute(image, v_feature, cv::Size(8, 8));
//hog.compute(image, v_feature, cv::Size(16, 16));

int featureVecSize = v_feature.size();
//cout << "****************************************haha****************" << endl;
//cout << featureVecSize<<endl;
//return 0;
for (int j = 0; j<featureVecSize; j++)
{
//sampleFeaturesMat[i][j] = v_feature[j];
CV_MAT_ELEM(*sampleFeaturesMat, float, i, j) = v_feature[j]; //CV_MAT_ELEM什么意思
}
sampleLabelMat->data.fl[i] = 1; //.fl[]是什么
cout << "positive" << i + 1 << "is running..." << endl;
}
//fclose(fin);
//***************************************************************************************************
// 负例的特征
//***************************************************************************************************
//negative文件读入
//ifstream fin(negativePath, ios::in);
//if (!fin)
//{
// cout << "can not open the file!" << endl;
// return -1;
//}
char negativeImage[256] = ""; //初始化吗
string s_negativeImage;
for (int i = 0; i < negativeSampleCount; i++)
{
//图片名修改
//hog特征提取
memset(negativeImage, ‘\0‘, sizeof(negativeImage));
sprintf(negativeImage, "%d.png", i + 1); //要改成.jpg吗
s_negativeImage = negativeImage;
path = negativePath + s_negativeImage;
//cout << "********************************************************"<<endl;
//cout << path<<endl;
Mat image = imread(path);
if (image.data == NULL)
{
cout << "positive image sample load error: " << i << " " << path << endl;
system("pause");
continue;
}
//hog特征提取
//gpu::HOGDescriptor hog(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9); //貌似还有一些参数,重载了?
//HOGDescriptor hog(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9);
//HOGDescriptor hog;
//vector<float> v_feature;
image = image(Rect(16, 16, 64, 128));
hog.compute(image, v_feature, cv::Size(8, 8));

int featureVecSize = v_feature.size();
//cout << "***************************lalala*****************************" << endl;
//cout << featureVecSize;

for (int j = 0; j<featureVecSize; j++)
{
CV_MAT_ELEM(*sampleFeaturesMat, float, positiveSampleCount + i, j) = v_feature[j]; //CV_MAT_ELEM什么意思
}
sampleLabelMat->data.fl[positiveSampleCount + i] = 0; //.fl[]是什么
cout << "negative" << i + 1 << "is running..." << endl;
}

//**********************************************************************************************
// Linear SVM训练
//**********************************************************************************************
//设置参数
CvSVMParams params;
params.svm_type = SVM::C_SVC;
params.C = 0.01;
params.kernel_type = SVM::LINEAR;
//params.term_crit = TermCriteria(CV_TERMCRIT_ITER, (int)1e7, 1e-6);
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 1000, FLT_EPSILON);


//训练
cout << "Starting training process" << endl;
//CvSVM svm;
MySVM svm;
svm.train(sampleFeaturesMat, sampleLabelMat, Mat(), Mat(), params);
cout << "Finished training process" << endl;
//**********************************************************************************************
// 结果保存
//**********************************************************************************************
//classifierSavePath文件读入
//ifstream fin(classifierSavePath, ios::in);
//if (!fin)
//{
// cout << "positivePath can not open the file!" << endl;
// return -1;
//}
//svm.save(classifierSavePath);
//cvReleaseMat(&sampleFeaturesMat);
//cvReleaseMat(&sampleLabelMat);
//cout << "has saved succeeded! " << endl;

//**********************************************************************************************
// 测试
//**********************************************************************************************
//test文件读入
//ifstream fin(testPath, ios::in);
//if (!fin)
//{
// cout << "can not open the file!" << endl;
// return -1;
//}
char testImage[256] = ""; //初始化吗
string s_testImage;
for (int i = 0; i < testSampleCount; i++)
{
//图片名修改
//hog特征提取
memset(testImage, ‘\0‘, sizeof(testImage));
sprintf(testImage, "%d.png", i + 1); //要改成.jpg吗
s_testImage = testImage;
path = testPath + s_testImage;

Mat image = imread(path);
if (image.data == NULL)
{
cout << "positive image sample load error: " << i << " " << path << endl;
system("pause");
continue;
}
//hog特征提取
//gpu::HOGDescriptor hog(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9); //貌似还有一些参数,重载了?
//HOGDescriptor hog(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9);
//HOGDescriptor hog;
//vector<float> v_feature;
image = image(Rect(16, 16, 64, 128));
hog.compute(image, v_feature, cv::Size(8, 8));

int featureVecSize = v_feature.size();
//cout << "***************************lalala*****************************" << endl;
//cout << featureVecSize << endl;
for (int j = 0; j<featureVecSize; j++)
{
//CV_MAT_ELEM(*testFeaturesMat, float, i, j) = v_feature[j]; //CV_MAT_ELEM什么意思
CV_MAT_ELEM(*testFeaturesMat, float, 0, j) = v_feature[j];
}
float response = svm.predict(testFeaturesMat);
//testLabelMat->data.fl[i] = response; //.fl[]是什么
testLabelMat[i] = response;
}
float right = 0;
for (int i = 0; i < testSampleCount; i++)
{
//if (testLabelMat->data.fl[i] == 1)
if (testLabelMat[i] == 1)
{
right++;
}
}
float radio = right / testSampleCount;
cout << "the radio of the train is:" << radio << endl;


/*************************************************************************************************
线性SVM训练完成后得到的XML文件里面,有一个数组,叫做support vector,还有一个数组,叫做alpha,有一个浮点数,叫做rho;
将alpha矩阵同support vector相乘,注意,alpha*supportVector,将得到一个列向量。之后,再该列向量的最后添加一个元素rho。
如此,变得到了一个分类器,利用该分类器,直接替换opencv中行人检测默认的那个分类器(cv::HOGDescriptor::setSVMDetector()),
就可以利用你的训练样本训练出来的分类器进行行人检测了。
***************************************************************************************************/
int DescriptorDim = svm.get_var_count();//特征向量的维数,即HOG描述子的维数
int supportVectorNum = svm.get_support_vector_count();//支持向量的个数
cout << "支持向量个数:" << supportVectorNum << endl;

Mat alphaMat = Mat::zeros(1, supportVectorNum, CV_32FC1);//alpha向量,长度等于支持向量个数
Mat supportVectorMat = Mat::zeros(supportVectorNum, DescriptorDim, CV_32FC1);//支持向量矩阵
Mat resultMat = Mat::zeros(1, DescriptorDim, CV_32FC1);//alpha向量乘以支持向量矩阵的结果

//将支持向量的数据复制到supportVectorMat矩阵中
for (int i = 0; i<supportVectorNum; i++)
{
const float * pSVData = svm.get_support_vector(i);//返回第i个支持向量的数据指针
for (int j = 0; j<DescriptorDim; j++)
{
//cout<<pData[j]<<" ";
supportVectorMat.at<float>(i, j) = pSVData[j];
}
}

//将alpha向量的数据复制到alphaMat中
double * pAlphaData = svm.get_alpha_vector();//返回SVM的决策函数中的alpha向量
for (int i = 0; i<supportVectorNum; i++)
{
alphaMat.at<float>(0, i) = pAlphaData[i];
}

//计算-(alphaMat * supportVectorMat),结果放到resultMat中
//gemm(alphaMat, supportVectorMat, -1, 0, 1, resultMat);//不知道为什么加负号?
resultMat = -1 * alphaMat * supportVectorMat;

//得到最终的setSVMDetector(const vector<float>& detector)参数中可用的检测子
vector<float> myDetector;
//将resultMat中的数据复制到数组myDetector中
for (int i = 0; i<DescriptorDim; i++)
{
myDetector.push_back(resultMat.at<float>(0, i));
}
//最后添加偏移量rho,得到检测子
myDetector.push_back(svm.get_rho());
cout << "特征向量维数:" << svm.get_var_count()<< endl;
cout << "检测子维数:" << myDetector.size() << endl;

 

//设置HOGDescriptor的检测子



//cout << "默认检测子维数" << hog.getDefaultPeopleDetector().size()<<endl;
//hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
cout<<"特征描述子:"<<hog.getDescriptorSize()<<endl;
cout << "描述子维数:" << v_feature.size() << endl;
hog.setSVMDetector(myDetector); //#############################


cout << "debug:" << endl;
//保存检测子参数到文件
ofstream fout("HOGDetectorForOpenCV.txt");
for (int i = 0; i<myDetector.size(); i++)
{
fout << myDetector[i] << endl;
}


/**************读入图片进行HOG行人检测******************/
//Mat src = imread("00000.jpg");
//Mat src = imread("2007_000423.jpg");
Mat src = imread("D:\\dataset\\temp\\1.jpg");
vector<Rect> found, found_filtered;//矩形框数组
cout << "进行多尺度HOG人体检测" << endl;
hog.detectMultiScale(src, found, 0, Size(8, 8), Size(32, 32), 1.05, 2);//对图片进行多尺度行人检测
cout << "找到的矩形框个数:" << found.size() << endl;

//找出所有没有嵌套的矩形框r,并放入found_filtered中,如果有嵌套的话,则取外面最大的那个矩形框放入found_filtered中
for (int i = 0; i < found.size(); i++)
{
Rect r = found[i];
int j = 0;
for (; j < found.size(); j++)
if (j != i && (r & found[j]) == r)
break;
if (j == found.size())
found_filtered.push_back(r);
}

//画矩形框,因为hog检测出的矩形框比实际人体框要稍微大些,所以这里需要做一些调整
for (int i = 0; i<found_filtered.size(); i++)
{
Rect r = found_filtered[i];
r.x += cvRound(r.width*0.1);
r.width = cvRound(r.width*0.8);
r.y += cvRound(r.height*0.07);
r.height = cvRound(r.height*0.8);
rectangle(src, r.tl(), r.br(), Scalar(0, 255, 0), 3);
}

imwrite("ImgProcessed.jpg", src);
namedWindow("src", 0);
imshow("src", src);
waitKey();//注意:imshow之后必须加waitKey,否则无法显示图像
#endif
return 0;
}

hog+svm+检测人(代替默认的参数)

标签:

原文地址:http://www.cnblogs.com/Wanggcong/p/4784994.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!