Hog SVM 车辆 行人检测
HOG SVM 车辆检测
近期需要对卡口车辆的车脸进行检测,首先选用一个常规的检测方法即是hog特征与SVM,Hog特征是由dalal在2005年提出的用于道路中行人检测的方法,并且取的了不错的识别效果。在人脸检测方面目前主流的方法,先不考虑复杂的深度学习,大多采用Haar和Adaboost的手段来实现。我接下来将会用着两种方法来实现对卡口的车辆检测。
首先引出 Hog特征,Hog特征是梯度方向直方图,是一种底层的视觉特征,主要描述的是图像中的梯度分布情况,而梯度分布信息主要是集中在图像中不同内容之间的边界之处,可以较好的反应图像的基本轮廓面貌。在此处并不展开对描述子的详细介绍,给出一个我当时看的博客链接,对描述子原理分析的比较透彻。hog特征原理
接下来将整个特征提取、训练、检测的流程:
1.首先是准备训练样本,分别是正样本和负样本以及测试样本。正负样本一般来说负样本最好是正样本的2-3倍比较好,覆盖面不要是乱七八糟的图像,要贴合实际应用时的场景来选取,样本对训练过程很重要,很重要,很重要,不要以为随随便便弄一些照片就OK。
2.在程序中导入测试样本,分别提取相应的Hog特征,这个地方我有两点要说明
2.1.样本的尺度要正则化,也就是样本的尺寸要一样,这样可以排除训练样本尺度对模型训练的影响,在正则化的时候,尽量是不要改变其比例。
2.2.在hog特征描述子初始化的时候,需要设置窗口大小,块大小,块滑动大小,以及细胞大小和直方图相应的bin的数目,窗口大小要和输入的训练样本的尺寸一样。
3.提取正负样本的hog特征,我在这里采用的是128128的规模,是正方形的车脸,描述子规模是8100维。
4.SVM采用opencv中自带的,其实opencv中采用的也是某一个版本的LIBSVM,只是重新封装了借口的操作而已。
5.在SVM处,需要注意的是如果之后你要用SVM中自带的detector,也就是用setSVMDetector的话,这个检测器已经是写好了的转门用了处理线性核训练的模型,因为当时dalal用的就是Hog与线性的SVM特征,而且opencv自带的只支持线性的,如果你要用高斯特征即RBF核,不可以采用setSVMDetector,你用了就会出错,根本检测不到真实的位置,这里非常关键,你如果要做分类的话可以直接调用predict,但此处应该只是对车脸与非车脸做,而不是在一张图中找出车脸,如果你要找出目标物,需要自己写相应的detector,来应用你训练好的模型!!!!!
6在检测时,检测窗口的大小必须和训练样本的尺寸是一样的,就是训练时的Hog窗口大小和检测时Hog窗口大小必须保持一致,剩下的就是检测过程中看看没有没嵌套什么的,OK,一下是代码
#include<opencv/cv.h>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/opencv.hpp>
#include<opencv2/gpu/gpu.hpp>
#include<opencv2/ml/ml.hpp>
#include<opencv2/objdetect/objdetect.hpp>
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
using namespace std;
using namespace cv;
#define TRAIN//开关控制是否训练还是直接载入训练好的模型
class MySVM: public CvSVM
{
public:
double * get_alpha_data()
{
return this->decision_func->alpha;
}
double get_rho_data()
{
return this->decision_func->rho;
}
};
void main(int argc, char ** argv)
{
MySVM SVM;
int descriptorDim;
string buffer;
string trainImg;
vector<string> posSamples;
vector<string> negSamples;
vector<string> testSamples;
int posSampleNum;
int negSampleNum;
int testSampleNum;
string basePath = "";//相对路径之前加上基地址,如果训练样本中是相对地址,则都加上基地址
double rho;
#ifdef TRAIN
ifstream fInPos("D:\\DataSet\\CarFaceDataSet\\PositiveSample.txt");//读取正样本
ifstream fInNeg("D:\\DataSet\\CarFaceDataSet\\NegtiveSample.txt");//读取负样本
while (fInPos)//讲正样本读入imgPathList中
{
if(getline(fInPos, buffer))
posSamples.push_back(basePath + buffer);
}
posSampleNum = posSamples.size();
fInPos.close();
while(fInNeg)//读取负样本
{
if (getline(fInNeg, buffer))
negSamples.push_back(basePath + buffer);
}
negSampleNum = negSamples.size();
fInNeg.close();
Mat sampleFeatureMat;//样本特征向量矩阵
Mat sampleLabelMat;//样本标签
HOGDescriptor * hog = new HOGDescriptor (cvSize(128, 128), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 9);
vector<float> descriptor;
for(int i = 0 ; i < posSampleNum; i++)// 处理正样本
{
Mat inputImg = imread(posSamples[i]);
cout<<"processing "<<i<<"/"<<posSampleNum<<" "<<posSamples[i]<<endl;
Size dsize = Size(128,128);
Mat trainImg = Mat(dsize, CV_32S);
resize(inputImg, trainImg, dsize);
hog->compute(trainImg, descriptor, Size(8, 8));
descriptorDim = descriptor.size();
if(i == 0)//首次特殊处理根据检测到的维数确定特征矩阵的尺寸
{
sampleFeatureMat = Mat::zeros(posSampleNum + negSampleNum, descriptorDim, CV_32FC1);
sampleLabelMat = Mat::zeros(posSampleNum + negSampleNum, 1, CV_32FC1);
}
for(int j = 0; j < descriptorDim; j++)//将特征向量复制到矩阵中
{
sampleFeatureMat.at<float>(i, j) = descriptor[j];
}
sampleLabelMat.at<float>(i, 0) = 1;
}
cout<<"extract posSampleFeature done"<<endl;
for(int i = 0 ; i < negSampleNum; i++)//处理负样本
{
Mat inputImg = imread(negSamples[i]);
cout<<"processing "<<i<<"/"<<negSampleNum<<" "<<negSamples[i]<<endl;
Size dsize = Size(128,128);
Mat trainImg = Mat(dsize, CV_32S);
resize(inputImg, trainImg, dsize);
hog->compute(trainImg, descriptor, Size(8,8));
descriptorDim = descriptor.size();
for(int j = 0; j < descriptorDim; j++)//将特征向量复制到矩阵中
{
sampleFeatureMat.at<float>(posSampleNum + i, j) = descriptor[j];
}
sampleLabelMat.at<float>(posSampleNum + i, 0) = -1;
}
cout<<"extract negSampleFeature done"<<endl;
//此处先预留hard example 训练后再添加
ofstream foutFeature("SampleFeatureMat.txt");//保存特征向量文件
for(int i = 0; i < posSampleNum + negSampleNum; i++)
{
for(int j = 0; j < descriptorDim; j++)
{
foutFeature<<sampleFeatureMat.at<float>(i, j)<<" ";
}
foutFeature<<"\n";
}
foutFeature.close();
cout<<"output posSample and negSample Feature done"<<endl;
CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_ITER, 1000, FLT_EPSILON);
CvSVMParams params(CvSVM::C_SVC, CvSVM::LINEAR, 0, 1, 0, 0.01, 0, 0, 0, criteria); //这里一定要注意,LINEAR代表的是线性核,RBF代表的是高斯核,如果要用opencv自带的detector必须用线性核,如果自己写,或者只是判断是否为车脸的2分类问题则可以用RBF,在此应用环境中线性核的性能还是不错的
cout<<"SVM Training Start..."<<endl;
SVM.train_auto(sampleFeatureMat, sampleLabelMat, Mat(), Mat(), params);
SVM.save("SVM_Model.xml");
cout<<"SVM Training Complete"<<endl;
#endif
#ifndef TRAIN
SVM.load("SVM_Model.xml");//加载模型文件
#endif
descriptorDim = SVM.get_var_count();
int supportVectorNum = SVM.get_support_vector_count();
cout<<"support vector num: "<< supportVectorNum <<endl;
Mat alphaMat = Mat::zeros(1, supportVectorNum, CV_32FC1);
Mat supportVectorMat = Mat::zeros(supportVectorNum, descriptorDim, CV_32FC1);
Mat resultMat = Mat::zeros(1, descriptorDim, CV_32FC1);
for (int i = 0; i < supportVectorNum; i++)//复制支持向量矩阵
{
const float * pSupportVectorData = SVM.get_support_vector(i);
for(int j = 0 ;j < descriptorDim; j++)
{
supportVectorMat.at<float>(i,j) = pSupportVectorData[j];
}
}
double *pAlphaData = SVM.get_alpha_data();
for (int i = 0; i < supportVectorNum; i++)//复制函数中的alpha 记住决策公式Y= wx+b
{
alphaMat.at<float>(0, i) = pAlphaData[i];
}
resultMat = -1 * alphaMat * supportVectorMat; //alphaMat就是权重向量
//cout<<resultMat;
cout<<"描述子维数 "<<descriptorDim<<endl;
vector<float> myDetector;
for (int i = 0 ;i < descriptorDim; i++)
{
myDetector.push_back(resultMat.at<float>(0, i));
}
rho = SVM.get_rho_data();
myDetector.push_back(rho);
cout<<"检测子维数 "<<myDetector.size()<<endl;
HOGDescriptor myHOG (Size(128, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);
myHOG.setSVMDetector(myDetector);//设置检测子
//保存检测子
int minusNum = 0;
int posNum = 0;
ofstream foutDetector("HogDetectorForCarFace.txt");
for (int i = 0 ;i < myDetector.size(); i++)
{
foutDetector<<myDetector[i]<<" ";
//cout<<myDetector[i]<<" ";
}
//cout<<endl<<"posNum "<<posNum<<endl;
//cout<<endl<<"minusNum "<<minusNum<<endl;
foutDetector.close();
//test part
ifstream fInTest("D:\\DataSet\\CarFaceDataSet\\testSample.txt");
while (fInTest)
{
if(getline(fInTest, buffer))
{
testSamples.push_back(basePath + buffer);
}
}
testSampleNum = testSamples.size();
fInTest.close();
for (int i = 0; i < testSamples.size(); i++)
{
Mat testImg = imread(testSamples[i]);
Size dsize = Size(320, 240);
Mat testImgNorm (dsize, CV_32S);
resize(testImg, testImgNorm, dsize);
vector<Rect> found, foundFiltered;
cout<<"MultiScale detect "<<endl;
myHOG.detectMultiScale(testImgNorm, found, 0, Size(8,8), Size(0,0), 1.05, 2);
cout<<"Detected Rect Num"<< found.size()<<endl;
for (int i = 0; i < found.size(); i++)//查看是否有嵌套的矩形框
{
Rect r = found[i];
int j = 0;
for (; j < found.size(); j++)
{
if ( i != j && (r & found[j]) == r)
{
break;
}
}
if(j == found.size())
foundFiltered.push_back(r);
}
for( int i = 0; i < foundFiltered.size(); i++)//画出矩形框
{
Rect r = foundFiltered[i];
rectangle(testImgNorm, r.tl(), r.br(), Scalar(0,255,0), 1);
}
imshow("test",testImgNorm);
waitKey();
}
system("pause");
}




总体效果还是不错的,如果对hardexample,进行进一步训练,以及样本的数据进行clean,相信精度还可以进一步提高,并且现在维数也比价高,位了加快检测还可以用PCA进一步降维,但必须自己重新写detector了哦,一定要好好理解一下detector,其实hog + svm的代码很多,本质上都是差不多的。
Hog SVM 车辆 行人检测的更多相关文章
- 利用HOG+SVM实现行人检测
利用HOG+SVM实现行人检测 很久以前做的行人检测,现在稍加温习,上传记录一下. 首先解析视频,提取视频的每一帧形成图片存到磁盘.代码如下 import os import cv2 videos_s ...
- OpenCV中基于HOG特征的行人检测
目前基于机器学习方法的行人检测的主流特征描述子之一是HOG(Histogram of Oriented Gradient, 方向梯度直方图).HOG特征是用于目标检测的特征描述子,它通过计算和统计图像 ...
- 基于YOLOv3和Qt5的车辆行人检测(C++版本)
概述 YOLOv3: 车辆行人检测算法 GitHub Qt5: 制作简单的GUI OpenCV:主要用于putText.drawRec等 Step YOLOv3检测结果 Fig 1. input im ...
- opencv+树莓PI的基于HOG特征的行人检测
树莓PI远程控制摄像头请参考前文:http://www.cnblogs.com/yuliyang/p/3561209.html 参考:http://answers.opencv.org/questio ...
- paper 86:行人检测资源(上)综述文献【转载,以后使用】
行人检测具有极其广泛的应用:智能辅助驾驶,智能监控,行人分析以及智能机器人等领域.从2005年以来行人检测进入了一个快速的发展阶段,但是也存在很多问题还有待解决,主要还是在性能和速度方面还不能达到一个 ...
- PCL行人检测
首先我们知道Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功,HOG+SVM进行行人检测的方法是法国研究人员Dalal在2005的CVPR上提出的,而如今虽然有很 ...
- HoG SVM 目标检测分析
前一段时间开始了解HoG跟SVM行人识别,看了很多包括Dalal得前辈的文章及经验分享,对HoG理论有了些初步的认识. HoG 的全称是 Histogram of Oriented Gradient, ...
- paper 87:行人检测资源(下)代码数据【转载,以后使用】
这是行人检测相关资源的第二部分:源码和数据集.考虑到实际应用的实时性要求,源码主要是C/C++的.源码和数据集的网址,经过测试都可访问,并注明了这些网址最后更新的日期,供学习和研究进行参考.(欢迎补充 ...
- 行人检测(Pedestrian Detection)资源
一.论文 综述类的文章 [1]P.Dollar, C. Wojek,B. Schiele, et al. Pedestrian detection: an evaluation of the stat ...
随机推荐
- 与众不同 windows phone (43) - 8.0 相机和照片: 镜头的可扩展性, 图片的可扩展性, 图片的自动上传扩展
[源码下载] 与众不同 windows phone (43) - 8.0 相机和照片: 镜头的可扩展性, 图片的可扩展性, 图片的自动上传扩展 作者:webabcd 介绍与众不同 windows ph ...
- SqlServer 2008 R2定时备份数据库,并且发送邮件通知
先配置数据库的邮件设置,这样才可以发送邮件. 2. 3. 4. 5. 6. 7. 8. 9. 10. 总的预览图,如图 执行这一段(先发送备份邮件,然后进行数据备份,将昨天的发送数据插入到另一张表中, ...
- (旧)子数涵数·Flash——影片剪辑的其他操作
一.复制影片剪辑 1.方法:duplicatemovieClip(影片实名,新实名,深度级别) 2.解释:影片实名就是你要复制的对象,新实名就是你要粘贴的对象,深度级别就是粘贴后的影片剪辑的堆叠顺序( ...
- 记录php日志
1.记录PHP错误日志 display_errors与log_errors的区别 display_errors 错误回显,一般常用于开发模式,但是很多应用在正式环境中也忘记了关闭此选项.错误回显可以暴 ...
- 【GOF23设计模式】外观模式
来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_外观模式.公司注册流程.迪米特法则 package com.test.facade; public interface 工 ...
- js中的排序
不靠谱的sort() 众所周知,js中的sort()排序是按字母表顺序排序的,这就导致如下现象: var a = [9,60,111,55,8,7777]; a.sort(); alert(a); / ...
- 用css伪类实现提示框效果
题目要求用css实现下图效果: 很明显难点就在那个多出去的三角形上,下面代码是用一个div来实现的,用到了伪类 : befor和 : after,使用这两个伪类活生生的在div之前和之后多出了&quo ...
- WCF Service部署在IIS上
环境vs2010,WCF应用程序.如何将WCF部署在IIS上. 第一步:右键点击项目,选择生成部署包. 第二步:在你项目所在的文件目录下找到Package文件夹,这就是我们的部署包所在的地方.在这个p ...
- jQuery $.extend()用法总结
Query开发插件的两个方法 1.jQuery.extend(object);为扩展jQuery类本身.为类添加新的方法. 2.jQuery.fn.extend(object);给jQuery对象添加 ...
- FME2014汉化问题
问题:FME2014汉化包安装上不起作用,安装环境是是Win7 64位,FME是64位版本的,默认位置在Program Files\FME下,而汉化包安装默认位置在Program Files (x86 ...