LBP人脸识别

LBP(local binary pattern)是一种用来描述图像局部纹理特征的算子。原始的LBP于1994年提出,它反映内容是每个像素与周围像素的关系。后被不断的改进和优化,分别提出了LBP旋转不变模式、LBP均匀模式等。

一:原始的LBP

   给出一个简单的案例计算LBP:如下图,周围8个像素点比中间点像素值大(或者相等)的记为1,小的记为0,这样就得到二值图,然后按顺时针方向得到二进制串10001111

这样中间点的像素值就用241来代替。注意这里的计算LBP的顺序并没有硬性要求,只是一个量化公式,在同一处理中保持相同的顺序即可。

下面给出LBP的计算公式:



二、旋转不变的LBP模式<LBPROT>

原始的LBP不具有旋转不变性,这样我们就提出了旋转不变的LBP模式。旋转不变的LBP计算公式如下:


这样计算出来的LBP共有36种,分布情况如下面两幅图:


其中白点代表1,黑点代表0。


三:均匀LBP模式

旋转LBP模式同样存在缺陷,大量的实验证明LBP模式的36种情况在一幅图像中分布出现的频率差异较大,得到的效果并不是很好。因此人们提出了均匀LBP模式即uniform LBP。

均匀模式就是一个二进制序列从01或是从10的变过不超过2次(这个二进制序列首尾相连)。比如:10100000的变化次数为3次所以不是一个uniform pattern。所有的8位二进制数中共有58(变化次数为0的有2种,变化次数为1的有0种,变化次数为2的有56种)个uniform pattern.为什么要提出这么个uniform LBP呢,因为研究者发现他们计算出来的大部分值都在这58种之中可达到90%以上,所以他们把值分为59类,58个uniform pattern为一类,其它的所有值为第59类。59=(2+0+56)+1,这样直方图从原来的256维变成59维。起到了降维的作用

 计算公式:


应用:

在模式识别如判断两幅图片的相似性时,我们可以统计这两幅图像的LBP特征的直方图。这样,在原始的LBP模式中,统计的直方图可以当做一个256维的向量。直接这样判断,很多时候会因为“位置没有对准”而产生很大的误差。大量研究表明,此时我们可以将一幅图片划分为若干的子区域,对每个子区域内的每个像素点都提取LBP特征,然后,在每个子区域内建立LBP特征的统计直方图。如此一来,每个子区域,就可以用一个统计直方图来进行描述;整个图片就由若干个统计直方图组成。比如将一幅图像划分为10*10个区域,这样得到向量的维数就是256*10*10。而针对uniform LBP,此时向量的维数就是59*10*10, 从而达到降维的目的。

目前,LBP局部纹理提取算子,已经成功应用在指纹识别、字符识别、人脸识别、车牌识别等领域。


Code:

原始的LBP:

  1. void LBP(Mat &image, Mat &result)  
  2. {  
  3.     for(int y = 1; y < image.rows-1; y ++)  
  4.     {  
  5.         for(int x = 1; x < image.cols-1; x++)  
  6.         {  
  7.             uchar neighbor[8] = {0};  
  8.             neighbor[0] = image.at<uchar>(y-1, x-1);  
  9.             neighbor[1] = image.at<uchar>(y-1, x);  
  10.             neighbor[2] = image.at<uchar>(y-1, x+1);  
  11.             neighbor[3] = image.at<uchar>(y, x+1);  
  12.             neighbor[4] = image.at<uchar>(y+1, x+1);  
  13.             neighbor[5] = image.at<uchar>(y+1, x);  
  14.             neighbor[6] = image.at<uchar>(y+1, x-1);  
  15.             neighbor[7] = image.at<uchar>(y, x-1);  
  16.             uchar center = image.at<uchar>(y, x);  
  17.             uchar temp = 0;  
  18.             for(int k = 0; k < 8; k++)  
  19.             {  
  20.                 temp += (neighbor[k] >= center)* (1<<k);  // 计算LBP的值  
  21.             }  
  22.             result.at<uchar>(y,x) = temp;   
  23.         }  
  24.     }  
  25. }  
  26.   
  27. int main()  
  28. {  
  29.     Mat image = imread("F:\\lena.png", 0);  
  30.     if(!image.data)  
  31.     {  
  32.         cout << "Fail to load image" << endl;  
  33.         return 0;  
  34.     }  
  35.     Mat result;  
  36.     result.create(Size(image.cols, image.rows), image.type());  
  37.     LBP(image, result);  
  38.     namedWindow("result", 0);  
  39.     imshow("result", result);  
  40.     waitKey(0);  
  41.     return 0;  
  42. }  
uniform LBP:

  1. // 计算跳变次数  
  2. int getHopCount(int i)  
  3. {  
  4.     int a[8] = {0};  
  5.     int cnt = 0;  
  6.     int k = 7;  
  7.     while(i)  
  8.     {  
  9.         a[k] = i&1;  
  10.         i = i >> 1;  
  11.         --k;  
  12.     }  
  13.     for(k = 0; k < 7; k++)  
  14.     {  
  15.         if(a[k] != a[k+1])  
  16.         {  
  17.             ++cnt;  
  18.         }  
  19.     }  
  20.     if(a[0] != a[7])  
  21.     {  
  22.         ++cnt;  
  23.     }  
  24.     return cnt;  
  25. }  
  26.   
  27. // 降维数组 由256->59  
  28. void lbp59table(uchar *table)  
  29. {  
  30.     memset(table, 0, 256);  
  31.     uchar temp = 1;  
  32.     for(int i = 0; i < 256; i++)  
  33.     {  
  34.         if(getHopCount(i) <= 2)    // 跳变次数<=2 的为非0值  
  35.         {  
  36.             table[i] = temp;  
  37.             temp ++;  
  38.         }  
  39.     }  
  40. }  
  41.   
  42. void uniformLBP(Mat &image, Mat &result, uchar *table)  
  43. {  
  44.     for(int y = 1; y < image.rows-1; y ++)  
  45.     {  
  46.         for(int x = 1; x < image.cols-1; x++)  
  47.         {  
  48.             uchar neighbor[8] = {0};  
  49.             neighbor[0] = image.at<uchar>(y-1, x-1);  
  50.             neighbor[1] = image.at<uchar>(y-1, x);  
  51.             neighbor[2] = image.at<uchar>(y-1, x+1);  
  52.             neighbor[3] = image.at<uchar>(y, x+1);  
  53.             neighbor[4] = image.at<uchar>(y+1, x+1);  
  54.             neighbor[5] = image.at<uchar>(y+1, x);  
  55.             neighbor[6] = image.at<uchar>(y+1, x-1);  
  56.             neighbor[7] = image.at<uchar>(y, x-1);  
  57.             uchar center = image.at<uchar>(y, x);  
  58.             uchar temp = 0;  
  59.             for(int k = 0; k < 8; k++)  
  60.             {  
  61.                 temp += (neighbor[k] >= center)* (1<<k);  // 计算LBP的值  
  62.             }  
  63.             result.at<uchar>(y,x) = table[temp];   //  降为59维空间  
  64.         }  
  65.     }  
  66. }  
  67.   
  68. int main()  
  69. {  
  70.     uchar table[256];  
  71.     lbp59table(table);  
  72.     Mat image = imread("F:\\lena.png", 0);  
  73.     if(!image.data)  
  74.     {  
  75.         cout << "Fail to load image" << endl;  
  76.         return 0;  
  77.     }  
  78.     Mat result;  
  79.     result.create(Size(image.cols, image.rows), image.type());  
  80.     uniformLBP(image, result, table);  
  81.   
  82.     namedWindow("uniformResult", 0);  
  83.     imshow("uniformResult", result);  
  84.   
  85.     waitKey(0);  
  86.     return 0;  
  87.       
  88. }  

Result:

原图:

原始LBP:


uniform LBP:


参考文献:文章:Multiresolution Gray-Scale and Rotation Invariant Texture Classificationwith Local Binary Patterns 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LBP(Local Binary Patterns)是一种基于局部纹理特征的人脸识别方法。下面是使用MATLAB实现LBP人脸识别的基本步骤: 1. 读入人脸图像集,将其转换为灰度图像。 ``` % 读入人脸图像集 imgSet = imageSet('face_database', 'recursive'); % 将图像集转换为灰度图像 for i = 1:imgSet.Count img = read(imgSet, i); img = rgb2gray(img); imgSet.ImageLocation{i} = img; end ``` 2. 对每个图像进行LBP特征提取,并将其存储在特征矩阵中。 ``` % 定义LBP特征提取函数 lbp = @(x)reshape(dec2bin(... x(1,1)*0+x(2,1)*1+x(3,1)*2+x(3,2)*4+x(3,3)*8+x(2,3)*16+x(1,3)*32+x(1,2)*64,8)',1,[]); % 提取每个图像的LBP特征 featureMatrix = zeros(imgSet.Count, 256); for i = 1:imgSet.Count img = read(imgSet, i); imgLBP = vl_lbp(im2single(img), 8); featureMatrix(i,:) = double(reshape(imgLBP,1,[])); end ``` 3. 使用PCA降维,将特征矩阵降维到低维空间。 ``` % 对特征矩阵进行PCA降维 [coeff,score,latent] = pca(featureMatrix); lowDim = score(:,1:50); ``` 4. 对测试图像进行LBP特征提取,并将其投影到低维空间中。 ``` % 读入测试图像 testImg = imread('test_face.png'); testImg = rgb2gray(testImg); % 提取测试图像的LBP特征 testImgLBP = vl_lbp(im2single(testImg), 8); testFeature = double(reshape(testImgLBP,1,[])); % 将测试图像特征投影到低维空间中 testLowDim = (testFeature - mean(featureMatrix))*coeff(:,1:50); ``` 5. 计算测试图像与每个训练图像之间的欧氏距离,找到与测试图像距离最近的训练图像。 ``` % 计算测试图像与每个训练图像之间的欧氏距离 distances = zeros(imgSet.Count, 1); for i = 1:imgSet.Count distances(i) = norm(lowDim(i,:) - testLowDim); end % 找到距离最近的训练图像 [minDist, idx] = min(distances); ``` 6. 输出识别结果。 ``` % 输出识别结果 if minDist < 100 fprintf('该测试图像与第%d个训练图像匹配\n', idx); else fprintf('无法识别该测试图像\n'); end ``` 完整代码如下: ``` % 读入人脸图像集 imgSet = imageSet('face_database', 'recursive'); % 将图像集转换为灰度图像 for i = 1:imgSet.Count img = read(imgSet, i); img = rgb2gray(img); imgSet.ImageLocation{i} = img; end % 定义LBP特征提取函数 lbp = @(x)reshape(dec2bin(... x(1,1)*0+x(2,1)*1+x(3,1)*2+x(3,2)*4+x(3,3)*8+x(2,3)*16+x(1,3)*32+x(1,2)*64,8)',1,[]); % 提取每个图像的LBP特征 featureMatrix = zeros(imgSet.Count, 256); for i = 1:imgSet.Count img = read(imgSet, i); imgLBP = vl_lbp(im2single(img), 8); featureMatrix(i,:) = double(reshape(imgLBP,1,[])); end % 对特征矩阵进行PCA降维 [coeff,score,latent] = pca(featureMatrix); lowDim = score(:,1:50); % 读入测试图像 testImg = imread('test_face.png'); testImg = rgb2gray(testImg); % 提取测试图像的LBP特征 testImgLBP = vl_lbp(im2single(testImg), 8); testFeature = double(reshape(testImgLBP,1,[])); % 将测试图像特征投影到低维空间中 testLowDim = (testFeature - mean(featureMatrix))*coeff(:,1:50); % 计算测试图像与每个训练图像之间的欧氏距离 distances = zeros(imgSet.Count, 1); for i = 1:imgSet.Count distances(i) = norm(lowDim(i,:) - testLowDim); end % 找到距离最近的训练图像 [minDist, idx] = min(distances); % 输出识别结果 if minDist < 100 fprintf('该测试图像与第%d个训练图像匹配\n', idx); else fprintf('无法识别该测试图像\n'); end ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值