• 为了保证你在浏览本网站时有着更好的体验,建议使用类似Chrome、Firefox之类的浏览器~~
    • 如果你喜欢本站的内容何不Ctrl+D收藏一下呢,与大家一起分享各种编程知识~
    • 本网站研究机器学习、计算机视觉、模式识别~当然不局限于此,生命在于折腾,何不年轻时多折腾一下

Opencv3.0HOG-SVM自定义xml检测

cv admin 4年前 (2015-11-17) 5072次浏览 0个评论 扫描二维码

方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子。它通过计算和统计图像局部区域的梯度方向直方图来构成特征。Hog 特征结合 SVM 分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功。需要提醒的是,HOG+SVM 进行行人检测的方法是法国研究人员 Dalal 在 2005 的 CVPR 上提出的,而如今虽然有很多行人检测算法不断提出,但基本都是以 HOG+SVM 的思路为主。

 

Opencv 3.0 已经取消了 Cvsvm 类了,因此之前在网上看到的许多 2.0 时代 example 都无法在 3.0 上使用。

上图是 3.0 借口类的继承关系示意图。

template <typename _Tp >
static Ptr< _Tp > load (const String &filename, const String &objname=String())
Loads algorithm from the file. More...

由于是模板类操作,在使用 svm 的 load 加载就需要如下操作:

Ptr<ml::SVM>svm = ml::SVM::load<ml::SVM>("SVM_HOG_2400PosINRIA_12000Neg_HardExample.xml");

以下为完整程序代码:

#include <iostream>
#include <fstream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/ml/ml.hpp>

using namespace std;
using namespace cv;

class MySVM : public  ml::SVM
{
public:
	//获得 SVM 的决策函数中的 alpha 数组
	double get_svm_rho()
	{
		return this->getDecisionFunction(0, svm_alpha, svm_svidx);
	}

	//获得 SVM 的决策函数中的 rho 参数,即偏移量

	vectorsvm_alpha;
	vectorsvm_svidx;
	float  svm_rho;

};



int main()
{
	namedWindow("src", 0);
	//检测窗口(64,128),块尺寸(16,16),块步长(8,8),cell 尺寸(8,8),直方图 bin 个数 9
	//HOGDescriptor hog(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);//HOG 检测器,用来计算 HOG 描述子的
	int DescriptorDim;//HOG 描述子的维数,由图片大小、检测窗口大小、块大小、细胞单元中直方图 bin 个数决定
	//Ptr svm = ml::SVM::create();
	Ptr<ml::SVM>svm = ml::SVM::load<ml::SVM>("SVM_HOG_2400PosINRIA_12000Neg_HardExample.xml");
	DescriptorDim = svm->getVarCount();//特征向量的维数,即 HOG 描述子的维数
	Mat supportVector = svm->getSupportVectors();//支持向量的个数
	int supportVectorNum = supportVector.rows;
	cout << "支持向量个数:" << supportVectorNum << endl;
	//-------------------------------------------------
	vectorsvm_alpha;
	vectorsvm_svidx;
	float  svm_rho;
	
	svm_rho=svm->getDecisionFunction(0, svm_alpha, svm_svidx);
	//-------------------------------------------------
	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 = supportVector;
	////将 alpha 向量的数据复制到 alphaMat 中
	//double * pAlphaData = svm.get_alpha_vector();//返回 SVM 的决策函数中的 alpha 向量
	for (int i = 0; i < supportVectorNum; i++)
	{
		alphaMat.at(0, i) = svm_alpha[i];
	}

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

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

	//myHOG.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
	myHOG.setSVMDetector(myDetector);
	//myHOG.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());

	/**************读入图片进行 HOG 行人检测******************/
	//Mat src = imread("00000.jpg");
	//Mat src = imread("2007_000423.jpg");


	VideoCapture vp("Capture-3202684690.avi");

	Mat frame;

	while (true)
	{
		if (!vp.read(frame))
		{
			cout << "读取视频结束" << endl;
			break;
		}
		Mat src = frame;
		vector found, found_filtered;//矩形框数组
		//cout << "进行多尺度 HOG 人体检测" << endl;
		myHOG.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);
		}


		imshow("src", src);
		waitKey(1);//注意:imshow 之后必须加 waitKey,否则无法显示图像

	}
	

	system("pause");
}

Deeplearn, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明Opencv3.0HOG-SVM 自定义 xml 检测
喜欢 (3)
admin
关于作者:
互联网行业码农一枚/业余铲屎官/数码影音爱好者/二次元

您必须 登录 才能发表评论!