opencv之HOG特征详解与行人检测
- 格式:docx
- 大小:1.10 MB
- 文档页数:4
⽬标检测学习_1(⽤opencv⾃带hog实现⾏⼈检测) 本⽂主要介绍下opencv中怎样使⽤hog算法,因为在opencv中已经集成了hog这个类。
其实使⽤起来是很简单的,从后⾯的代码就可以看出来。
本⽂参考的资料为opencv⾃带的sample。
关于opencv中hog的源码分析,可以参考本⼈的另⼀篇博客: 开发环境:opencv2.4.2+Qt4.8.2+ubuntu12.04+QtCreator2.5. 实验功能: 单击Open Image按钮,选择需要进⾏⼈检测的⼀张图⽚,确定后⾃动显⽰出来。
该图⽚的⼤⼩没限制。
单击People Detect按钮,则程序会⾃动对该图⽚进⾏⾏⼈检测,且将检测到的效果显⽰出来,即⽤1个矩形框将⾏⼈框出来。
单击Close按钮,退出程序。
实验说明: 1. hog描述⼦在opencv中为HOGDescriptor。
2. 可以调⽤该描述⼦setSVMDetector⽅法给⽤于对hog特征进⾏分类的svm模型的系数赋值,这⾥的参数为HOGDescriptor::getDefaultPeopleDetector()时表⽰采⽤系统默认的参数,因为这些参数是⽤很多图⽚训练⽽来的。
3. 对输⼊图⽚进⾏⾏⼈检测时由于图⽚的⼤⼩不⼀样,所以要⽤到多尺度检测。
这⾥是⽤hog类的⽅法detectMultiScale。
参数解释如下:HOGDescriptor::detectMultiScale(const GpuMat& img, vector<Rect>& found_locations, doublehit_threshold=0, Size win_stride=Size(), Size padding=Size(),double scale0=1.05, int group_threshold=2) 该函数表⽰对输⼊的图⽚img进⾏多尺度⾏⼈检测img为输⼊待检测的图⽚;found_locations为检测到⽬标区域列表;参数3为程序内部计算为⾏⼈⽬标的阈值,也就是检测到的特征到SVM分类超平⾯的距离;参数4为滑动窗⼝每次移动的距离。
第33卷 第4期2011年4月武 汉 理 工 大 学 学 报JOURNAL OF WUHAN UNIVERSITY OF TECHNOLOGY V ol.33 N o.4 A pr.2011DOI:10.3963/j.issn.1671 4431.2011.04.030基于HOG 和颜色特征的行人检测曲永宇,刘 清,郭建明,周生辉(武汉理工大学自动化学院,武汉430070)摘 要: 基于梯度方向直方图(H OG )特征的行人检测是目前检测精度较高的主流方法。
针对基于梯度直方图特征的行人检测存在检测精度还有待提高、向量维数大的问题,提出使用梯度直方图统计特征加颜色频率和肤色特征描述行人,选取一些分类能力较强的block 作为最后的特征,使用线性SV M 分类。
在IN RIA 库上的实验证明,该方法能有效地提高检测精度。
关键词: 行人检测; 梯度直方图(HO G); 颜色特征; block 选择中图分类号: T P 751.1文献标识码: A 文章编号:1671 4431(2011)04 0134 05HOG and Color Based Pedestrian DetectionQU Yong y u,L I U Qing ,G UO J ian ming ,ZH O U S heng hui(Scho ol o f A uto matio n,Wuhan U niv ersity of T echno lo gy ,W uhan 430070,China)Abstract: H istog r am o f or iented g radient(H OG )based on pedestr ian detect ion is the popular method w ith t he hig hest detection rat e curr ent ly.T o further im pr ove its detection r ate and decrease its larg e dimensions o f feat ur es,this paper in tegr ates HO G w ith color frequent and skin colo r feature to descr ibe pedestr ian,w e select some blo ck features w ith better classify ing ability as t he final featur e,then use linear SVM as our classifier.T he ex per iment o n IN RI A demo nstr ates t he hig h detection r ate of our met ho d.Key words: pedestr ian detection; hist og ram of o riented gr adient(HO G); color featur e; blo ck selection收稿日期:2010 08 15.基金项目:湖北省自然科学基金(2009CD B403)和武汉理工大学自主创新研究基金(2010 Va 012).作者简介:曲永宇(1987 ),女,硕士生.E mail:quyong yu163@ 行人检测在视频监控[1]、机器人学、虚拟现实技术等领域有广泛的应用,也是计算机视觉和模式识别领域中的重要研究方向。
【转载】opencv实现⼈脸检测全⽂转载⾃CSDN的博客(不知道怎么将CSDN的博客转到博客园,应该没这功能吧,所以直接复制全⽂了),转载地址如下本篇⽂章主要介绍了如何使⽤OpenCV实现⼈脸检测。
本⽂不具体讲解⼈脸检测的原理,直接使⽤OpenCV实现。
OpenCV版本:2.4.10;VS开发版本:VS2012。
⼀、OpenCV⼈脸检测要实现⼈脸识别功能,⾸先要进⾏⼈脸检测,判断出图⽚中⼈脸的位置,才能进⾏下⼀步的操作。
1、OpenCV⼈脸检测的⽅法在OpenCV中主要使⽤了两种特征(即两种⽅法)进⾏⼈脸检测,Haar特征和LBP特征。
在OpenCV中,使⽤已经训练好的XML格式的分类器进⾏⼈脸检测。
在OpenCV的安装⽬录下的sources⽂件夹⾥的data⽂件夹⾥可以看到下图所⽰的内容:上图中⽂件夹的名字“haarcascades”、“hogcascades”和“lbpcascades”分别表⽰通过“haar”、“hog”和“lbp”三种不同的特征⽽训练出的分类器:即各⽂件夹⾥的⽂件。
"haar"特征主要⽤于⼈脸检测,“hog”特征主要⽤于⾏⼈检测,“lbp”特征主要⽤于⼈脸识别。
打开“haarcascades”⽂件夹,如下图所⽰图中的XML⽂件即是我们⼈脸检测所需要的分类器⽂件。
在实际使⽤中,推荐使⽤上图中被标记的“haarcascade_frontalface_alt2.xml”分类器⽂件,准确率和速度都⽐较好。
2、OpenCV中的⼈脸检测的类在OpenCV中,使⽤类“CascadeClassifier”进⾏⼈脸检测CascadeClassifier faceCascade; //实例化对象所需要使⽤的函数:faceCascade.load("../data/haarcascade_frontalface_alt2"); //加载分类器faceCascade.detectMultiScale(imgGray, faces, 1.2, 6, 0, Size(0, 0)); //多尺⼨检测⼈脸实现⼈脸检测主要依赖于detectMultiScale()函数,下⾯简单说⼀下函数参数的含义,先看函数原型:1. CV_WRAP virtual void detectMultiScale( const Mat& image,2. CV_OUT vector<Rect>& objects,3. double scaleFactor=1.1,4. int minNeighbors=3, int flags=0,5. Size minSize=Size(),6. Size maxSize=Size() );各参数含义:const Mat& image: 需要被检测的图像(灰度图)vector<Rect>& objects: 保存被检测出的⼈脸位置坐标序列double scaleFactor: 每次图⽚缩放的⽐例int minNeighbors: 每⼀个⼈脸⾄少要检测到多少次才算是真的⼈脸int flags:决定是缩放分类器来检测,还是缩放图像Size(): 表⽰⼈脸的最⼤最⼩尺⼨⼆、代码实现1、检测图⽚中的⼈脸#include<opencv2/objdetect/objdetect.hpp>#include<opencv2/highgui/highgui.hpp>#include<opencv2/imgproc/imgproc.hpp>using namespace cv;//⼈脸检测的类CascadeClassifier faceCascade;int main(){faceCascade.load("../data/haarcascade_frontalface_alt2.xml"); //加载分类器,注意⽂件路径Mat img = imread("../data/PrettyGirl.jpg");Mat imgGray;vector<Rect> faces;if(img.empty()){return1;}if(img.channels() ==3){cvtColor(img, imgGray, CV_RGB2GRAY);}else{imgGray = img;}faceCascade.detectMultiScale(imgGray, faces, 1.2, 6, 0, Size(0, 0)); //检测⼈脸if(faces.size()>0){for(int i =0; i<faces.size(); i++){rectangle(img, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height), Scalar(0, 255, 0), 1, 8); //框出⼈脸位置}}imshow("FacesOfPrettyGirl", img);waitKey(0);return0;}结果如下图:2、检测视频中的⼈脸//头⽂件#include<opencv2/objdetect/objdetect.hpp>#include<opencv2/highgui/highgui.hpp>#include<opencv2/imgproc/imgproc.hpp>using namespace cv;//⼈脸检测的类CascadeClassifier faceCascade;int main(){faceCascade.load("../data/haarcascade_frontalface_alt2.xml"); //加载分类器,注意⽂件路径VideoCapture cap;cap.open(0); //打开摄像头//cap.open("../data/test.avi"); //打开视频Mat img, imgGray;vector<Rect> faces;int c = 0;if(!cap.isOpened()){return1;}while(c!=27)cap>>img;if(img.channels() ==3){cvtColor(img, imgGray, CV_RGB2GRAY);}else{imgGray = img;}faceCascade.detectMultiScale(imgGray, faces, 1.2, 6, 0, Size(0, 0)); //检测⼈脸if(faces.size()>0){for(int i =0; i<faces.size(); i++){rectangle(img, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height),Scalar(0, 255, 0), 1, 8); //框出⼈脸位置}}imshow("Camera", img);c = waitKey(1);}return0;}在视频实时检测时,可能会出现卡顿,是因为检测⼈脸花费了过多的时间,这⾥代码只实现基本功能,并未优化。
HogSVM车辆⾏⼈检测HOG SVM 车辆检测 近期需要对卡⼝车辆的车脸进⾏检测,⾸先选⽤⼀个常规的检测⽅法即是hog特征与SVM,Hog特征是由dalal在2005年提出的⽤于道路中⾏⼈检测的⽅法,并且取的了不错的识别效果。
在⼈脸检测⽅⾯⽬前主流的⽅法,先不考虑复杂的深度学习,⼤多采⽤Haar和Adaboost的⼿段来实现。
我接下来将会⽤着两种⽅法来实现对卡⼝的车辆检测。
⾸先引出 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 TRAINifstream 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必须⽤线性核,如果⾃⼰写,或者只是判断是否为车 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 TRAINSVM.load("SVM_Model.xml");//加载模型⽂件#endifdescriptorDim = 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 partifstream 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的代码很多,本质上都是差不多的。
基于opencv的⾏⼈检测(⽀持图⽚视频)基于⽅向梯度直⽅图(HOG)/线性⽀持向量机(SVM)算法的⾏⼈检测⽅法中存在检测速度慢的问题,如下图所⽰,对⼀张400*490像素的图⽚进⾏检测要接近800毫秒,所以hog+svm的⽅法放在视频中进⾏⾏⼈检测时,每秒只能检测1帧图⽚,1帧/s根本不能达到视频播放的流畅性。
本⽂采⽤先从视频每帧的图像中提取出物体的轮廓(也可以对前后两针图⽚做差,只对有变化的部分进⾏检测,其⽬的⼀样,都是减少运算的⾯积),再对每个轮廓进⾏HOG+SVM检测,判断是否为⾏⼈。
可以⼤⼤的缩减HOG+SVM的⾯积,经实测,检测速度可以达到10帧/S,可以勉强达到视频流畅的要求。
轮廓的提取⽤的是cv::findContours的API,感兴趣的可以⾃⼰去查看相关资料⾸先介绍下⽅向梯度直⽅图。
在图像或者视频帧中,边缘⽅向密度分布可以很好地描述局部⽬标的形状和表象,也就是说通过 HOG特征,可以有效地将⼈体和复杂背景区分出来。
对于⾏⼈检测中 HOG 特征提取的具体实现⽅法是: 将视频中的每⼀帧通过滑动窗⼝切割成很⼩的区域( Cell) ,通过计算每个区域⾯的⽅向梯度特征,得到每个区域的⽅向特征直⽅图,⼩区域再组成更⼤的区域,通过将区域的⽅向梯度特征组合起来并在块单元中进⾏归⼀化处理,就形成了⼀个 Block 内 HOG 描述⼦,遍历搜索所有的⽅向特征从⽽最终构成⼀个帧的 HOG 描述特征向量。
算法的过程[3]分为:①将⼀个视频的每⼀帧进⾏灰度化处理。
把视频的每⼀帧彩⾊空间变成灰度空间,因为 HOG 中不需要彩⾊信息的帮助。
②对输⼊的视频的每⼀帧进⾏颜⾊空间的归⼀化。
由于视频中⼈信息的复杂性,背影的灰暗程度以及光照的影响都对检测器的鲁棒性有⼀定的影响,归⼀化可以很⼤程度上降低这些的影响。
这⾥使⽤gamma 校正: 对像素值求其平⽅根( 降低数值⼤⼩)。
③计算像素梯度。
这是 HOG 特征检测中最重要的⼀个环节,通过像素的梯度⽅向直⽅图来描述像素的特征。
文章标题:探讨OpenCV中HOG特征向量个数的计算方法概述HOG(Histogram of Oriented Gradients,梯度方向直方图)是一种用于目标检测的特征描述子,它能够提取图像中目标的局部特征,并且对光照变化具有较好的鲁棒性。
在OpenCV中,HOG特征向量的计算对于目标检测和行人检测等任务非常重要。
本文将从简单到复杂,由浅入深地探讨OpenCV中关于HOG特征向量个数的计算方法,帮助读者更好地理解这一重要概念。
一、HOG特征向量简介HOG特征是一种描述图像局部梯度方向的特征,它将图像分成若干个小的局部区域,并计算每个区域内梯度方向的直方图。
通过计算梯度方向直方图可以描述目标的轮廓信息,从而实现目标的检测。
在OpenCV中,HOG特征向量的维度由参数决定,而这个参数即是我们所关心的HOG特征向量个数的计算方法。
二、HOG特征向量个数的计算方法在OpenCV中,HOG特征向量的个数可以通过如下公式进行计算:[公式1]。
其中,cellSize代表每个小单元的大小,blockSize代表每个块的大小,blockStride代表块的步长,winSize代表窗口的大小,nbins代表梯度方向的直方图数量。
通过调节这些参数,可以灵活地控制HOG特征向量的个数,进而影响目标检测的性能。
在实际应用中,我们可以根据具体的任务和图像特点来调节HOG特征向量的个数。
较大的特征向量个数可以提高目标检测的精度,但也会增加计算量和内存消耗;而较小的特征向量个数则可以降低计算量和内存消耗,但可能会降低检测的精度。
合理地计算HOG特征向量的个数对于实际应用非常重要。
三、HOG特征向量个数的影响HOG特征向量的个数对目标检测性能有着重要的影响。
较大的特征向量个数可以提高目标检测的精度,尤其是对于小尺寸目标的检测具有较好的效果;而较小的特征向量个数则可能会导致目标检测的误判和漏判。
在实际应用中,我们需要根据具体的场景和目标特点来调节HOG特征向量的个数,以达到最佳的检测效果。
1、HOG特征:方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子。
它通过计算和统计图像局部区域的梯度方向直方图来构成特征。
Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功。
需要提醒的是,HOG+SVM进行行人检测的方法是法国研究人员Dalal 在2005的CVPR上提出的,而如今虽然有很多行人检测算法不断提出,但基本都是以HOG+SVM的思路为主。
(1)主要思想:在一副图像中,局部目标的表象和形状(appearance and shape)能够被梯度或边缘的方向密度分布很好地描述。
(本质:梯度的统计信息,而梯度主要存在于边缘的地方)。
(2)具体的实现方法是:首先将图像分成小的连通区域,我们把它叫细胞单元。
然后采集细胞单元中各像素点的梯度的或边缘的方向直方图。
最后把这些直方图组合起来就可以构成特征描述器。
(3)提高性能:把这些局部直方图在图像的更大的范围内(我们把它叫区间或block)进行对比度归一化(contrast-normalized),所采用的方法是:先计算各直方图在这个区间(block)中的密度,然后根据这个密度对区间中的各个细胞单元做归一化。
通过这个归一化后,能对光照变化和阴影获得更好的效果。
(4)优点:与其他的特征描述方法相比,HOG有很多优点。
首先,由于HOG是在图像的局部方格单元上操作,所以它对图像几何的和光学的形变都能保持很好的不变性,这两种形变只会出现在更大的空间领域上。
其次,在粗的空域抽样、精细的方向抽样以及较强的局部光学归一化等条件下,只要行人大体上能够保持直立的姿势,可以容许行人有一些细微的肢体动作,这些细微的动作可以被忽略而不影响检测效果。
因此HOG特征是特别适合于做图像中的人体检测的。
2、HOG特征提取算法的实现过程:大概过程:HOG特征提取方法就是将一个image(你要检测的目标或者扫描窗口):1)灰度化(将图像看做一个x,y,z(灰度)的三维图像);2)采用Gamma校正法对输入图像进行颜色空间的标准化(归一化);目的是调节图像的对比度,降低图像局部的阴影和光照变化所造成的影响,同时可以抑制噪音的干扰;3)计算图像每个像素的梯度(包括大小和方向);主要是为了捕获轮廓信息,同时进一步弱化光照的干扰。
2021.06科学技术创新基于H O G+SV M 实现行人检测任小康陈鸿享(西京学院,陕西西安710123)1概述方向梯度直方图(H i s t ogr am of O r i ent ed G r adi ent ,H O G )是用于计算机视觉识别和处理过程中对物体形状、轮廓进行检测的特征描述子。
通过计算并统计数字图像中被识别物体边缘的梯度方向直方图来构成特征描述子。
2005年在I EEE 国际计算机视觉与模式识别会议(I EEE Conf er ence on Com put er V i s i on and Pat t er n R ecogni t i on ,CV PR )[1]上,来自法国的研究人员N avneet D al al 和Bi l l Tr i ggs 提出利用H O G 对图像边缘特征进行提取,并利用支持向量机(Suppor t V ect or M achi ne ,SV M )作为二分类器训练此模型,该模型经过大量对测试样本测试后发现,H O G 与SV M 相结合的方法是速度和效果综合平衡性能较好的一种行人检测(Pedes t r i an D et ect i on)方法。
H O G +SV M 模型广泛应用于计算机视觉,尤其在行人检测领域获得了极大的成功。
行人检测技术可与行人跟踪、行人重识别等技术结合,应用于人工智能系统、车辆辅助驾驶系统、智能机器人、智能视频监控、人体行为分析、智能交通等领域,是当前的热门研究方向之一。
2H O G (梯度方向直方图)原理一幅数字图像,其梯度主要在与被检测图像的轮廓处,即目标区域的边缘部分可以很好地用方向密度分布进行描述。
2.1H O G 实现方法通过提取关键信息并丢弃冗余信息来简化图像,通常对于H O G 特征描述子,输入图像的大小为64×128×3,输出特征向量的长度为3780。
为了解决光照变化和阴影对结果的影响,将这些在细胞单元中获取到的局部直方图在图像的更大的范围,即区间(bl ock )进行对比度归一化[2](Cont r as t nor m al i z at i on )。
HOG(Histogram of Oriented Gradient)特征在对象检测与模式匹配中是一种常见的特征提取算法,是基于本地像素块进行特征直方图提取的一种算法,对象局部的变形与光照影响有很好的稳定性,最初是用HOG特征来来识别人像,通过HOG特征提取+SVM训练,可以得到很好的效果,OpenCV已经有了。
HOG特征提取的大致流程如下:
详细步骤
第一步:灰度化
对HOG特征提取来说第一步是对输入的彩色图像转换为灰度图像,图像灰度化的方法有很多,不同灰度化方法之间有一些微小的差异,从彩色到灰度的图像转换可以表示如下:
第二步:计算图像梯度
计算图像的X方向梯度dx与Y方向梯度dy,根据梯度计算mag与角度,计算梯度时候可以先高斯模糊一下(可选步骤),然后使用sobel或者其它一阶导数算子计算梯度值dx、dy、mag、angle:
第三步:Cell分割与Block
对于图像来说,分成8x8像素块,每个块称为一个Cell,每个2x2大小的
Cell称为一个Block,每个Cell根据角度与权重建立直方图,每20度为一
个BIN,每个Cell得到9个值、每个Block得到36个值(4x9), 图像如下:
每个Block为单位进行L2数据归一化,作用是抵消光照/迁移影响,L2的归一化的公式如下:
第四步:生成描述子
对于窗口64x128范围大小的像素块,可以得到8x16个Cell,使用Block
在窗口移动,得到输出的向量总数为7x15x36=3780特征向量,每次Block
移动步长是八个像素单位,一个Cell大小。
使用HOG特征数据
HOG特征本身是不支持旋转不变性与多尺度检测的,但是通过构建高斯金字塔实现多尺度的开窗检测就会得到不同分辨率的多尺度检测支持。
OpenCV中HOG多尺度对象检测API如下:
virtual void cv::HOGDescriptor::detectMultiScale(
InputArray img,
std::vector< Rect > & foundLocations,
double hitThreshold = 0,
Size winStride = Size(),
Size padding = Size(),
double scale = 1.05,
double finalThreshold = 2.0,
bool useMeanshiftGrouping = false
)
Img-表示输入图像
foundLocations-表示发现对象矩形框
hitThreshold-表示SVM距离度量,默认0表示,表示特征与SVM分类超平面之间
winStride-表示窗口步长
padding-表示填充
scale-表示尺度空间
finalThreshold-最终阈值,默认为2.0
useMeanshiftGrouping-不建议使用,速度太慢拉
使用OpenCV预训练SVM行人HOG特征分类器实现多尺度行人检测的代码如下:
import cv2 as cv
if __name__ == '__main__':
src = cv.imread("D:/images/pedestrian.png")
cv.imshow("input", src)
hog = cv.HOGDescriptor()
hog.setSVMDetector(cv.HOGDescriptor_getDefaultPeopleDetector()) # Detect people in the image
(rects, weights) = hog.detectMultiScale(src,
winStride=(4, 4),
padding=(8, 8),
scale=1.25,
useMeanshiftGrouping=False)
for (x, y, w, h) in rects:
cv.rectangle(src, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv.imshow("hog-detector", src)
cv.waitKey(0)
cv.destroyAllWindows()
原图显示如下:
运行显示如下:。