LBP特征(6)LBPH

LBPH——图像的LBP特征向量

LBPH,Local Binary Patterns Histograms,即LBP特征的统计直方图,LBPH将LBP特征与图像的空间信息结合在一起。这种表示方法由Ahonen等人在论文【Ahonen, T., Hadid, A., and Pietikainen, M. Face Recognition with Local Binary Patterns. Computer Vision- ECCV 2004 (2004), 469–481】中提出,他们将LBP特征图像分成m个局部块,并提取每个局部块的直方图,然后将这些直方图依次连接在一起形成LBP特征的统计直方图,即LBPH。
 


一幅图像具体的计算LBPH的过程(以Opencv中的人脸识别为例): 
1. 计算图像的LBP特征图像,在上面已经讲过了。 
2. 将LBP特征图像进行分块,Opencv中默认将LBP特征图像分成8行8列64块区域; 
3. 计算每块区域特征图像的直方图cell_LBPH,将直方图进行归一化,直方图大小为1*numPatterns 
4. 将上面计算的每块区域特征图像的直方图按分块的空间顺序依次排列成一行,形成LBP特征向量,大小为1*(numPatterns*64) 
5. 用机器学习的方法对LBP特征向量进行训练,用来检测和识别目标 
 

举例说明LBPH的维度: 
采样点为8个,如果用的是原始的LBP或Extended LBP特征,其LBP特征值的模式为256种,则一幅图像的LBP特征向量维度为:64*256=16384维, 
而如果使用的UniformPatternLBP特征,其LBP值的模式为59种,其特征向量维度为:64*59=3776维,可以看出,使用等价模式特征,其特征向量的维度大大减少, 
这意味着使用机器学习方法进行学习的时间将大大减少,而性能上没有受到很大影响。 
Opencv的人脸识别使用的是Extended LBP。
 

//计算一个LBP特征图像块的直方图
Mat getLocalRegionLBPH(const Mat& src, int minValue, int maxValue, bool normed)
{
	//定义存储直方图的矩阵
	Mat result;
	//计算得到直方图bin的数目,直方图数组的大小
	int histSize = maxValue - minValue + 1;
	//定义直方图每一维的bin的变化范围
	float range[] = { static_cast<float>(minValue),static_cast<float>(maxValue + 1) };
	//定义直方图所有bin的变化范围
	const float* ranges = { range };
	//计算直方图,src是要计算直方图的图像,1是要计算直方图的图像数目,0是计算直方图所用的图像的通道序号,从0索引
	//Mat()是要用的掩模,result为输出的直方图,1为输出的直方图的维度,histSize直方图在每一维的变化范围
	//ranges,所有直方图的变化范围(起点和终点)
	calcHist(&src, 1, 0, Mat(), result, 1, &histSize, &ranges, true, false);
	//归一化
	if (normed)
	{
		result /= (int)src.total();
	}
	//结果表示成只有1行的矩阵
	return result.reshape(1, 1);
}
//计算LBP特征图像的直方图LBPH
Mat getLBPH(Mat src, int numPatterns, int grid_x, int grid_y, bool normed)
{
	int width = src.cols / grid_x;
	int height = src.rows / grid_y;
	//定义LBPH的行和列,grid_x*grid_y表示将图像分割成这么些块,numPatterns表示LBP值的模式种类
	Mat result = Mat::zeros(grid_x * grid_y, numPatterns, CV_32FC1);
	if (src.empty())
	{
		return result.reshape(1, 1);
	}
	int resultRowIndex = 0;
	//对图像进行分割,分割成grid_x*grid_y块,grid_x,grid_y默认为8
	for (int i = 0; i<grid_x; i++)
	{
		for (int j = 0; j<grid_y; j++)
		{
			//图像分块
			Mat src_cell = Mat(src, Range(i*height, (i + 1)*height), Range(j*width, (j + 1)*width));
			//计算直方图
			Mat hist_cell = getLocalRegionLBPH(src_cell, 0, (numPatterns - 1), true);
			//将直方图放到result中
			Mat rowResult = result.row(resultRowIndex);
			hist_cell.reshape(1, 1).convertTo(rowResult, CV_32FC1);
			resultRowIndex++;
		}
	}
	return result.reshape(1, 1);
}
 
 
int main()
{
	cv::Mat src = imread("..\\..\\image\\xx.png", 0);
	cv::Mat dst;
 
	//getOriginLBPFeature<uchar>(src, dst);
 
	//getCircularLBPFeatureOptimization<uchar>(src, dst, 1, 8);
 
	//getRotationInvariantLBPFeature<uchar>(src, dst, 1, 8);
 
	getUniformPatternLBPFeature<uchar>(src, dst, 1, 8);
 
	//getMultiScaleBlockLBPFeature(src, dst, 9);
 
	//SEMB_LBPFeature(src, dst, 9);
 
	cv::Mat result = getLBPH(dst, 59, 8, 8, true);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_30263737/article/details/90674529