Hog+svm行人检测

(1)第一个工程是用来训练分类器和检测正样本检测率的

// PeopleDetectHog.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream> 
#include <ctype.h>
#include "cv.h" 
#include "highgui.h" 
#include "stdafx.h" 
#include <ml.h> 
#include <fstream> 
#include <math.h>
#include <string> 
#include <vector> 
#include <stdio.h>

using namespace cv; 
using namespace std;

class Mysvm: public CvSVM 

public: 
int get_alpha_count() 

return this->sv_total; 
}

int get_sv_dim() 

return this->var_all; 
}

int get_sv_count() 

return this->decision_func->sv_count; 
}

double* get_alpha() 

return this->decision_func->alpha; 
}

float** get_sv() 

return this->sv; 
}

float get_rho() 

return this->decision_func->rho; 

};

int _tmain(int argc, _TCHAR* argv[])
{
int positiveSampleCount = 2416; //正样本数
int negativeSampleCount = 18185; //负样本数
int totalSampleCount = positiveSampleCount + negativeSampleCount; 

FILE* fp = fopen("PeopleDetectResult_INRIA2416.txt","w"); 

if(fp==NULL)
{
int n = GetLastError();
exit(1);


CvMat *sampleFeaturesMat = cvCreateMat(totalSampleCount , 3780, CV_32FC1); //这里第二个参数1764是hog维数,即矩阵的列是由下面的featureVec的大小决定的,可以由descriptors.size()得到,
//64*64的训练样本,该矩阵将是totalSample*1764;若是64*128,则对应3780维

cvSetZero(sampleFeaturesMat); 
CvMat *sampleLabelMat = cvCreateMat(totalSampleCount, 1, CV_32FC1); //存储样本图片类型 ,正样本1,负样本-1 
cvSetZero(sampleLabelMat); 

// fprintf(fp, "%s\n","Hog描述算子:\n SVM参数:"); 
cout<<"waiting......"<<endl; 
cout<<"start to training positive samples..."<<endl;

string buf; 
char line[512]; 
vector<string> img_path;//输入文件名变量
ifstream svm_data( "D:\\program\\matlabprojects\\PeopleSample\\pos1\\train_list.txt");
while (svm_data)
{
if (getline( svm_data, buf ))
{
img_path.push_back( buf ); 
}


svm_data.close();//关闭文件

IplImage* src; 
IplImage* img=cvCreateImage(cvSize(64,128),8,3);//需要分析的图片,这里默认设定图片是64*128大小,所以上面定义了3780,如果要更改图片大小,可以先用debug查看一下descriptors是多少,然后设定好再运行 

long t1 = GetTickCount();
for(int i=0; i<positiveSampleCount; i++) 

src=cvLoadImage(img_path[i].c_str(),1);
cvResize(src,img); //读取正样本图片
if( img == NULL ) 

cout<<" can not load the image:"<<img_path[i].c_str()<<endl; 
continue; 

cout<<" processing "<<img_path[i].c_str()<<endl; 

cv::HOGDescriptor hog(cv::Size(64,128), cv::Size(16,16), cv::Size(8,8),cv::Size(8,8), 9); 
//HOG的描述函数。如果是64*128的训练样本,需要把第一个参数改为cv::Size(64,128) 

vector<float> featureVec; 
hog.compute(img, featureVec, cv::Size(8,8)); //featureVec--存储每个样本图片的HOG特征向量 
for (int j=0; j<featureVec.size(); j++) 

CV_MAT_ELEM( *sampleFeaturesMat, float, i, j ) = featureVec[j]; 

sampleLabelMat->data.fl[i] = 1; 


cvReleaseImage( &src); 
cvReleaseImage( &img); 
cout<<"end of training for positive samples..."<<endl; 

long t2 = GetTickCount();
fprintf(fp, "%s%d\n", "training for positive samples timeis:",t2-t1); 

cout<<"waiting......"<<endl; 
cout<<"start to train negative samples..."<<endl; 

string buff; 
int m;
vector<string> img_neg_path;//输入文件名变量
ifstream svm_neg_data( "D:\\program\\matlabprojects\\PeopleSample\\neg4\\train_list.txt");
while (svm_neg_data)
{
if (getline( svm_neg_data, buff ))
{
img_neg_path.push_back( buff ); 
}


svm_neg_data.close();//关闭文件
IplImage* neg;
IplImage* neg_img=cvCreateImage(cvSize(64,128),8,3);

for (int i=0; i<negativeSampleCount; i++) 

neg = cvLoadImage(img_neg_path[i].c_str(),1); //读取负样本图片
cvResize(neg,neg_img); //读取正样本图片
if( neg_img == NULL ) 

cout<<" can not load the image:"<<img_path[i].c_str()<<endl; 
continue; 


cout<<" processing"<<img_neg_path[i].c_str()<<endl; 
cv::HOGDescriptor hog(cv::Size(64,128), cv::Size(16,16), cv::Size(8,8),cv::Size(8,8), 9); //若为64*128的样本,需要将第一个参数做出改动(上述) 
vector<float> featureVec; 
hog.compute(neg_img,featureVec,cv::Size(8,8)); //featureVec.size(),且对于不同大小的输入训练图片,这个值是不同的 
//cout<<"The featureVector number of negativeSample is:"<<featureVec.size()<<endl; //查看一下featureVec的大小
for ( int j=0; j<featureVec.size(); j ++) 

CV_MAT_ELEM( *sampleFeaturesMat, float, i + positiveSampleCount, j ) =featureVec[ j ]; //把HOG存储下来


sampleLabelMat->data.fl[ i + positiveSampleCount ] = -1; 
m = i+1;

cout<<"The count of negativeSample is:"<<m<<endl;//统计处理过的负样本数目
fprintf(fp, "%s%d\n", "The count of negativeSample is:",m);
cout<<"end of training for negative samples..."<<endl; 

long t3 = GetTickCount();
cout<<"waiting......"<<endl; 
fprintf(fp, "%s%d\n", "training for negative samples timeis:",t3-t1); 

//☆☆☆☆☆☆☆☆☆(5)SVM学习☆☆☆☆☆☆☆☆☆☆☆☆ 

cout<<"start to train for SVM classifier..."<<endl; 

// SVM种类:CvSVM::C_SVC 
// Kernel的种类:CvSVM::LINEAR 
// degree:10.0(此次不使用) 
// gamma:8.0 
// coef0:1.0(此次不使用) 
// C:0.01 
// nu:0.5(此次不使用) 
// p:0.1(此次不使用) 
// 然后对训练数据正规化处理,并放在CvMat型的数组里。 

CvSVMParams params; 
params.svm_type = CvSVM::C_SVC; 
params.kernel_type = CvSVM::LINEAR; 
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 1000, FLT_EPSILON); 
params.C = 0.01;

Mysvm svm;
long t4 = GetTickCount();

svm.train( sampleFeaturesMat, sampleLabelMat, NULL, NULL, params ); //用SVM线性分类器训练 
//sampleFeaturesMat保存各样本的特征值,sampleLabelMat保存图片类型*/

//保存最终的SVM
long t5 = GetTickCount();
fprintf(fp, "%s%d\n", "Time of train for SVM classifier is:",t5-t4); 
svm.save( "SVM_DATA.xml" ); 
cout<<"SVM_DATA.xml保存完毕!"<<endl;

cvReleaseMat(&sampleFeaturesMat); 
cvReleaseMat(&sampleLabelMat); 

int supportVectorSize = svm.get_support_vector_count(); 
cout<<"support vector size of SVM:"<<supportVectorSize<<endl; 
cout<<"SVM completed"<<endl; 

CvMat *sv,*alp,*re; //所有样本特征向量 
sv = cvCreateMat(supportVectorSize , 3780, CV_32FC1); 
alp = cvCreateMat(1 , supportVectorSize, CV_32FC1); 
re = cvCreateMat(1 , 3780, CV_32FC1); 
CvMat *res = cvCreateMat(1 , 1, CV_32FC1); 

cvSetZero(sv); 
cvSetZero(re); 

for(int i=0; i<supportVectorSize; i++) 

memcpy( (float*)(sv->data.fl+i*3780), svm.get_support_vector(i), 3780*sizeof(float));


double* alphaArr = svm.get_alpha(); 
int alphaCount = svm.get_alpha_count(); 

for(int i=0; i<supportVectorSize; i++) 

alp->data.fl[i] = alphaArr[i]; 

cvMatMul(alp, sv, re); 

int posCount = 0; 
for (int i=0; i<3780; i++) 

re->data.fl[i] *= -1; 


FILE* fpp = fopen("Peopledetector_INRIA2416.txt","w"); 

if(fpp==NULL)
{
int n = GetLastError();
exit(1);

for(int i=0; i<3780; i++) 

fprintf(fpp,"%f \n",re->data.fl[i]); 

float rho = svm.get_rho(); 
fprintf(fpp, "%f", rho); 

cout<<"D:\hogSVMDetector.txt 保存完毕"<<endl; //保存HOG能识别的分类器 

fclose(fpp);

cvReleaseMat(&sv); 
cvReleaseMat(&alp); 
cvReleaseMat(&re); 
cvReleaseMat(&res);

// //***************************************检测正样本************************************ 
//
IplImage *test; 
vector<string> img_tst_path; 
// ifstream img_tst("D:\\program\\matlabprojects\\INRIAPerson\\test_my\\pos_bmp\\train_list.txt");//同输入训练样本,这里也是一样的,只不过不需要标注图片属于哪一类了 
// ifstream img_tst("D:\\train_list.txt");
ifstream img_tst( "D:\\program\\matlabprojects\\PeopleSample\\pos1\\train_list2.txt");
while( img_tst ) 

if( getline( img_tst, buf ) ) 

img_tst_path.push_back( buf ); 


img_tst.close(); 


// CvMat *test_hog = cvCreateMat( 1, 1764, CV_32FC1 );//注意这里的1764,同上面一样 
IplImage* trainImg=cvCreateImage(cvSize(64,128),8,3); 
int right=0;
int wrong=0; //用于计算正确率
int n;
for( string::size_type j = 0; j != img_tst_path.size(); j++ )//依次遍历所有的待检测图片 

test = cvLoadImage( img_tst_path[j].c_str(), 1); 
if( test == NULL ) 

cout<<" can not load the image:"<<img_tst_path[j].c_str()<<endl; 
continue; 


cvZero(trainImg); 
cvResize(test,trainImg); //读取图片 
HOGDescriptor *hog=newHOGDescriptor(cvSize(64,128),cvSize(16,16),cvSize(8,8),cvSize(8,8),9); //具体意思见参考文章1,2 
vector<float>descriptors;//结果数组 

hog->compute(trainImg, descriptors,Size(1,1), Size(0,0)); //调用计算函数开始计算 
cout<<"HOG dims: "<<descriptors.size()<<endl; 
CvMat* SVMtrainMat=cvCreateMat(1,descriptors.size(),CV_32FC1); 
n=0; 
for(vector<float>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++)

cvmSet(SVMtrainMat,0,n,*iter); 
n++; 


int ret = svm.predict(SVMtrainMat);//获取最终检测结果,这个predict的用法见 OpenCV的文档 

if (ret == 1)
{
right += 1;
}
else if (ret == -1)
{
wrong += 1;
}


DOUBLE result ;
result= double(right)/double(right+wrong);
cout<<"The Correct rateis:"<<result*100<<"%"<<endl; //检测正样本的正确率
fprintf(fp,"%s%f%s\n","The Correct rateis:",result*100,"%");
fclose(fp);

cvReleaseImage( &test ); 
cvReleaseImage( &trainImg );

*****************************************开始读入待识别的图像,检测车辆************************************

// IplImage* Img =cvLoadImage("D:\\program\\matlabprojects\\INRIAPerson\\Test\\pos_bmp\\00019.bmp"); //读入图像
// IplImage* DetecImg=cvCreateImage(cvSize(320,240),8,3);

// cvResize(Img,DetecImg);
// long t1 = GetTickCount();
//if (DetecImg == NULL)
//{
// cout<<" can not load the image"<<endl; 
// exit(-1);
//} //检测图像有没有被读入

//vector<float> x;
//
//ifstream fileIn("Peopledetector4.txt", ios::in); 
//float val = 0.0f; 
//while(!fileIn.eof()) 
//{ 
// fileIn>>val; 
// x.push_back(val); 
//} 
//fileIn.close();

//vector<cv::Rect> found; //检测出的车辆数量
//vector<cv::Rect> temp; //用于存放的容器
// vector<vector<cv::Rect>> bigfound;
//vector< vector<cv::Rect>> ::iterator bigit; //功能强大的迭代器

//IplImage* img = NULL;

//cv::HOGDescriptor hog(cv::Size(64,128),cv::Size(16,16), cv::Size(8,8), cv::Size(8,8), 9); 
//hog.setSVMDetector(x); //x向量对应的分类器
//long t3 = GetTickCount();

//cout<<"The process time is:"<<t3-t1<<endl; 
//
// 
hog.detectMultiScale(DetecImg, found, 0.7, cv::Size(8,8), cv::Size(5,5),1.06, 1, false); //检测当前图片的HOG特征,found为检测结果向量
// hog.detectMultiScale(DetecImg, found, 0.3, cv::Size(8,8), cv::Size(8,8),1.05, 2, false); 
//long t4 = GetTickCount();

//cout<<"The process time is:"<<t4-t1<<endl;

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

//cout<<"The number of vehicle is:"<<found_filtered.size()<<endl; //检测车辆数
在图片img上画出矩形框,因为hog检测出的矩形框比实际人体框要稍微大些,所以这里需要
做一些调整
//for(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);
// cvRectangle(DetecImg,cvPoint(r.x,r.y),cvPoint(r.x+r.width,r.y+r.height),CV_RGB(255,0,0),2);
//}
//cvShowImage("img",DetecImg);
//cvWaitKey(0);
//long t5 = GetTickCount();

//cout<<"The process time is:"<<t5-t1<<endl; 
//system("pause");
//cvWaitKey(0);
// 
// cvReleaseImage(&DetecImg);

//**********************************处理视频************************************

CvCapture* cap = cvCreateFileCapture("D:\\项目文档\\智能交通\\行人视频\\20120925\\20120925174702950.avi");//读入视频
if (!cap)
{
cout<<"avi file load error……"<<endl;
system("pause");
exit(-1);
} //检测视频有没有被读入

vector<float> x;

ifstream fileIn("Peopledetector4.txt",ios::in); 
float val = 0.0f; 
while(!fileIn.eof()) 

fileIn>>val; 
x.push_back(val); 

fileIn.close();

vector<cv::Rect> found; //检测出的车辆数量
vector<cv::Rect> temp; //用于存放的容器
vector<vector<cv::Rect>> bigfound;
vector< vector<cv::Rect>> ::iterator bigit; //功能强大的迭代器
cvNamedWindow("img",CV_WINDOW_AUTOSIZE);

IplImage* img = NULL;
IplImage* SizeImg=cvCreateImage(cvSize(320,240),8,3);

long t1 = GetTickCount();
// cv::HOGDescriptor hog(cv::Size(64,64), cv::Size(16,16), cv::Size(8,8),cv::Size(8,8), 9); 
cv::HOGDescriptor hog(cv::Size(64,128), cv::Size(16,16), cv::Size(8,8),cv::Size(8,8), 9);

long t4 = GetTickCount();
cout<<"time:"<<t4-t1<<endl;
hog.setSVMDetector(x); //x向量对应的分类器

while(1)
{
img=cvQueryFrame(cap);
// img = cvLoadImage("D:\\000120.bmp");
cvZero(SizeImg);
cvResize(img,SizeImg);
if(!img) break;
cvWaitKey(1);
//hog.detectMultiScale(img,found,0.9,cv::Size(2,2),cv::Size(64,64),1.06,1,false);
// hog.detectMultiScale(SizeImg, found, 0, Size(8, 8), Size(32, 32), 1.05, 2);
// hog.detectMultiScale(SizeImg, found, 0, cv::Size(11,11), cv::Size(32,32),0.5,2);
// hog.detectMultiScale(SizeImg, found, 1.0, cv::Size(16,16), cv::Size(32,32),1.05, 2, false); 
hog.detectMultiScale(SizeImg, found, 0, Size(8, 8), Size(16, 16), 1.0,2,false);

//检测当前帧的HOG特征,found为检测结果向量

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

cout<<"The number of vehicle is:"<<found_filtered.size()<<endl; //检测人数
//在图片img上画出矩形框,因为hog检测出的矩形框比实际人体框要稍微大些,所以这里需要
//做一些调整
for(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.7);
r.y += cvRound(r.height*0.1);
r.height = cvRound(r.height*0.7);
// rectangle(img, r.tl(), r.br(), Scalar(0, 255, 0), 3);
cvRectangle(SizeImg,cvPoint(r.x,r.y),cvPoint(r.x+r.width,r.y+r.height),CV_RGB(255,0,0),1);
}
cvShowImage("img",SizeImg);
cvWaitKey(1);

}
return 0;

}

(1)其中正负样本的选取还是要根据自己具体的问题选取,开始选取的是INRIA、MIT和TUD的样本库,正样本检测效果还可以95%,只是检测自己的视频图像效果就不好了

(2)样本为64×128,样本生成方法见下一篇日志,哈哈

用matlab生成样本

(1)      生成正样本    

(2)      生成负样本

样本生成之后,在文件夹中建立文本:

dir /b/s/p/w *.bmp>train_list.txt

@pause

即可生成目录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值