LBP算法的研究及其实现
原文:http://blog.csdn.net/dujian996099665/article/details/8886576
一,原始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 matrices Mat src = _src.getMat(); // allocate memory for result _dst.create(src.rows-2, src.cols-2, CV_8UC1); Mat dst = _dst.getMat(); // zero the result matrix dst.setTo(0); cout<<"rows "<<src.rows<<" cols "<<src.cols<<endl; cout<<"channels "<<src.channels(); getchar(); // calculate patterns for(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; else tmp[0]=0; if(data[i*step+(j-1)]>data[i*step+j]) tmp[1]=1; else tmp[1]=0; if(data[(i+1)*step+(j-1)]>data[i*step+j]) tmp[2]=1; else tmp[2]=0; if (data[(i+1)*step+j]>data[i*step+j]) tmp[3]=1; else tmp[3]=0; if (data[(i+1)*step+(j+1)]>data[i*step+j]) tmp[4]=1; else tmp[4]=0; if(data[i*step+(j+1)]>data[i*step+j]) tmp[5]=1; else tmp[5]=0; if(data[(i-1)*step+(j+1)]>data[i*step+j]) tmp[6]=1; else tmp[6]=0; if(data[(i-1)*step+j]>data[i*step+j]) tmp[7]=1; else tmp[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
五、参考
opencv2.4.4中的facerec文档
http://blog.csdn.net/guoming0000/article/details/8022197
等等。
LBP算法的研究及其实现相关推荐
- opencv学习之(三)-LBP算法的研究及其实现
一,原始LBP算法 LBP的基本思想是对图像的像素和它局部周围像素进行对比后的结果进行求和.把这个像素作为中心,对相邻像素进行阈值比较.如果中心像素的亮度大于等于他的相邻像素,把他标记为1,否则标记为 ...
- 图像特征提取与描述_角点特征04:LBP算法+HOG特征算子
1.LBP算法 LBP(Local Binary Pattern)指局部二值模式,是一种用来描述图像局部特征的算子,LBP特征具有灰度不变性和旋转不变性等显著优点.它是由T. Ojala, M.Pie ...
- LBP算法的一些讲解
目标检测的图像特征提取之(二)LBP特征 zouxy09@qq.com http://blog.csdn.net/zouxy09 LBP(Local Binary Pattern,局部二值模式)是一种 ...
- OpenCV中基于LBP算法的人脸检测测试代码
下面是OpenCV 3.3中基于CascadeClassifier类的LBP算法实现的人脸检测,从结果上看,不如其它开源库效果好,如libfacedetection,可参考 https://blog. ...
- 阅读豆丁网----基于模型的混合多目标算法的研究
链接: 基于模型的混合多目标算法的研究 - 豆丁网 http://www.docin.com/p-1088777086.html (1) 研究背景意义 RM-MEDA(Regularity Mode ...
- 全基因组关联分析中上位性检测算法的研究
全基因组关联分析中上位性检测算法的研究 前言 这个项目主要是分享一些全基因组关联分析中上位性检测算法的研究经验,算是,怎么入门,写这么个东西,一是做总结,二是咱实验室估计以后还会有做这个方向的,备着吧 ...
- 更高效的PacBio长read纠错算法的研究
更高效的PacBio长read纠错算法的研究 更高效的PacBio长read纠错算法的研究 中文摘要 第三代PacBio测序技术的长read已越来越广泛的应用于各类测序项目中,而降低其约15%的错误率 ...
- 基于长短读长和参考基因组的组装错误检测算法的研究
基于长短读长和参考基因组的组装错误检测算法的研究 论文目录 致谢 第1-6页 摘要 第6-7页 ABSTRACT 第7-8页 序言 第9-13页 1 引言 第13-26页 1.1 基因测序项目介绍 第 ...
- K单体型重建算法的研究
K单体型重建算法的研究 王兆灿 [摘要]:随着新一代基因测序技术的飞速发展,以及单体型数据在人类遗传学等领域研究和应用的不断深入,对单体型数据的研究开始转向其他生物物种.由于测序技术的限制,通过生 ...
最新文章
- 如何用 Redis 解决海量重复提交问题
- JBDC更新计数行以及调用存储过程返回多个结果集
- 很久没有更新blog了,对不起每一位朋友。
- 通过JDBC连接取得数据库相关的元数据
- android 关于2.2版本之前的流量统计
- 蓝桥杯 ALGO-30算法训练 入学考试(01背包,动态规划)
- php抽象类初始化方法,php – 抽象类方法声明
- 声笔飞码6.00版使用指南
- 小白微信小程序开发入门经验总结,干货!生日惊喜可用
- vsscanf用法解析
- 基于html的项目的选题报告,团队项目-选题报告
- C# 关于winFrom控制网页的自动登录的问题(网页刷屏器的制作原理)
- windbg 查看结构体_Windbg入门实战讲解
- 深度评测阿里云、腾讯云和华为云
- 校招软件测试面试问题总结
- 孙正义与马云的故事:马云就是他心目中的那个人
- Django2.1 translation详解
- Android P(9.0) 证书加密算法变更
- win10无法打开匿名级安全令牌_Printer Spoofer:在Windows 10及Server 2019上滥用Impersonation权限...
- threeJS对光有反应的材质