【机器学习】LBP+SVM实现特征检测

初学机器学习,参考HOG SVM 车辆检测(https://www.cnblogs.com/louyihang-loves-baiyan/p/4658478.html)、LBP特征原理(https://blog.csdn.net/q1007729991/article/details/52995734)及LBP特征的实现及LBP+SVM分类 (https://blog.csdn.net/qianqing13579/article/details/49406563)的一些理论知识内容,实现基于LBP特征加上其他约束特征,结合SVM模型训练正负样本,实现二分类、对感兴趣特征的检测。

#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace cv;
using namespace std;

#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;
	}
};


//计算输入图片的最大灰度差、平均灰度、平均梯度
int calAverageGary(const Mat &inImg, int &maxGaryDiff, int &averageGrad_xy)
{
	float averageGary;
	int garySum = 0;
	int i, j;

	//求平均灰度值
	for (i=0; i(j, i);
		}
	}
	averageGary = (int)(garySum*1.0f/(inImg.rows*inImg.cols));

	//求滑窗内的最大灰度差值
	double minGary, maxGary; 
	minMaxLoc(inImg, &minGary, &maxGary, NULL, NULL);
	maxGaryDiff = (int)(maxGary-minGary);

	//求滑窗内的平均梯度值
	Mat grad_x, grad_y, abs_grad_x, abs_grad_y, grad_xy; 
	Sobel( inImg, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT );  	//求X方向梯度 
	convertScaleAbs( grad_x, abs_grad_x );  
	Sobel( inImg, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT );  	//求Y方向梯度  
	convertScaleAbs( grad_y, abs_grad_y );  
	addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad_xy);  	       //合并梯度(近似)  
	//cout<<"gary_xy"<(j, i);
		}
	}
	averageGrad_xy = (int)(grad_xy_sum*1.0f/(inImg.rows*inImg.cols));
	return averageGary;
}


// 计算等价模式LBP特征图
static void ComputeLBPImage_Uniform(const Mat &srcImage, Mat &LBPImage)
{
	// 参数检查,内存分配
	CV_Assert(srcImage.depth() == CV_8U&&srcImage.channels() == 1);
	LBPImage.create(srcImage.size(), srcImage.type());

	// 计算LBP图
	Mat extendedImage;
	copyMakeBorder(srcImage, extendedImage, 1, 1, 1, 1, BORDER_DEFAULT);

	// LUT(256种每一种模式对应的等价模式)
	static const int table[256] = { 1, 2, 3, 4, 5, 0, 6, 7, 8, 0, 0, 0, 9, 0, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 14, 0, 15, 16, 17, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 20, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25,
		0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 27, 0, 28, 29, 30, 31, 0, 32, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0
		, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 36, 37, 38, 0, 39, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42
		, 43, 44, 0, 45, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 47, 48, 49, 0, 50, 0, 0, 0, 51, 52, 53, 0, 54, 55, 56, 57, 58 };

	// 计算LBP
	int heightOfExtendedImage = extendedImage.rows;
	int widthOfExtendedImage = extendedImage.cols;
	int widthOfLBP=LBPImage.cols;
	uchar *rowOfExtendedImage = extendedImage.data+widthOfExtendedImage+1;
	uchar *rowOfLBPImage = LBPImage.data;

	int pixelDiff = 5;

	for (int y = 1; y <= heightOfExtendedImage - 2; ++y,rowOfExtendedImage += widthOfExtendedImage, rowOfLBPImage += widthOfLBP)
	{
		// 列
		uchar *colOfExtendedImage = rowOfExtendedImage;
		uchar *colOfLBPImage = rowOfLBPImage;
		for (int x = 1; x <= widthOfExtendedImage - 2; ++x, ++colOfExtendedImage, ++colOfLBPImage)
		{
			// 计算LBP值
			int LBPValue = 0;
			if (colOfExtendedImage[0 - widthOfExtendedImage - 1] >= colOfExtendedImage[0]+pixelDiff)
				LBPValue += 128;
			if (colOfExtendedImage[0 - widthOfExtendedImage] >= colOfExtendedImage[0]+pixelDiff)
				LBPValue += 64;
			if (colOfExtendedImage[0 - widthOfExtendedImage + 1] >= colOfExtendedImage[0]+pixelDiff)
				LBPValue += 32;
			if (colOfExtendedImage[0 + 1] >= colOfExtendedImage[0]+pixelDiff)
				LBPValue += 16;
			if (colOfExtendedImage[0 + widthOfExtendedImage + 1] >= colOfExtendedImage[0]+pixelDiff)
				LBPValue += 8;
			if (colOfExtendedImage[0 + widthOfExtendedImage] >= colOfExtendedImage[0]+pixelDiff)
				LBPValue += 4;
			if (colOfExtendedImage[0 + widthOfExtendedImage - 1] >= colOfExtendedImage[0]+pixelDiff)
				LBPValue += 2;
			if (colOfExtendedImage[0 - 1] >= colOfExtendedImage[0]+pixelDiff)
				LBPValue += 1;

			colOfLBPImage[0] = table[LBPValue];
		}
	}
}

//计算归一化的LBP特征矩阵
static void ComputeLBPFeatureVector_Uniform(const Mat &srcImage, Size cellSize, Mat &featureVector)
{
	// 参数检查,内存分配
	CV_Assert(srcImage.depth() == CV_8U&&srcImage.channels() == 1);

	Mat LBPImage;
	ComputeLBPImage_Uniform(srcImage, LBPImage);

	//cout<<"LBPImage_uniform:"<(0,i) = (uchar)(LBPImage.at(0,i) * 255.0f);
	}
	//cout<<"LBPImage_255"< posSamples;
	vector negSamples;
	vector testSamples;
	int posSampleNum;
	int negSampleNum;
	int testSampleNum;
	double rho;

#ifdef TRAIN   //此开关开启,使用正负样本进行训练
	ifstream fInPos("..\\Inputs\\PositiveSample.txt");  //读取正样本
	ifstream fInNeg("..\\Inputs\\NegtiveSample.txt");   //读取负样本

	while (fInPos) //正样本读入imgPathList中
	{
		if(getline(fInPos, buffer))
			posSamples.push_back(buffer);
	}
	posSampleNum = posSamples.size();
	fInPos.close();

	while(fInNeg) //读取负样本
	{
		if (getline(fInNeg, buffer))
			negSamples.push_back(buffer);
	}
	negSampleNum = negSamples.size();
	fInNeg.close();

	Mat sampleFeatureMat; //样本特征向量矩阵
	Mat sampleLabelMat;   //样本标签

	//1、处理正样本
	for(int i = 0 ; i < posSampleNum; i++) 
	{
		Mat inputImg = imread(posSamples[i]);
		GaussianBlur(inputImg, inputImg, Size(3,3), 0);
		cout<<"processing "<1)	cvtColor(trainImg, trainImg, CV_BGR2GRAY);

		Mat dstImg(trainImg.rows, trainImg.cols, CV_8UC1, Scalar(0));
		vector descriptor;

		//等价模式LBP特征计算
		Mat sigleFeatureMat;
		calExtendLBPFeature(trainImg, Size(3, 3), sigleFeatureMat);

		descriptorDim = sigleFeatureMat.cols;

		if(i == 0)//首次特殊处理根据检测到的维数确定特征矩阵的尺寸
		{
			sampleFeatureMat = Mat::zeros(posSampleNum + negSampleNum, descriptorDim, CV_32FC1);
			sampleLabelMat = Mat::zeros(posSampleNum + negSampleNum, 1, CV_32SC1);
		}

		sigleFeatureMat.row(0).copyTo(sampleFeatureMat.row(i));   //把sigleFeatureMat的第一列赋给sampleFeatureMat的第i列
		sampleLabelMat.at(i, 0) = 1;
	}
	cout<<"extract posSampleFeature done"<1)	cvtColor(trainImg, trainImg, CV_BGR2GRAY);

		Mat dstImg(trainImg.rows, trainImg.cols, CV_8UC1, Scalar(0));
		Mat sigleFeatureMat;  //单行矩阵

		//12×30负样本,等价模式LBP特征计算(增加3维)
		calExtendLBPFeature(trainImg, Size(3, 3), sigleFeatureMat);

		sigleFeatureMat.row(0).copyTo(sampleFeatureMat.row(posSampleNum + i));   //把sigleFeatureMat赋给sampleFeatureMat的第i列
		sampleLabelMat.at(posSampleNum + i, 0) = 0;                         //标签保存样本被划分的类型
	}
	cout<<"extract negSampleFeature done"<(i, j)<<" ";
		}
		foutFeature<<"\n";
	}
	foutFeature.close();
	cout<<"output posSample and negSample Feature done"<(i,j) = pSupportVectorData[j];
		}
	}

	double *pAlphaData = SVM.get_alpha_data();
	for (int i = 0; i < supportVectorNum; i++)   //复制函数中的alpha 记住决策公式Y= wx+b
	{
		alphaMat.at(0, i) = pAlphaData[i];
	}

	resultMat = -1 * alphaMat * supportVectorMat; //alphaMat就是权重向量

	cout<<"描述子维数 "< myDetector;
	for (int i = 0 ;i < descriptorDim; i++)
	{
		myDetector.push_back(resultMat.at(0, i));
	}

	rho = SVM.get_rho_data();
	myDetector.push_back(rho);
	cout<<"检测子维数 "<1)  cvtColor(testImg, testImg, CV_BGR2GRAY);

		imshow("原图", testImg);
		GaussianBlur(testImg, testImg, Size(3,3), 0);   //高斯滤波
		//imshow("高斯滤波后", testImg);
		//equalizeHist(testImg, testImg);  //直方图均衡
		//imshow("直方图均衡后", testImg);

		Mat copyImg = testImg.clone();
		if(copyImg.channels()<3)  cvtColor(copyImg, copyImg, CV_GRAY2BGR);

		Mat testImgNorm; 
		resize(testImg, testImgNorm, Size(300, 720));

		vector found, foundFiltered;

		//设计滑窗遍历测试样本:计算每个滑窗内的LBP特征,给SVM预测,把输出为1的框画出来。
		int m, n;
		Mat slideWinImg(30, 12, CV_8UC1, Scalar(0));
		Mat dstImg(30, 12, CV_8UC1, Scalar(0));   //LBP图,可不输出
		Mat lideWinImgFeatureMat;
		Mat sigleFeatureMat = Mat::zeros(1, descriptorDim, CV_32FC1);  
		vector descriptor;

		for(n=0; n<=testImgNorm.rows-30; n+=30) 
		{
			for(m=0; m<=testImgNorm.cols-12; m+=4)
			{
				slideWinImg = testImgNorm(Rect(m, n, 12, 30));
				if (slideWinImg.channels()>1)	cvtColor(slideWinImg, slideWinImg, CV_BGR2GRAY);
				
				Mat extendLBPFeature;
				calExtendLBPFeature(slideWinImg, Size(3, 3), extendLBPFeature);

				//使用训练的SVM模型预测测试样本
				int predictResult = SVM.predict(extendLBPFeature);
				//cout<<"SVM训练模型预测结果:"<

你可能感兴趣的:(机器学习,OpenCv)