一,原始LBP算法

LBP的基本思想是对图像的像素和它局部周围像素进行对比后的结果进行求和。把这个像素作为中心,对相邻像素进行阈值比较。如果中心像素的亮度大于等于他的相邻像素,把他标记为1,否则标记为0。你会用二进制数字来表示每个像素,比如11001111。因此,由于周围相邻8个像素,你最终可能获取2^8个可能组合,被称为局部二值模式,有时被称为LBP码。第一个在文献中描述的LBP算子实际使用的是3*3的邻域

一个更加正式的LBP操作可以被定义为

其中 是中心像素,亮度是 ;而 则是相邻像素的亮度。s是一个符号函数:

这种描述方法使得你可以很好的捕捉到图像中的细节。实际上,研究者们可以用它在纹理分类上得到最先进的水平。正如刚才描述的方法被提出后,固定的近邻区域对于尺度变化的编码失效。所以,使用一个变量的扩展方法,在文献[AHP04]中有描述。主意是使用可变半径的圆对近邻像素进行编码,这样可以捕捉到如下的近邻:

对一个给定的点   ,他的近邻点  可以由如下计算:

其中,R是圆的半径,而P是样本点的个数。

这个操作是对原始LBP算子的扩展,所以有时被称为扩展LBP(又称为圆形LBP)。如果一个在圆上的点不在图像坐标上,我们使用他的内插点。计算机科学有一堆聪明的插值方法,而OpenCV使用双线性插值。

二.原始LBP算法的实现

附上代码:

// LBP.cpp : 定义控制台应用程序的入口点。
///************************************************************************ OpenCV 2.4.4 测试例程* 杜健健 提供***********************************************************************/#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include  <cv.h>
#include  <highgui.h>
#include  <cxcore.h>using namespace std;
using namespace cv;//原始的LBP算法
//使用模板参数template <typename _Tp> static
void olbp_(InputArray _src, OutputArray _dst) {// get matricesMat src = _src.getMat();// allocate memory for result_dst.create(src.rows-2, src.cols-2, CV_8UC1);Mat dst = _dst.getMat();// zero the result matrixdst.setTo(0);cout<<"rows "<<src.rows<<" cols "<<src.cols<<endl;cout<<"channels "<<src.channels();getchar();// calculate patternsfor(int i=1;i<src.rows-1;i++) {cout<<endl;for(int j=1;j<src.cols-1;j++) {_Tp center = src.at<_Tp>(i,j);//cout<<"center"<<(int)center<<"  ";unsigned char code = 0;code |= (src.at<_Tp>(i-1,j-1) >= center) << 7;code |= (src.at<_Tp>(i-1,j  ) >= center) << 6;code |= (src.at<_Tp>(i-1,j+1) >= center) << 5;code |= (src.at<_Tp>(i  ,j+1) >= center) << 4;code |= (src.at<_Tp>(i+1,j+1) >= center) << 3;code |= (src.at<_Tp>(i+1,j  ) >= center) << 2;code |= (src.at<_Tp>(i+1,j-1) >= center) << 1;code |= (src.at<_Tp>(i  ,j-1) >= center) << 0;dst.at<unsigned char>(i-1,j-1) = code;//cout<<(int)code<<" ";//cout<<(int)code<<endl;}}
}//基于旧版本的opencv的LBP算法opencv1.0
void LBP (IplImage *src,IplImage *dst)
{int tmp[8]={0};CvScalar s;IplImage * temp = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U,1);uchar *data=(uchar*)src->imageData;int step=src->widthStep;cout<<"step"<<step<<endl;for (int i=1;i<src->height-1;i++)for(int j=1;j<src->width-1;j++){int sum=0;if(data[(i-1)*step+j-1]>data[i*step+j])tmp[0]=1;elsetmp[0]=0;if(data[i*step+(j-1)]>data[i*step+j])tmp[1]=1;elsetmp[1]=0;if(data[(i+1)*step+(j-1)]>data[i*step+j])tmp[2]=1;elsetmp[2]=0;if (data[(i+1)*step+j]>data[i*step+j])tmp[3]=1;elsetmp[3]=0;if (data[(i+1)*step+(j+1)]>data[i*step+j])tmp[4]=1;elsetmp[4]=0;if(data[i*step+(j+1)]>data[i*step+j])tmp[5]=1;elsetmp[5]=0;if(data[(i-1)*step+(j+1)]>data[i*step+j])tmp[6]=1;elsetmp[6]=0;if(data[(i-1)*step+j]>data[i*step+j])tmp[7]=1;elsetmp[7]=0;   //计算LBP编码s.val[0]=(tmp[0]*1+tmp[1]*2+tmp[2]*4+tmp[3]*8+tmp[4]*16+tmp[5]*32+tmp[6]*64+tmp[7]*128);cvSet2D(dst,i,j,s);写入LBP图像}
}int _tmain(int argc, _TCHAR* argv[])
{//IplImage* face = cvLoadImage("D://input//yalefaces//01//s1.bmp",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);IplImage* face = cvLoadImage("D://input//lena.jpg",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);//IplImage* lbp_face =   cvCreateImage(cvGetSize(face), IPL_DEPTH_8U,1);IplImage* Gray_face = cvCreateImage( cvSize( face->width,face->height ), face->depth, 1);//先分配图像空间cvCvtColor(face, Gray_face ,CV_BGR2GRAY);//把载入图像转换为灰度图IplImage* lbp_face =   cvCreateImage(cvGetSize(Gray_face), IPL_DEPTH_8U,1);//先分配图像空间cvNamedWindow("Gray Image",1);cvShowImage("Gray Image",Gray_face);//Mat face2 = imread("D://input//buti.jpg",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);Mat face2 = imread("D://input//yalefaces//01//s1.bmp",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);//Mat Gray_face2 = Mat::zeros(face2.size(),IPL_DEPTH_8U,1);//cvCvtColor(face2,Gray_face2,CV_BGR2RAY);Mat lbp_face2 = Mat::zeros(face2.size(),face2.type()) ;//Mat::copyTo(lbp_face,face);//显示原始的输入图像cvNamedWindow("Src Image",CV_WINDOW_AUTOSIZE);cvShowImage("Src Image",face);//imshow("Src Image",face);//计算输入图像的LBP纹理特征LBP(Gray_face,lbp_face);//olbp_<uchar>((Mat)face,(Mat)lbp_face);//有问题的调用olbp_<uchar>(face2,lbp_face2);//显示第一幅图像的LBP纹理特征图cvNamedWindow("LBP Image",CV_WINDOW_AUTOSIZE);cvShowImage("LBP Image",lbp_face);//显示第二幅图 的LBP纹理特征图-一张yaleface人脸库中的人脸LBP特征图namedWindow("LBP Image2",1);imshow("LBP Image2",lbp_face2);waitKey();//cvReleaseImage(&face);cvDestroyWindow("Src Image");return 0;}

三.示例结果,LBP纹理特征

原始图像lena.jpg

变换成灰度图后:

提取图片的LBP特征:

提取人脸图像的LBP特征;

四.注意事项

1 两个函数都只能对灰度图像就行处理,所以,在使用这两个函数时,必须先把原始图像转换成灰度图像方可

2 关于早期只显示图像1/3或者1/4区域的LBP纹理特征问题的解决方法:

这个是因为你的输入图像不是灰度图的缘故,需要把彩色图,多通道的图像转换成单通道的图像,再作为参数传入函数,才能得到完整图像的LBP纹理特征。

3 载入灰度图像的方法:

把函数cvLoadImage()函数的第二个参数,还有imread() 的第二个参数设置成:CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR

就可以了。哦也,这个可是我在网上找了好久才解决的,分享一下,欢迎大家多多指点。

五.遇到的问题

就是使用Mat结构存储彩色图像,多通道图像后,怎么把它转换成单通道的灰度图。
我网上找了好多资料,没发现有相关可以参考的函数可以直接调用。有一个提到可以使用IplImage和Mat相互转化。我想用这种方法,就是先转换再调用cvCvtColor() 进行灰度图的转化。但没有试过,不知道可不可以。
如果有同学知道怎么弄,欢迎告诉我一下,不胜感激

六.参考

opencv2.4.4中的facerec文档

http://blog.csdn.net/guoming0000/article/details/8022197

等等。

opencv学习之(三)-LBP算法的研究及其实现相关推荐

  1. LBP算法的研究及其实现

    原文:http://blog.csdn.net/dujian996099665/article/details/8886576 一,原始LBP算法 LBP的基本思想是对图像的像素和它局部周围像素进行对 ...

  2. Opencv学习笔记(三) -- 图像压缩与保存

    1.图像压缩 1.1常用图像格式 bmp Windows位图格式.该格式为不压缩格式,缺点是图像文件较大. jpg JPEG是为静态图像所建立的第一个国际数字图像压缩标准,也是至今一直在使用的.应用最 ...

  3. Opencv学习记录(三) —— 得到图像中目标物坐标的简单处理算法(望指正与补充)

    先描述一下使用场景: 我要识别一个红灯,已经把目标准确的提取出来了,二值图像中白色为目标物,现在要算出二值图中的白色像素点的坐标.因为之后需要移植到树莓派,所以需要高效的方法.             ...

  4. OpenCV学习(20) grabcut分割算法

    在OpenCV中,实现了grabcut分割算法,该算法可以方便的分割出前景图像,操作简单,而且分割的效果很好.算法的原理参见papaer:"GrabCut" - Interacti ...

  5. OpenCV学习记录 三 (傅里叶逆变换原理及实现)

    为什么要在频率域研究图像增强? 利用频率成分和图像外表之间的对应关系.滤波在频率域更为直观,它可以解释空间域滤波的某些性质.可以在频率域指定滤波器,做反变换,然后在空间域使用结果滤波器作为空间域滤波器 ...

  6. 学习笔记(三) 线性回归算法(Linear Regression)

    一.算法简介 代码下载:https://download.csdn.net/download/xdg2008/14017829 1.1 什么是回归分析 回归分析是一种预测性的建模技术,它研究的是因变量 ...

  7. OpenCV学习笔记三-Mat数据结构

    主要记录Mat数据结构的一些操作 P3 Mat 数据结构的一些操作 #include<opencv2/opencv.hpp> #include<iostream>using n ...

  8. brisk matlab,opencv学习笔记三十七:BRISK特征点检测与匹配

    简介 BRISK算法是2011年ICCV上<BRISK:Binary Robust Invariant Scalable Keypoints>文章中,提出来的一种特征提取算法,也是一种二进 ...

  9. opencv 学习第三课 画线段 圆 椭圆 矩形 多边形 插入文字 代码注释版 保证你每一行都能读懂

    import numpy as np import cv2 as cv # 创建一张大小为512×512,通道数为3的黑色的图片 img = np.zeros((512,512,3), np.uint ...

最新文章

  1. Windows与Linux之间互传文件的方法
  2. 为了上班摸鱼,我用Python开发“BOSS来了”
  3. 基于脆弱水印的图像篡改检测实现
  4. AutoMapper的介绍与使用(二)
  5. Storm精华问答 | 如何理解spout/bolt的生命周期?
  6. android webview缩放功能,在Android WebView中启用/禁用缩放
  7. Tomcat源码下载地址
  8. HDU-2686 Matrix 多进程DP
  9. 拓端tecdat|用R语言模拟随机服务排队系统
  10. 高中生入门计算机编程,高中生必看:入门学软件编程,看这三点...
  11. 浏览器 远程桌面连接到服务器,在浏览器中嵌入远程桌面
  12. python爬虫 requests使用代理ip
  13. lambda函数用法及注意事项(简单总结,有待补充)
  14. 灵感 | 设计平平无奇?试试这种方法!
  15. 谈谈eve-ng仿真模器
  16. windows10 C盘满了,怎么处理
  17. 计算机高级系统设置打不开,win7高级系统设置打不开的解决方法
  18. 【转】图灵机与计算问题(张江)
  19. SoftReference(利用软引用写的一个简单HashMap)
  20. 腾达u6无线网卡 linux,腾达U6驱动下载 腾达U6无线网卡驱动 v0.12.2.3 官方版 下载-脚本之家...

热门文章

  1. QList使用注意(浅拷贝 深拷贝)
  2. 【机器学习】经典的机器学习200道面试题(附参考答案)
  3. 利用Python爬虫爬取指定天猫店铺全店商品信息
  4. Android指定物理按键唤醒屏幕
  5. excel绘制回归直线
  6. 点击刷新按钮实现listview的数据刷新
  7. 基址变址寻址来实现暂存数据功能
  8. 服务器性能基准测试,性能基准测试
  9. linux 五种 IO 模型
  10. JavaWeb+Tomcat+Servlet使用<c:foreach>标签时,jsp等网页文件获取不到request域中的数据