紧接上一篇未完成的工作,实现LBPH!!!
介绍其实上篇博客已经介绍了一些LBP的实现:
https://blog.csdn.net/zqx951102/article/details/100713614
LBPH的概念这篇博客有介绍,
https://blog.csdn.net/guo1988kui/article/details/79976202
LBPH,Local Binary Patterns Histograms,即LBP特征的统计直方图,LBPH将LBP特征与图像的空间信息结合在一起。这种表示方法由Ahonen等人在论文[3]中提出,他们将LBP特征图像分成m个局部块,并提取每个局部块的直方图,然后将这些直方图依次连接在一起形成LBP特征的统计直方图,即LBPH。
一幅图像具体的计算LBPH的过程(以Opencv中的人脸识别为例):
这篇博客也介绍了lbph不过代码不全,计算直方图没写!!
https://blog.csdn.net/heli200482128/article/details/79204008
他就是用了elbp。然后在用lbph计算得出直方图矩阵。
本人综合了一下:然后代码贴出:
#include "opencv2/core/core.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/highgui/highgui.hpp"
#include
#include
#include
#include
using namespace cv;
using namespace std;
//计算一个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(minValue),static_cast(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)
{
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(radius * cos(2.0*CV_PI*n/static_cast(neighbors)));
float y = static_cast(-radius * sin(2.0*CV_PI*n/static_cast(neighbors)));
// 上取整和下取整的值
int fx = static_cast(floor(x));
int fy = static_cast(floor(y));
int cx = static_cast(ceil(x));
int cy = static_cast(ceil(y));
// 小数部分
float ty = y - fy;
float tx = x - fx;
// 设置插值权重
float w1 = (1 - tx) * (1 - ty);
float w2 = tx * (1 - ty);
float w3 = (1 - tx) * ty;
float w4 = tx * ty;
// 循环处理图像数据
for(int i=radius; i < src.rows-radius;i++)
{
for(int j=radius;j < src.cols-radius;j++)
{
// 计算插值
float t = static_cast(w1*src.at(i+fy,j+fx) + w2*src.at(i+fy,j+cx) + w3*src.at(i+cy,j+fx) + w4*src.at(i+cy,j+cx));
// 进行编码
dst.at(i-radius,j-radius) += ((t > src.at(i,j)) || (std::abs(t-src.at(i,j)) < std::numeric_limits::epsilon())) << n;
}
}
}
}
int main()
{
//显示原图
Mat img = imread("F://ZQX//32x256.bmp", 0);
namedWindow("image");
imshow("image", img);
int radius, neighbors;
//假设
radius = 1; //半径越小 图像越清晰 精细
neighbors =8; //领域数目越小,图像亮度越低,合理,4太小了比较黑 设置8比较合理
Mat dst1 = Mat(img.rows-2*radius, img.cols-2*radius,CV_8UC1, Scalar(0)); //2
elbp(img,dst1,1,8);
namedWindow("圆形LBP");
imshow("圆形LBP", dst1);
//lbph是先生成lbp然后再统计局部的直方图,具体步骤https://blog.csdn.net/guo1988kui/article/details/79976202,第三部分LBPH,看一下步骤就明白了!!
Mat m=getLBPH(dst1,2,8,8);
cout<
图像使用的是一张32*256虹膜图像
效果图:
直方图矩阵的数值和圆形LBP处理的结果,上一篇处理的结果都没贴,就贴了代码。
最近看了一篇基于python的博客代码:
https://blog.csdn.net/lk3030/article/details/84034963
链接在这 都能实现 挺不错的